--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/geometries/variant.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace append\r
+{\r
+\r
+template <typename Geometry, typename Point>\r
+struct append_no_action\r
+{\r
+ static inline void apply(Geometry& , Point const& ,\r
+ int = 0, int = 0)\r
+ {\r
+ }\r
+};\r
+\r
+template <typename Geometry, typename Point>\r
+struct append_point\r
+{\r
+ static inline void apply(Geometry& geometry, Point const& point,\r
+ int = 0, int = 0)\r
+ {\r
+ typename geometry::point_type<Geometry>::type copy;\r
+ geometry::detail::conversion::convert_point_to_point(point, copy);\r
+ traits::push_back<Geometry>::apply(geometry, copy);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry, typename Range>\r
+struct append_range\r
+{\r
+ typedef typename boost::range_value<Range>::type point_type;\r
+\r
+ static inline void apply(Geometry& geometry, Range const& range,\r
+ int = 0, int = 0)\r
+ {\r
+ for (typename boost::range_iterator<Range const>::type\r
+ it = boost::begin(range);\r
+ it != boost::end(range);\r
+ ++it)\r
+ {\r
+ append_point<Geometry, point_type>::apply(geometry, *it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon, typename Point>\r
+struct point_to_polygon\r
+{\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+\r
+ static inline void apply(Polygon& polygon, Point const& point,\r
+ int ring_index, int = 0)\r
+ {\r
+ if (ring_index == -1)\r
+ {\r
+ append_point<ring_type, Point>::apply(\r
+ exterior_ring(polygon), point);\r
+ }\r
+ else if (ring_index < int(num_interior_rings(polygon)))\r
+ {\r
+ append_point<ring_type, Point>::apply(\r
+ range::at(interior_rings(polygon), ring_index), point);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon, typename Range>\r
+struct range_to_polygon\r
+{\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+\r
+ static inline void apply(Polygon& polygon, Range const& range,\r
+ int ring_index, int = 0)\r
+ {\r
+ if (ring_index == -1)\r
+ {\r
+ append_range<ring_type, Range>::apply(\r
+ exterior_ring(polygon), range);\r
+ }\r
+ else if (ring_index < int(num_interior_rings(polygon)))\r
+ {\r
+ append_range<ring_type, Range>::apply(\r
+ range::at(interior_rings(polygon), ring_index), range);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::append\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+namespace splitted_dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry, typename Point>\r
+struct append_point\r
+ : detail::append::append_no_action<Geometry, Point>\r
+{};\r
+\r
+template <typename Geometry, typename Point>\r
+struct append_point<linestring_tag, Geometry, Point>\r
+ : detail::append::append_point<Geometry, Point>\r
+{};\r
+\r
+template <typename Geometry, typename Point>\r
+struct append_point<ring_tag, Geometry, Point>\r
+ : detail::append::append_point<Geometry, Point>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Point>\r
+struct append_point<polygon_tag, Polygon, Point>\r
+ : detail::append::point_to_polygon<Polygon, Point>\r
+{};\r
+\r
+\r
+template <typename Tag, typename Geometry, typename Range>\r
+struct append_range\r
+ : detail::append::append_no_action<Geometry, Range>\r
+{};\r
+\r
+template <typename Geometry, typename Range>\r
+struct append_range<linestring_tag, Geometry, Range>\r
+ : detail::append::append_range<Geometry, Range>\r
+{};\r
+\r
+template <typename Geometry, typename Range>\r
+struct append_range<ring_tag, Geometry, Range>\r
+ : detail::append::append_range<Geometry, Range>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Range>\r
+struct append_range<polygon_tag, Polygon, Range>\r
+ : detail::append::range_to_polygon<Polygon, Range>\r
+{};\r
+\r
+} // namespace splitted_dispatch\r
+\r
+\r
+// Default: append a range (or linestring or ring or whatever) to any geometry\r
+template\r
+<\r
+ typename Geometry, typename RangeOrPoint,\r
+ typename TagRangeOrPoint = typename tag<RangeOrPoint>::type\r
+>\r
+struct append\r
+ : splitted_dispatch::append_range<typename tag<Geometry>::type, Geometry, RangeOrPoint>\r
+{};\r
+\r
+// Specialization for point to append a point to any geometry\r
+template <typename Geometry, typename RangeOrPoint>\r
+struct append<Geometry, RangeOrPoint, point_tag>\r
+ : splitted_dispatch::append_point<typename tag<Geometry>::type, Geometry, RangeOrPoint>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace append\r
+{\r
+\r
+template <typename MultiGeometry, typename RangeOrPoint>\r
+struct append_to_multigeometry\r
+{\r
+ static inline void apply(MultiGeometry& multigeometry,\r
+ RangeOrPoint const& range_or_point,\r
+ int ring_index, int multi_index)\r
+ {\r
+\r
+ dispatch::append\r
+ <\r
+ typename boost::range_value<MultiGeometry>::type,\r
+ RangeOrPoint\r
+ >::apply(range::at(multigeometry, multi_index), range_or_point, ring_index);\r
+ }\r
+};\r
+\r
+}} // namespace detail::append\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+namespace splitted_dispatch\r
+{\r
+\r
+template <typename Geometry, typename Point>\r
+struct append_point<multi_point_tag, Geometry, Point>\r
+ : detail::append::append_point<Geometry, Point>\r
+{};\r
+\r
+template <typename Geometry, typename Range>\r
+struct append_range<multi_point_tag, Geometry, Range>\r
+ : detail::append::append_range<Geometry, Range>\r
+{};\r
+\r
+template <typename MultiGeometry, typename RangeOrPoint>\r
+struct append_point<multi_linestring_tag, MultiGeometry, RangeOrPoint>\r
+ : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>\r
+{};\r
+\r
+template <typename MultiGeometry, typename RangeOrPoint>\r
+struct append_range<multi_linestring_tag, MultiGeometry, RangeOrPoint>\r
+ : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>\r
+{};\r
+\r
+template <typename MultiGeometry, typename RangeOrPoint>\r
+struct append_point<multi_polygon_tag, MultiGeometry, RangeOrPoint>\r
+ : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>\r
+{};\r
+\r
+template <typename MultiGeometry, typename RangeOrPoint>\r
+struct append_range<multi_polygon_tag, MultiGeometry, RangeOrPoint>\r
+ : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>\r
+{};\r
+\r
+} // namespace splitted_dispatch\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct append\r
+{\r
+ template <typename RangeOrPoint>\r
+ static inline void apply(Geometry& geometry,\r
+ RangeOrPoint const& range_or_point,\r
+ int ring_index,\r
+ int multi_index)\r
+ {\r
+ concepts::check<Geometry>();\r
+ dispatch::append<Geometry, RangeOrPoint>::apply(geometry,\r
+ range_or_point,\r
+ ring_index,\r
+ multi_index);\r
+ }\r
+};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename RangeOrPoint>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ RangeOrPoint const& m_range_or_point;\r
+ int m_ring_index;\r
+ int m_multi_index;\r
+\r
+ visitor(RangeOrPoint const& range_or_point,\r
+ int ring_index,\r
+ int multi_index):\r
+ m_range_or_point(range_or_point),\r
+ m_ring_index(ring_index),\r
+ m_multi_index(multi_index)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ void operator()(Geometry& geometry) const\r
+ {\r
+ append<Geometry>::apply(geometry,\r
+ m_range_or_point,\r
+ m_ring_index,\r
+ m_multi_index);\r
+ }\r
+ };\r
+\r
+ template <typename RangeOrPoint>\r
+ static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& variant_geometry,\r
+ RangeOrPoint const& range_or_point,\r
+ int ring_index,\r
+ int multi_index)\r
+ {\r
+ boost::apply_visitor(\r
+ visitor<RangeOrPoint>(\r
+ range_or_point,\r
+ ring_index,\r
+ multi_index\r
+ ),\r
+ variant_geometry\r
+ );\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant;\r
+\r
+\r
+/*!\r
+\brief Appends one or more points to a linestring, ring, polygon, multi-geometry\r
+\ingroup append\r
+\tparam Geometry \tparam_geometry\r
+\tparam RangeOrPoint Either a range or a point, fullfilling Boost.Range concept or Boost.Geometry Point Concept\r
+\param geometry \param_geometry\r
+\param range_or_point The point or range to add\r
+\param ring_index The index of the ring in case of a polygon:\r
+ exterior ring (-1, the default) or interior ring index\r
+\param multi_index The index of the geometry to which the points are appended\r
+\r
+\qbk{[include reference/algorithms/append.qbk]}\r
+}\r
+ */\r
+template <typename Geometry, typename RangeOrPoint>\r
+inline void append(Geometry& geometry, RangeOrPoint const& range_or_point,\r
+ int ring_index = -1, int multi_index = 0)\r
+{\r
+ resolve_variant::append<Geometry>\r
+ ::apply(geometry, range_or_point, ring_index, multi_index);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/range/functions.hpp>\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>\r
+#include <boost/geometry/algorithms/detail/calculate_sum.hpp>\r
+// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>\r
+#include <boost/geometry/algorithms/detail/multi_sum.hpp>\r
+\r
+#include <boost/geometry/strategies/area.hpp>\r
+#include <boost/geometry/strategies/default_area_result.hpp>\r
+\r
+#include <boost/geometry/strategies/concepts/area_concept.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/order_as_direction.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace area\r
+{\r
+\r
+struct box_area\r
+{\r
+ template <typename Box, typename Strategy>\r
+ static inline typename coordinate_type<Box>::type\r
+ apply(Box const& box, Strategy const&)\r
+ {\r
+ // Currently only works for 2D Cartesian boxes\r
+ assert_dimension<Box, 2>();\r
+\r
+ return (get<max_corner, 0>(box) - get<min_corner, 0>(box))\r
+ * (get<max_corner, 1>(box) - get<min_corner, 1>(box));\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ iterate_direction Direction,\r
+ closure_selector Closure\r
+>\r
+struct ring_area\r
+{\r
+ template <typename Ring, typename Strategy>\r
+ static inline typename Strategy::return_type\r
+ apply(Ring const& ring, Strategy const& strategy)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Strategy>) );\r
+ assert_dimension<Ring, 2>();\r
+\r
+ // Ignore warning (because using static method sometimes) on strategy\r
+ boost::ignore_unused_variable_warning(strategy);\r
+\r
+ // An open ring has at least three points,\r
+ // A closed ring has at least four points,\r
+ // if not, there is no (zero) area\r
+ if (boost::size(ring)\r
+ < core_detail::closure::minimum_ring_size<Closure>::value)\r
+ {\r
+ return typename Strategy::return_type();\r
+ }\r
+\r
+ typedef typename reversible_view<Ring const, Direction>::type rview_type;\r
+ typedef typename closeable_view\r
+ <\r
+ rview_type const, Closure\r
+ >::type view_type;\r
+ typedef typename boost::range_iterator<view_type const>::type iterator_type;\r
+\r
+ rview_type rview(ring);\r
+ view_type view(rview);\r
+ typename Strategy::state_type state;\r
+ iterator_type it = boost::begin(view);\r
+ iterator_type end = boost::end(view);\r
+\r
+ for (iterator_type previous = it++;\r
+ it != end;\r
+ ++previous, ++it)\r
+ {\r
+ strategy.apply(*previous, *it, state);\r
+ }\r
+\r
+ return strategy.result(state);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::area\r
+\r
+\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct area : detail::calculate_null\r
+{\r
+ template <typename Strategy>\r
+ static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct area<Geometry, box_tag> : detail::area::box_area\r
+{};\r
+\r
+\r
+template <typename Ring>\r
+struct area<Ring, ring_tag>\r
+ : detail::area::ring_area\r
+ <\r
+ order_as_direction<geometry::point_order<Ring>::value>::value,\r
+ geometry::closure<Ring>::value\r
+ >\r
+{};\r
+\r
+\r
+template <typename Polygon>\r
+struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum\r
+{\r
+ template <typename Strategy>\r
+ static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)\r
+ {\r
+ return calculate_polygon_sum::apply<\r
+ typename Strategy::return_type,\r
+ detail::area::ring_area\r
+ <\r
+ order_as_direction<geometry::point_order<Polygon>::value>::value,\r
+ geometry::closure<Polygon>::value\r
+ >\r
+ >(polygon, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiGeometry>\r
+struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum\r
+{\r
+ template <typename Strategy>\r
+ static inline typename Strategy::return_type\r
+ apply(MultiGeometry const& multi, Strategy const& strategy)\r
+ {\r
+ return multi_sum::apply\r
+ <\r
+ typename Strategy::return_type,\r
+ area<typename boost::range_value<MultiGeometry>::type>\r
+ >(multi, strategy);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct area\r
+{\r
+ template <typename Strategy>\r
+ static inline typename Strategy::return_type apply(Geometry const& geometry,\r
+ Strategy const& strategy)\r
+ {\r
+ return dispatch::area<Geometry>::apply(geometry, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<typename Strategy::return_type>\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy): m_strategy(strategy) {}\r
+\r
+ template <typename Geometry>\r
+ typename Strategy::return_type operator()(Geometry const& geometry) const\r
+ {\r
+ return area<Geometry>::apply(geometry, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename Strategy::return_type\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{area}\r
+\ingroup area\r
+\details \details_calc{area}. \details_default_strategy\r
+\r
+The area algorithm calculates the surface area of all geometries having a surface, namely\r
+box, polygon, ring, multipolygon. The units are the square of the units used for the points\r
+defining the surface. If subject geometry is defined in meters, then area is calculated\r
+in square meters.\r
+\r
+The area calculation can be done in all three common coordinate systems, Cartesian, Spherical\r
+and Geographic as well.\r
+\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{area}\r
+\r
+\qbk{[include reference/algorithms/area.qbk]}\r
+\qbk{[heading Examples]}\r
+\qbk{[area] [area_output]}\r
+*/\r
+template <typename Geometry>\r
+inline typename default_area_result<Geometry>::type area(Geometry const& geometry)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ // TODO put this into a resolve_strategy stage\r
+ // (and take the return type from resolve_variant)\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef typename strategy::area::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type,\r
+ point_type\r
+ >::type strategy_type;\r
+\r
+ // detail::throw_on_empty_input(geometry);\r
+\r
+ return resolve_variant::area<Geometry>::apply(geometry, strategy_type());\r
+}\r
+\r
+/*!\r
+\brief \brief_calc{area} \brief_strategy\r
+\ingroup area\r
+\details \details_calc{area} \brief_strategy. \details_strategy_reasons\r
+\tparam Geometry \tparam_geometry\r
+\tparam Strategy \tparam_strategy{Area}\r
+\param geometry \param_geometry\r
+\param strategy \param_strategy{area}\r
+\return \return_calc{area}\r
+\r
+\qbk{distinguish,with strategy}\r
+\r
+\qbk{\r
+[include reference/algorithms/area.qbk]\r
+\r
+[heading Example]\r
+[area_with_strategy]\r
+[area_with_strategy_output]\r
+\r
+[heading Available Strategies]\r
+\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]\r
+\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)]\r
+}\r
+ */\r
+template <typename Geometry, typename Strategy>\r
+inline typename Strategy::return_type area(\r
+ Geometry const& geometry, Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ // detail::throw_on_empty_input(geometry);\r
+\r
+ return resolve_variant::area<Geometry>::apply(geometry, strategy);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Samuel Debionne, Grenoble, France.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/numeric/conversion/bounds.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_values.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/util/for_each_coordinate.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Assign a range of points to a linestring, ring or polygon\r
+\note The point-type of the range might be different from the point-type of the geometry\r
+\ingroup assign\r
+\tparam Geometry \tparam_geometry\r
+\tparam Range \tparam_range_point\r
+\param geometry \param_geometry\r
+\param range \param_range_point\r
+\r
+\qbk{\r
+[heading Notes]\r
+[note Assign automatically clears the geometry before assigning (use append if you don't want that)]\r
+[heading Example]\r
+[assign_points] [assign_points_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.append append]\r
+}\r
+ */\r
+template <typename Geometry, typename Range>\r
+inline void assign_points(Geometry& geometry, Range const& range)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ clear(geometry);\r
+ geometry::append(geometry, range, -1, 0);\r
+}\r
+\r
+\r
+/*!\r
+\brief assign to a box inverse infinite\r
+\details The assign_inverse function initialize a 2D or 3D box with large coordinates, the\r
+min corner is very large, the max corner is very small. This is a convenient starting point to\r
+collect the minimum bounding box of a geometry.\r
+\ingroup assign\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\r
+\qbk{\r
+[heading Example]\r
+[assign_inverse] [assign_inverse_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.make.make_inverse make_inverse]\r
+}\r
+ */\r
+template <typename Geometry>\r
+inline void assign_inverse(Geometry& geometry)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::assign_inverse\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::apply(geometry);\r
+}\r
+\r
+/*!\r
+\brief assign zero values to a box, point\r
+\ingroup assign\r
+\details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\r
+ */\r
+template <typename Geometry>\r
+inline void assign_zero(Geometry& geometry)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::assign_zero\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::apply(geometry);\r
+}\r
+\r
+/*!\r
+\brief Assign two coordinates to a geometry (usually a 2D point)\r
+\ingroup assign\r
+\tparam Geometry \tparam_geometry\r
+\tparam Type \tparam_numeric to specify the coordinates\r
+\param geometry \param_geometry\r
+\param c1 \param_x\r
+\param c2 \param_y\r
+\r
+\qbk{distinguish, 2 coordinate values}\r
+\qbk{\r
+[heading Example]\r
+[assign_2d_point] [assign_2d_point_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]\r
+}\r
+ */\r
+template <typename Geometry, typename Type>\r
+inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::assign\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ geometry::dimension<Geometry>::type::value\r
+ >::apply(geometry, c1, c2);\r
+}\r
+\r
+/*!\r
+\brief Assign three values to a geometry (usually a 3D point)\r
+\ingroup assign\r
+\tparam Geometry \tparam_geometry\r
+\tparam Type \tparam_numeric to specify the coordinates\r
+\param geometry \param_geometry\r
+\param c1 \param_x\r
+\param c2 \param_y\r
+\param c3 \param_z\r
+\r
+\qbk{distinguish, 3 coordinate values}\r
+\qbk{\r
+[heading Example]\r
+[assign_3d_point] [assign_3d_point_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]\r
+}\r
+ */\r
+template <typename Geometry, typename Type>\r
+inline void assign_values(Geometry& geometry,\r
+ Type const& c1, Type const& c2, Type const& c3)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::assign\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ geometry::dimension<Geometry>::type::value\r
+ >::apply(geometry, c1, c2, c3);\r
+}\r
+\r
+/*!\r
+\brief Assign four values to a geometry (usually a box or segment)\r
+\ingroup assign\r
+\tparam Geometry \tparam_geometry\r
+\tparam Type \tparam_numeric to specify the coordinates\r
+\param geometry \param_geometry\r
+\param c1 First coordinate (usually x1)\r
+\param c2 Second coordinate (usually y1)\r
+\param c3 Third coordinate (usually x2)\r
+\param c4 Fourth coordinate (usually y2)\r
+\r
+\qbk{distinguish, 4 coordinate values}\r
+ */\r
+template <typename Geometry, typename Type>\r
+inline void assign_values(Geometry& geometry,\r
+ Type const& c1, Type const& c2, Type const& c3, Type const& c4)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::assign\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ geometry::dimension<Geometry>::type::value\r
+ >::apply(geometry, c1, c2, c3, c4);\r
+}\r
+\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct assign\r
+{\r
+ static inline void\r
+ apply(Geometry1& geometry1, const Geometry2& geometry2)\r
+ {\r
+ concepts::check<Geometry1>();\r
+ concepts::check<Geometry2 const>();\r
+ concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();\r
+ \r
+ static bool const same_point_order\r
+ = point_order<Geometry1>::value == point_order<Geometry2>::value;\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ (same_point_order),\r
+ ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER,\r
+ (types<Geometry1, Geometry2>)\r
+ );\r
+ static bool const same_closure\r
+ = closure<Geometry1>::value == closure<Geometry2>::value;\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ (same_closure),\r
+ ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE,\r
+ (types<Geometry1, Geometry2>)\r
+ );\r
+ \r
+ dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);\r
+ }\r
+};\r
+ \r
+ \r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ \r
+ visitor(Geometry2 const& geometry2)\r
+ : m_geometry2(geometry2)\r
+ {}\r
+ \r
+ template <typename Geometry1>\r
+ result_type operator()(Geometry1& geometry1) const\r
+ {\r
+ return assign\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply\r
+ (geometry1, m_geometry2);\r
+ }\r
+ };\r
+ \r
+ static inline void\r
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry2), geometry1);\r
+ }\r
+};\r
+ \r
+ \r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ Geometry1& m_geometry1;\r
+ \r
+ visitor(Geometry1 const& geometry1)\r
+ : m_geometry1(geometry1)\r
+ {}\r
+ \r
+ template <typename Geometry2>\r
+ result_type operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return assign\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply\r
+ (m_geometry1, geometry2);\r
+ }\r
+ };\r
+ \r
+ static inline void\r
+ apply(Geometry1& geometry1,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry1), geometry2);\r
+ }\r
+};\r
+ \r
+ \r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>\r
+struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >\r
+{\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ template <typename Geometry1, typename Geometry2>\r
+ result_type operator()(\r
+ Geometry1& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return assign\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply\r
+ (geometry1, geometry2);\r
+ }\r
+ };\r
+ \r
+ static inline void\r
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry1, geometry2);\r
+ }\r
+};\r
+ \r
+} // namespace resolve_variant\r
+ \r
+\r
+/*!\r
+\brief Assigns one geometry to another geometry\r
+\details The assign algorithm assigns one geometry, e.g. a BOX, to another\r
+geometry, e.g. a RING. This only works if it is possible and applicable.\r
+\ingroup assign\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry (target)\r
+\param geometry2 \param_geometry (source)\r
+\r
+\qbk{\r
+[heading Example]\r
+[assign] [assign_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.convert convert]\r
+}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)\r
+{\r
+ resolve_variant::assign<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/geometries/box.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>\r
+struct box_loop\r
+{\r
+ typedef typename coordinate_type<BoxOut>::type coordinate_type;\r
+\r
+ static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)\r
+ {\r
+ coordinate_type d = distance;\r
+ set<C, D>(box_out, get<C, D>(box_in) + d);\r
+ box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);\r
+ }\r
+};\r
+\r
+template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>\r
+struct box_loop<BoxIn, BoxOut, T, C, N, N>\r
+{\r
+ static inline void apply(BoxIn const&, T const&, BoxOut&) {}\r
+};\r
+\r
+// Extends a box with the same amount in all directions\r
+template<typename BoxIn, typename BoxOut, typename T>\r
+inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)\r
+{\r
+ assert_dimension_equal<BoxIn, BoxOut>();\r
+\r
+ static const std::size_t N = dimension<BoxIn>::value;\r
+\r
+ box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);\r
+ box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);\r
+}\r
+\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Input,\r
+ typename Output,\r
+ typename TagIn = typename tag<Input>::type,\r
+ typename TagOut = typename tag<Output>::type\r
+>\r
+struct buffer: not_implemented<TagIn, TagOut>\r
+{};\r
+\r
+\r
+template <typename BoxIn, typename BoxOut>\r
+struct buffer<BoxIn, BoxOut, box_tag, box_tag>\r
+{\r
+ template <typename Distance>\r
+ static inline void apply(BoxIn const& box_in, Distance const& distance,\r
+ Distance const& , BoxOut& box_out)\r
+ {\r
+ detail::buffer::buffer_box(box_in, distance, box_out);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct buffer\r
+{\r
+ template <typename Distance, typename GeometryOut>\r
+ static inline void apply(Geometry const& geometry,\r
+ Distance const& distance,\r
+ Distance const& chord_length,\r
+ GeometryOut& out)\r
+ {\r
+ dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Distance, typename GeometryOut>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ Distance const& m_distance;\r
+ Distance const& m_chord_length;\r
+ GeometryOut& m_out;\r
+\r
+ visitor(Distance const& distance,\r
+ Distance const& chord_length,\r
+ GeometryOut& out)\r
+ : m_distance(distance),\r
+ m_chord_length(chord_length),\r
+ m_out(out)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ void operator()(Geometry const& geometry) const\r
+ {\r
+ buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);\r
+ }\r
+ };\r
+\r
+ template <typename Distance, typename GeometryOut>\r
+ static inline void apply(\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ Distance const& distance,\r
+ Distance const& chord_length,\r
+ GeometryOut& out\r
+ )\r
+ {\r
+ boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{buffer}\r
+\ingroup buffer\r
+\details \details_calc{buffer, \det_buffer}.\r
+\tparam Input \tparam_geometry\r
+\tparam Output \tparam_geometry\r
+\tparam Distance \tparam_numeric\r
+\param geometry_in \param_geometry\r
+\param geometry_out \param_geometry\r
+\param distance The distance to be used for the buffer\r
+\param chord_length (optional) The length of the chord's in the generated arcs around points or bends\r
+\r
+\qbk{[include reference/algorithms/buffer.qbk]}\r
+ */\r
+template <typename Input, typename Output, typename Distance>\r
+inline void buffer(Input const& geometry_in, Output& geometry_out,\r
+ Distance const& distance, Distance const& chord_length = -1)\r
+{\r
+ concepts::check<Input const>();\r
+ concepts::check<Output>();\r
+\r
+ resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out);\r
+}\r
+\r
+/*!\r
+\brief \brief_calc{buffer}\r
+\ingroup buffer\r
+\details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.\r
+\tparam Input \tparam_geometry\r
+\tparam Output \tparam_geometry\r
+\tparam Distance \tparam_numeric\r
+\param geometry \param_geometry\r
+\param distance The distance to be used for the buffer\r
+\param chord_length (optional) The length of the chord's in the generated arcs\r
+ around points or bends (RESERVED, NOT YET USED)\r
+\return \return_calc{buffer}\r
+ */\r
+template <typename Output, typename Input, typename Distance>\r
+Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)\r
+{\r
+ concepts::check<Input const>();\r
+ concepts::check<Output>();\r
+\r
+ Output geometry_out;\r
+\r
+ resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);\r
+\r
+ return geometry_out;\r
+}\r
+\r
+/*!\r
+\brief \brief_calc{buffer}\r
+\ingroup buffer\r
+\details \details_calc{buffer, \det_buffer}.\r
+\tparam GeometryIn \tparam_geometry\r
+\tparam MultiPolygon \tparam_geometry{MultiPolygon}\r
+\tparam DistanceStrategy A strategy defining distance (or radius)\r
+\tparam SideStrategy A strategy defining creation along sides\r
+\tparam JoinStrategy A strategy defining creation around convex corners\r
+\tparam EndStrategy A strategy defining creation at linestring ends\r
+\tparam PointStrategy A strategy defining creation around points\r
+\param geometry_in \param_geometry\r
+\param geometry_out output multi polygon (or std:: collection of polygons),\r
+ will contain a buffered version of the input geometry\r
+\param distance_strategy The distance strategy to be used\r
+\param side_strategy The side strategy to be used\r
+\param join_strategy The join strategy to be used\r
+\param end_strategy The end strategy to be used\r
+\param point_strategy The point strategy to be used\r
+\r
+\qbk{distinguish,with strategies}\r
+\qbk{[include reference/algorithms/buffer_with_strategies.qbk]}\r
+ */\r
+template\r
+<\r
+ typename GeometryIn,\r
+ typename MultiPolygon,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy\r
+>\r
+inline void buffer(GeometryIn const& geometry_in,\r
+ MultiPolygon& geometry_out,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy)\r
+{\r
+ typedef typename boost::range_value<MultiPolygon>::type polygon_type;\r
+ concepts::check<GeometryIn const>();\r
+ concepts::check<polygon_type>();\r
+\r
+ typedef typename point_type<GeometryIn>::type point_type;\r
+ typedef typename rescale_policy_type<point_type>::type rescale_policy_type;\r
+\r
+ geometry_out.clear();\r
+\r
+ if (geometry::is_empty(geometry_in))\r
+ {\r
+ // Then output geometry is kept empty as well\r
+ return;\r
+ }\r
+\r
+ model::box<point_type> box;\r
+ geometry::envelope(geometry_in, box);\r
+ geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));\r
+\r
+ rescale_policy_type rescale_policy\r
+ = boost::geometry::get_rescale_policy<rescale_policy_type>(box);\r
+\r
+ detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),\r
+ distance_strategy,\r
+ side_strategy,\r
+ join_strategy,\r
+ end_strategy,\r
+ point_strategy,\r
+ rescale_policy);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/exception.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/strategies/centroid.hpp>\r
+#include <boost/geometry/strategies/concepts/centroid_concept.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+\r
+#include <boost/geometry/util/for_each_coordinate.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)\r
+\r
+/*!\r
+\brief Centroid Exception\r
+\ingroup centroid\r
+\details The centroid_exception is thrown if the free centroid function is called with\r
+ geometries for which the centroid cannot be calculated. For example: a linestring\r
+ without points, a polygon without points, an empty multi-geometry.\r
+\qbk{\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.centroid the centroid function]\r
+}\r
+\r
+ */\r
+class centroid_exception : public geometry::exception\r
+{\r
+public:\r
+\r
+ /*!\r
+ \brief The default constructor\r
+ */\r
+ inline centroid_exception() {}\r
+\r
+ /*!\r
+ \brief Returns the explanatory string.\r
+ \return Pointer to a null-terminated string with explanatory information.\r
+ */\r
+ virtual char const* what() const throw()\r
+ {\r
+ return "Boost.Geometry Centroid calculation exception";\r
+ }\r
+};\r
+\r
+#endif\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace centroid\r
+{\r
+\r
+struct centroid_point\r
+{\r
+ template<typename Point, typename PointCentroid, typename Strategy>\r
+ static inline void apply(Point const& point, PointCentroid& centroid,\r
+ Strategy const&)\r
+ {\r
+ geometry::convert(point, centroid);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Indexed,\r
+ typename Point,\r
+ std::size_t Dimension = 0,\r
+ std::size_t DimensionCount = dimension<Indexed>::type::value\r
+>\r
+struct centroid_indexed_calculator\r
+{\r
+ typedef typename select_coordinate_type\r
+ <\r
+ Indexed, Point\r
+ >::type coordinate_type;\r
+ static inline void apply(Indexed const& indexed, Point& centroid)\r
+ {\r
+ coordinate_type const c1 = get<min_corner, Dimension>(indexed);\r
+ coordinate_type const c2 = get<max_corner, Dimension>(indexed);\r
+ coordinate_type m = c1 + c2;\r
+ coordinate_type const two = 2;\r
+ m /= two;\r
+\r
+ set<Dimension>(centroid, m);\r
+\r
+ centroid_indexed_calculator\r
+ <\r
+ Indexed, Point, Dimension + 1\r
+ >::apply(indexed, centroid);\r
+ }\r
+};\r
+\r
+\r
+template<typename Indexed, typename Point, std::size_t DimensionCount>\r
+struct centroid_indexed_calculator<Indexed, Point, DimensionCount, DimensionCount>\r
+{\r
+ static inline void apply(Indexed const& , Point& )\r
+ {\r
+ }\r
+};\r
+\r
+\r
+struct centroid_indexed\r
+{\r
+ template<typename Indexed, typename Point, typename Strategy>\r
+ static inline void apply(Indexed const& indexed, Point& centroid,\r
+ Strategy const&)\r
+ {\r
+ centroid_indexed_calculator\r
+ <\r
+ Indexed, Point\r
+ >::apply(indexed, centroid);\r
+ }\r
+};\r
+\r
+\r
+// There is one thing where centroid is different from e.g. within.\r
+// If the ring has only one point, it might make sense that\r
+// that point is the centroid.\r
+template<typename Point, typename Range>\r
+inline bool range_ok(Range const& range, Point& centroid)\r
+{\r
+ std::size_t const n = boost::size(range);\r
+ if (n > 1)\r
+ {\r
+ return true;\r
+ }\r
+ else if (n <= 0)\r
+ {\r
+#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)\r
+ throw centroid_exception();\r
+#else\r
+ return false;\r
+#endif\r
+ }\r
+ else // if (n == 1)\r
+ {\r
+ // Take over the first point in a "coordinate neutral way"\r
+ geometry::convert(*boost::begin(range), centroid);\r
+ return false;\r
+ }\r
+ //return true; // unreachable\r
+}\r
+\r
+/*!\r
+ \brief Calculate the centroid of a Ring or a Linestring.\r
+*/\r
+template <closure_selector Closure>\r
+struct centroid_range_state\r
+{\r
+ template<typename Ring, typename PointTransformer, typename Strategy>\r
+ static inline void apply(Ring const& ring,\r
+ PointTransformer const& transformer,\r
+ Strategy const& strategy,\r
+ typename Strategy::state_type& state)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+\r
+ typedef typename geometry::point_type<Ring const>::type point_type;\r
+ typedef typename closeable_view<Ring const, Closure>::type view_type;\r
+\r
+ typedef typename boost::range_iterator<view_type const>::type iterator_type;\r
+\r
+ view_type view(ring);\r
+ iterator_type it = boost::begin(view);\r
+ iterator_type end = boost::end(view);\r
+\r
+ if (it != end)\r
+ {\r
+ typename PointTransformer::result_type\r
+ previous_pt = transformer.apply(*it);\r
+\r
+ for ( ++it ; it != end ; ++it)\r
+ {\r
+ typename PointTransformer::result_type\r
+ pt = transformer.apply(*it);\r
+\r
+ strategy.apply(static_cast<point_type const&>(previous_pt),\r
+ static_cast<point_type const&>(pt),\r
+ state);\r
+\r
+ previous_pt = pt;\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+template <closure_selector Closure>\r
+struct centroid_range\r
+{\r
+ template<typename Range, typename Point, typename Strategy>\r
+ static inline bool apply(Range const& range, Point& centroid,\r
+ Strategy const& strategy)\r
+ {\r
+ if (range_ok(range, centroid))\r
+ {\r
+ // prepare translation transformer\r
+ translating_transformer<Range> transformer(*boost::begin(range));\r
+ \r
+ typename Strategy::state_type state;\r
+ centroid_range_state<Closure>::apply(range, transformer,\r
+ strategy, state);\r
+ \r
+ if ( strategy.result(state, centroid) )\r
+ {\r
+ // translate the result back\r
+ transformer.apply_reverse(centroid);\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Centroid of a polygon.\r
+ \note Because outer ring is clockwise, inners are counter clockwise,\r
+ triangle approach is OK and works for polygons with rings.\r
+*/\r
+struct centroid_polygon_state\r
+{\r
+ template<typename Polygon, typename PointTransformer, typename Strategy>\r
+ static inline void apply(Polygon const& poly,\r
+ PointTransformer const& transformer,\r
+ Strategy const& strategy,\r
+ typename Strategy::state_type& state)\r
+ {\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+ typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;\r
+\r
+ per_ring::apply(exterior_ring(poly), transformer, strategy, state);\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(poly);\r
+\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ per_ring::apply(*it, transformer, strategy, state);\r
+ }\r
+ }\r
+};\r
+\r
+struct centroid_polygon\r
+{\r
+ template<typename Polygon, typename Point, typename Strategy>\r
+ static inline bool apply(Polygon const& poly, Point& centroid,\r
+ Strategy const& strategy)\r
+ {\r
+ if (range_ok(exterior_ring(poly), centroid))\r
+ {\r
+ // prepare translation transformer\r
+ translating_transformer<Polygon>\r
+ transformer(*boost::begin(exterior_ring(poly)));\r
+ \r
+ typename Strategy::state_type state;\r
+ centroid_polygon_state::apply(poly, transformer, strategy, state);\r
+ \r
+ if ( strategy.result(state, centroid) )\r
+ {\r
+ // translate the result back\r
+ transformer.apply_reverse(centroid);\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Building block of a multi-point, to be used as Policy in the\r
+ more generec centroid_multi\r
+*/\r
+struct centroid_multi_point_state\r
+{\r
+ template <typename Point, typename PointTransformer, typename Strategy>\r
+ static inline void apply(Point const& point,\r
+ PointTransformer const& transformer,\r
+ Strategy const& strategy,\r
+ typename Strategy::state_type& state)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ strategy.apply(static_cast<Point const&>(transformer.apply(point)),\r
+ state);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Generic implementation which calls a policy to calculate the\r
+ centroid of the total of its single-geometries\r
+ \details The Policy is, in general, the single-version, with state. So\r
+ detail::centroid::centroid_polygon_state is used as a policy for this\r
+ detail::centroid::centroid_multi\r
+\r
+*/\r
+template <typename Policy>\r
+struct centroid_multi\r
+{\r
+ template <typename Multi, typename Point, typename Strategy>\r
+ static inline bool apply(Multi const& multi,\r
+ Point& centroid,\r
+ Strategy const& strategy)\r
+ {\r
+#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)\r
+ // If there is nothing in any of the ranges, it is not possible\r
+ // to calculate the centroid\r
+ if (geometry::is_empty(multi))\r
+ {\r
+ throw centroid_exception();\r
+ }\r
+#endif\r
+\r
+ // prepare translation transformer\r
+ translating_transformer<Multi> transformer(multi);\r
+\r
+ typename Strategy::state_type state;\r
+\r
+ for (typename boost::range_iterator<Multi const>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ Policy::apply(*it, transformer, strategy, state);\r
+ }\r
+\r
+ if ( strategy.result(state, centroid) )\r
+ {\r
+ // translate the result back\r
+ transformer.apply_reverse(centroid);\r
+ return true;\r
+ }\r
+ \r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+template <typename Algorithm>\r
+struct centroid_linear_areal\r
+{\r
+ template <typename Geometry, typename Point, typename Strategy>\r
+ static inline void apply(Geometry const& geom,\r
+ Point& centroid,\r
+ Strategy const& strategy)\r
+ {\r
+ if ( ! Algorithm::apply(geom, centroid, strategy) )\r
+ {\r
+ geometry::point_on_border(centroid, geom);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::centroid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct centroid: not_implemented<Tag>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct centroid<Geometry, point_tag>\r
+ : detail::centroid::centroid_point\r
+{};\r
+\r
+template <typename Box>\r
+struct centroid<Box, box_tag>\r
+ : detail::centroid::centroid_indexed\r
+{};\r
+\r
+template <typename Segment>\r
+struct centroid<Segment, segment_tag>\r
+ : detail::centroid::centroid_indexed\r
+{};\r
+\r
+template <typename Ring>\r
+struct centroid<Ring, ring_tag>\r
+ : detail::centroid::centroid_linear_areal\r
+ <\r
+ detail::centroid::centroid_range<geometry::closure<Ring>::value>\r
+ >\r
+{};\r
+\r
+template <typename Linestring>\r
+struct centroid<Linestring, linestring_tag>\r
+ : detail::centroid::centroid_linear_areal\r
+ <\r
+ detail::centroid::centroid_range<closed>\r
+ >\r
+{};\r
+\r
+template <typename Polygon>\r
+struct centroid<Polygon, polygon_tag>\r
+ : detail::centroid::centroid_linear_areal\r
+ <\r
+ detail::centroid::centroid_polygon\r
+ >\r
+{};\r
+\r
+template <typename MultiLinestring>\r
+struct centroid<MultiLinestring, multi_linestring_tag>\r
+ : detail::centroid::centroid_linear_areal\r
+ <\r
+ detail::centroid::centroid_multi\r
+ <\r
+ detail::centroid::centroid_range_state<closed>\r
+ >\r
+ >\r
+{};\r
+\r
+template <typename MultiPolygon>\r
+struct centroid<MultiPolygon, multi_polygon_tag>\r
+ : detail::centroid::centroid_linear_areal\r
+ <\r
+ detail::centroid::centroid_multi\r
+ <\r
+ detail::centroid::centroid_polygon_state\r
+ >\r
+ >\r
+{};\r
+\r
+template <typename MultiPoint>\r
+struct centroid<MultiPoint, multi_point_tag>\r
+ : detail::centroid::centroid_multi\r
+ <\r
+ detail::centroid::centroid_multi_point_state\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy {\r
+\r
+template <typename Geometry>\r
+struct centroid\r
+{\r
+ template <typename Point, typename Strategy>\r
+ static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)\r
+ {\r
+ dispatch::centroid<Geometry>::apply(geometry, out, strategy);\r
+ }\r
+\r
+ template <typename Point>\r
+ static inline void apply(Geometry const& geometry, Point& out, default_strategy)\r
+ {\r
+ typedef typename strategy::centroid::services::default_strategy\r
+ <\r
+ typename cs_tag<Geometry>::type,\r
+ typename tag_cast\r
+ <\r
+ typename tag<Geometry>::type,\r
+ pointlike_tag,\r
+ linear_tag,\r
+ areal_tag\r
+ >::type,\r
+ dimension<Geometry>::type::value,\r
+ Point,\r
+ Geometry\r
+ >::type strategy_type;\r
+\r
+ dispatch::centroid<Geometry>::apply(geometry, out, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct centroid\r
+{\r
+ template <typename Point, typename Strategy>\r
+ static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)\r
+ {\r
+ concepts::check_concepts_and_equal_dimensions<Point, Geometry const>();\r
+ resolve_strategy::centroid<Geometry>::apply(geometry, out, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Point, typename Strategy>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ Point& m_out;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Point& out, Strategy const& strategy)\r
+ : m_out(out), m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ void operator()(Geometry const& geometry) const\r
+ {\r
+ centroid<Geometry>::apply(geometry, m_out, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Point, typename Strategy>\r
+ static inline void\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ Point& out,\r
+ Strategy const& strategy)\r
+ {\r
+ boost::apply_visitor(visitor<Point, Strategy>(out, strategy), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{centroid} \brief_strategy\r
+\ingroup centroid\r
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_strategy_reasons\r
+\tparam Geometry \tparam_geometry\r
+\tparam Point \tparam_point\r
+\tparam Strategy \tparam_strategy{Centroid}\r
+\param geometry \param_geometry\r
+\param c \param_point \param_set{centroid}\r
+\param strategy \param_strategy{centroid}\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/centroid.qbk]}\r
+\qbk{[include reference/algorithms/centroid_strategies.qbk]}\r
+}\r
+\r
+*/\r
+template<typename Geometry, typename Point, typename Strategy>\r
+inline void centroid(Geometry const& geometry, Point& c,\r
+ Strategy const& strategy)\r
+{\r
+ resolve_variant::centroid<Geometry>::apply(geometry, c, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc{centroid}\r
+\ingroup centroid\r
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_default_strategy\r
+\tparam Geometry \tparam_geometry\r
+\tparam Point \tparam_point\r
+\param geometry \param_geometry\r
+\param c The calculated centroid will be assigned to this point reference\r
+\r
+\qbk{[include reference/algorithms/centroid.qbk]}\r
+\qbk{\r
+[heading Example]\r
+[centroid]\r
+[centroid_output]\r
+}\r
+ */\r
+template<typename Geometry, typename Point>\r
+inline void centroid(Geometry const& geometry, Point& c)\r
+{\r
+ geometry::centroid(geometry, c, default_strategy());\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc{centroid}\r
+\ingroup centroid\r
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}.\r
+\tparam Point \tparam_point\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{centroid}\r
+\r
+\qbk{[include reference/algorithms/centroid.qbk]}\r
+ */\r
+template<typename Point, typename Geometry>\r
+inline Point return_centroid(Geometry const& geometry)\r
+{\r
+ Point c;\r
+ geometry::centroid(geometry, c);\r
+ return c;\r
+}\r
+\r
+/*!\r
+\brief \brief_calc{centroid} \brief_strategy\r
+\ingroup centroid\r
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. \details_strategy_reasons\r
+\tparam Point \tparam_point\r
+\tparam Geometry \tparam_geometry\r
+\tparam Strategy \tparam_strategy{centroid}\r
+\param geometry \param_geometry\r
+\param strategy \param_strategy{centroid}\r
+\return \return_calc{centroid}\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/centroid.qbk]}\r
+\qbk{[include reference/algorithms/centroid_strategies.qbk]}\r
+ */\r
+template<typename Point, typename Geometry, typename Strategy>\r
+inline Point return_centroid(Geometry const& geometry, Strategy const& strategy)\r
+{\r
+ Point c;\r
+ geometry::centroid(geometry, c, strategy);\r
+ return c;\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP\r
+\r
+\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace clear\r
+{\r
+\r
+template <typename Geometry>\r
+struct collection_clear\r
+{\r
+ static inline void apply(Geometry& geometry)\r
+ {\r
+ traits::clear<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <typename Polygon>\r
+struct polygon_clear\r
+{\r
+ static inline void apply(Polygon& polygon)\r
+ {\r
+ traits::clear\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename traits::interior_mutable_type<Polygon>::type\r
+ >::type\r
+ >::apply(interior_rings(polygon));\r
+ traits::clear\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename traits::ring_mutable_type<Polygon>::type\r
+ >::type\r
+ >::apply(exterior_ring(polygon));\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct no_action\r
+{\r
+ static inline void apply(Geometry& )\r
+ {\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::clear\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type\r
+>\r
+struct clear: not_implemented<Tag>\r
+{};\r
+\r
+// Point/box/segment do not have clear. So specialize to do nothing.\r
+template <typename Geometry>\r
+struct clear<Geometry, point_tag>\r
+ : detail::clear::no_action<Geometry>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct clear<Geometry, box_tag>\r
+ : detail::clear::no_action<Geometry>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct clear<Geometry, segment_tag>\r
+ : detail::clear::no_action<Geometry>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct clear<Geometry, linestring_tag>\r
+ : detail::clear::collection_clear<Geometry>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct clear<Geometry, ring_tag>\r
+ : detail::clear::collection_clear<Geometry>\r
+{};\r
+\r
+\r
+// Polygon can (indirectly) use std for clear\r
+template <typename Polygon>\r
+struct clear<Polygon, polygon_tag>\r
+ : detail::clear::polygon_clear<Polygon>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct clear<Geometry, multi_tag>\r
+ : detail::clear::collection_clear<Geometry>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct clear\r
+{\r
+ static inline void apply(Geometry& geometry)\r
+ {\r
+ dispatch::clear<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct clear<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ template <typename Geometry>\r
+ inline void operator()(Geometry& geometry) const\r
+ {\r
+ clear<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline void apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)\r
+ {\r
+ boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Clears a linestring, ring or polygon (exterior+interiors) or multi*\r
+\details Generic function to clear a geometry. All points will be removed from the collection or collections\r
+ making up the geometry. In most cases this is equivalent to the .clear() method of a std::vector<...>. In\r
+ the case of a polygon, this clear functionality is automatically called for the exterior ring, and for the\r
+ interior ring collection. In the case of a point, boxes and segments, nothing will happen.\r
+\ingroup clear\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry which will be cleared\r
+\note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero"\r
+\r
+\qbk{[include reference/algorithms/clear.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline void clear(Geometry& geometry)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ resolve_variant::clear<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_array.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/for_each.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_values.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>\r
+#include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+// Silence warning C4512: assignment operator could not be generated\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127 4512)\r
+#endif\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace conversion\r
+{\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Box,\r
+ std::size_t Index,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct point_to_box\r
+{\r
+ static inline void apply(Point const& point, Box& box)\r
+ {\r
+ typedef typename coordinate_type<Box>::type coordinate_type;\r
+\r
+ set<Index, Dimension>(box,\r
+ boost::numeric_cast<coordinate_type>(get<Dimension>(point)));\r
+ point_to_box\r
+ <\r
+ Point, Box,\r
+ Index, Dimension + 1, DimensionCount\r
+ >::apply(point, box);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Box,\r
+ std::size_t Index,\r
+ std::size_t DimensionCount\r
+>\r
+struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>\r
+{\r
+ static inline void apply(Point const& , Box& )\r
+ {}\r
+};\r
+\r
+template <typename Box, typename Range, bool Close, bool Reverse>\r
+struct box_to_range\r
+{\r
+ static inline void apply(Box const& box, Range& range)\r
+ {\r
+ traits::resize<Range>::apply(range, Close ? 5 : 4);\r
+ assign_box_corners_oriented<Reverse>(box, range);\r
+ if (Close)\r
+ {\r
+ range::at(range, 4) = range::at(range, 0);\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Segment, typename Range>\r
+struct segment_to_range\r
+{\r
+ static inline void apply(Segment const& segment, Range& range)\r
+ {\r
+ traits::resize<Range>::apply(range, 2);\r
+\r
+ typename boost::range_iterator<Range>::type it = boost::begin(range);\r
+\r
+ assign_point_from_index<0>(segment, *it);\r
+ ++it;\r
+ assign_point_from_index<1>(segment, *it);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Range1,\r
+ typename Range2,\r
+ bool Reverse = false\r
+>\r
+struct range_to_range\r
+{\r
+ typedef typename reversible_view\r
+ <\r
+ Range1 const,\r
+ Reverse ? iterate_reverse : iterate_forward\r
+ >::type rview_type;\r
+ typedef typename closeable_view\r
+ <\r
+ rview_type const,\r
+ geometry::closure<Range1>::value\r
+ >::type view_type;\r
+\r
+ static inline void apply(Range1 const& source, Range2& destination)\r
+ {\r
+ geometry::clear(destination);\r
+\r
+ rview_type rview(source);\r
+\r
+ // We consider input always as closed, and skip last\r
+ // point for open output.\r
+ view_type view(rview);\r
+\r
+ typedef typename boost::range_size<Range1>::type size_type;\r
+ size_type n = boost::size(view);\r
+ if (geometry::closure<Range2>::value == geometry::open)\r
+ {\r
+ n--;\r
+ }\r
+\r
+ // If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()\r
+ // but ok, sice below it == end()\r
+\r
+ size_type i = 0;\r
+ for (typename boost::range_iterator<view_type const>::type it\r
+ = boost::begin(view);\r
+ it != boost::end(view) && i < n;\r
+ ++it, ++i)\r
+ {\r
+ geometry::append(destination, *it);\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Polygon1, typename Polygon2>\r
+struct polygon_to_polygon\r
+{\r
+ typedef range_to_range\r
+ <\r
+ typename geometry::ring_type<Polygon1>::type,\r
+ typename geometry::ring_type<Polygon2>::type,\r
+ geometry::point_order<Polygon1>::value\r
+ != geometry::point_order<Polygon2>::value\r
+ > per_ring;\r
+\r
+ static inline void apply(Polygon1 const& source, Polygon2& destination)\r
+ {\r
+ // Clearing managed per ring, and in the resizing of interior rings\r
+\r
+ per_ring::apply(geometry::exterior_ring(source),\r
+ geometry::exterior_ring(destination));\r
+\r
+ // Container should be resizeable\r
+ traits::resize\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename traits::interior_mutable_type<Polygon2>::type\r
+ >::type\r
+ >::apply(interior_rings(destination), num_interior_rings(source));\r
+\r
+ typename interior_return_type<Polygon1 const>::type\r
+ rings_source = interior_rings(source);\r
+ typename interior_return_type<Polygon2>::type\r
+ rings_dest = interior_rings(destination);\r
+\r
+ typename detail::interior_iterator<Polygon1 const>::type\r
+ it_source = boost::begin(rings_source);\r
+ typename detail::interior_iterator<Polygon2>::type\r
+ it_dest = boost::begin(rings_dest);\r
+\r
+ for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)\r
+ {\r
+ per_ring::apply(*it_source, *it_dest);\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Single, typename Multi, typename Policy>\r
+struct single_to_multi: private Policy\r
+{\r
+ static inline void apply(Single const& single, Multi& multi)\r
+ {\r
+ traits::resize<Multi>::apply(multi, 1);\r
+ Policy::apply(single, *boost::begin(multi));\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename Multi1, typename Multi2, typename Policy>\r
+struct multi_to_multi: private Policy\r
+{\r
+ static inline void apply(Multi1 const& multi1, Multi2& multi2)\r
+ {\r
+ traits::resize<Multi2>::apply(multi2, boost::size(multi1));\r
+\r
+ typename boost::range_iterator<Multi1 const>::type it1\r
+ = boost::begin(multi1);\r
+ typename boost::range_iterator<Multi2>::type it2\r
+ = boost::begin(multi2);\r
+\r
+ for (; it1 != boost::end(multi1); ++it1, ++it2)\r
+ {\r
+ Policy::apply(*it1, *it2);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::conversion\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,\r
+ typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,\r
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,\r
+ bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value\r
+ && !boost::is_array<Geometry1>::value\r
+>\r
+struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag,\r
+ std::size_t DimensionCount\r
+>\r
+struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>\r
+{\r
+ // Same geometry type -> copy whole geometry\r
+ static inline void apply(Geometry1 const& source, Geometry2& destination)\r
+ {\r
+ destination = source;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ std::size_t DimensionCount\r
+>\r
+struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>\r
+ : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Box1, typename Box2,\r
+ std::size_t DimensionCount\r
+>\r
+struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>\r
+ : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Segment1, typename Segment2,\r
+ std::size_t DimensionCount\r
+>\r
+struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>\r
+ : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>\r
+{};\r
+\r
+\r
+template <typename Segment, typename LineString, std::size_t DimensionCount>\r
+struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>\r
+ : detail::conversion::segment_to_range<Segment, LineString>\r
+{};\r
+\r
+\r
+template <typename Ring1, typename Ring2, std::size_t DimensionCount>\r
+struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>\r
+ : detail::conversion::range_to_range\r
+ <\r
+ Ring1,\r
+ Ring2,\r
+ geometry::point_order<Ring1>::value\r
+ != geometry::point_order<Ring2>::value\r
+ >\r
+{};\r
+\r
+template <typename LineString1, typename LineString2, std::size_t DimensionCount>\r
+struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>\r
+ : detail::conversion::range_to_range<LineString1, LineString2>\r
+{};\r
+\r
+template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>\r
+struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>\r
+ : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>\r
+{};\r
+\r
+template <typename Box, typename Ring>\r
+struct convert<Box, Ring, box_tag, ring_tag, 2, false>\r
+ : detail::conversion::box_to_range\r
+ <\r
+ Box,\r
+ Ring,\r
+ geometry::closure<Ring>::value == closed,\r
+ geometry::point_order<Ring>::value == counterclockwise\r
+ >\r
+{};\r
+\r
+\r
+template <typename Box, typename Polygon>\r
+struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>\r
+{\r
+ static inline void apply(Box const& box, Polygon& polygon)\r
+ {\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+\r
+ convert\r
+ <\r
+ Box, ring_type,\r
+ box_tag, ring_tag,\r
+ 2, false\r
+ >::apply(box, exterior_ring(polygon));\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, typename Box, std::size_t DimensionCount>\r
+struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>\r
+{\r
+ static inline void apply(Point const& point, Box& box)\r
+ {\r
+ detail::conversion::point_to_box\r
+ <\r
+ Point, Box, min_corner, 0, DimensionCount\r
+ >::apply(point, box);\r
+ detail::conversion::point_to_box\r
+ <\r
+ Point, Box, max_corner, 0, DimensionCount\r
+ >::apply(point, box);\r
+ }\r
+};\r
+\r
+\r
+template <typename Ring, typename Polygon, std::size_t DimensionCount>\r
+struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>\r
+{\r
+ static inline void apply(Ring const& ring, Polygon& polygon)\r
+ {\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+ convert\r
+ <\r
+ Ring, ring_type,\r
+ ring_tag, ring_tag,\r
+ DimensionCount, false\r
+ >::apply(ring, exterior_ring(polygon));\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon, typename Ring, std::size_t DimensionCount>\r
+struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>\r
+{\r
+ static inline void apply(Polygon const& polygon, Ring& ring)\r
+ {\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+\r
+ convert\r
+ <\r
+ ring_type, Ring,\r
+ ring_tag, ring_tag,\r
+ DimensionCount, false\r
+ >::apply(exterior_ring(polygon), ring);\r
+ }\r
+};\r
+\r
+\r
+// Dispatch for multi <-> multi, specifying their single-version as policy.\r
+// Note that, even if the multi-types are mutually different, their single\r
+// version types might be the same and therefore we call boost::is_same again\r
+\r
+template <typename Multi1, typename Multi2, std::size_t DimensionCount>\r
+struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>\r
+ : detail::conversion::multi_to_multi\r
+ <\r
+ Multi1,\r
+ Multi2,\r
+ convert\r
+ <\r
+ typename boost::range_value<Multi1>::type,\r
+ typename boost::range_value<Multi2>::type,\r
+ typename single_tag_of\r
+ <\r
+ typename tag<Multi1>::type\r
+ >::type,\r
+ typename single_tag_of\r
+ <\r
+ typename tag<Multi2>::type\r
+ >::type,\r
+ DimensionCount\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>\r
+struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>\r
+ : detail::conversion::single_to_multi\r
+ <\r
+ Single,\r
+ Multi,\r
+ convert\r
+ <\r
+ Single,\r
+ typename boost::range_value<Multi>::type,\r
+ typename tag<Single>::type,\r
+ typename single_tag_of\r
+ <\r
+ typename tag<Multi>::type\r
+ >::type,\r
+ DimensionCount,\r
+ false\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct convert\r
+{\r
+ static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)\r
+ {\r
+ concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();\r
+ dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ Geometry2& m_geometry2;\r
+\r
+ visitor(Geometry2& geometry2)\r
+ : m_geometry2(geometry2)\r
+ {}\r
+\r
+ template <typename Geometry1>\r
+ inline void operator()(Geometry1 const& geometry1) const\r
+ {\r
+ convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);\r
+ }\r
+ };\r
+\r
+ static inline void apply(\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2& geometry2\r
+ )\r
+ {\r
+ boost::apply_visitor(visitor(geometry2), geometry1);\r
+ }\r
+};\r
+\r
+}\r
+\r
+\r
+/*!\r
+\brief Converts one geometry to another geometry\r
+\details The convert algorithm converts one geometry, e.g. a BOX, to another\r
+geometry, e.g. a RING. This only works if it is possible and applicable.\r
+If the point-order is different, or the closure is different between two\r
+geometry types, it will be converted correctly by explicitly reversing the\r
+points or closing or opening the polygon rings.\r
+\ingroup convert\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry (source)\r
+\param geometry2 \param_geometry (target)\r
+\r
+\qbk{[include reference/algorithms/convert.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)\r
+{\r
+ resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+}\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP\r
+\r
+#include <boost/array.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/strategies/convex_hull.hpp>\r
+#include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+#include <boost/geometry/views/detail/range_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+#include <boost/geometry/algorithms/detail/as_range.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace convex_hull\r
+{\r
+\r
+template <order_selector Order, closure_selector Closure>\r
+struct hull_insert\r
+{\r
+\r
+ // Member template function (to avoid inconvenient declaration\r
+ // of output-iterator-type, from hull_to_geometry)\r
+ template <typename Geometry, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Geometry const& geometry,\r
+ OutputIterator out, Strategy const& strategy)\r
+ {\r
+ typename Strategy::state_type state;\r
+\r
+ strategy.apply(geometry, state);\r
+ strategy.result(state, out, Order == clockwise, Closure != open);\r
+ return out;\r
+ }\r
+};\r
+\r
+struct hull_to_geometry\r
+{\r
+ template <typename Geometry, typename OutputGeometry, typename Strategy>\r
+ static inline void apply(Geometry const& geometry, OutputGeometry& out,\r
+ Strategy const& strategy)\r
+ {\r
+ hull_insert\r
+ <\r
+ geometry::point_order<OutputGeometry>::value,\r
+ geometry::closure<OutputGeometry>::value\r
+ >::apply(geometry,\r
+ range::back_inserter(\r
+ // Handle linestring, ring and polygon the same:\r
+ detail::as_range\r
+ <\r
+ typename range_type<OutputGeometry>::type\r
+ >(out)), strategy);\r
+ }\r
+};\r
+\r
+}} // namespace detail::convex_hull\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct convex_hull\r
+ : detail::convex_hull::hull_to_geometry\r
+{};\r
+\r
+template <typename Box>\r
+struct convex_hull<Box, box_tag>\r
+{\r
+ template <typename OutputGeometry, typename Strategy>\r
+ static inline void apply(Box const& box, OutputGeometry& out,\r
+ Strategy const& )\r
+ {\r
+ static bool const Close\r
+ = geometry::closure<OutputGeometry>::value == closed;\r
+ static bool const Reverse\r
+ = geometry::point_order<OutputGeometry>::value == counterclockwise;\r
+\r
+ // A hull for boxes is trivial. Any strategy is (currently) skipped.\r
+ boost::array<typename point_type<Box>::type, 4> range;\r
+ geometry::detail::assign_box_corners_oriented<Reverse>(box, range);\r
+ geometry::append(out, range);\r
+ if (BOOST_GEOMETRY_CONDITION(Close))\r
+ {\r
+ geometry::append(out, *boost::begin(range));\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+template <order_selector Order, closure_selector Closure>\r
+struct convex_hull_insert\r
+ : detail::convex_hull::hull_insert<Order, Closure>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy {\r
+\r
+struct convex_hull\r
+{\r
+ template <typename Geometry, typename OutputGeometry, typename Strategy>\r
+ static inline void apply(Geometry const& geometry,\r
+ OutputGeometry& out,\r
+ Strategy const& strategy)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );\r
+ dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);\r
+ }\r
+\r
+ template <typename Geometry, typename OutputGeometry>\r
+ static inline void apply(Geometry const& geometry,\r
+ OutputGeometry& out,\r
+ default_strategy)\r
+ {\r
+ typedef typename strategy_convex_hull<\r
+ Geometry,\r
+ typename point_type<Geometry>::type\r
+ >::type strategy_type;\r
+\r
+ apply(geometry, out, strategy_type());\r
+ }\r
+};\r
+\r
+struct convex_hull_insert\r
+{\r
+ template <typename Geometry, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Geometry const& geometry,\r
+ OutputIterator& out,\r
+ Strategy const& strategy)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );\r
+\r
+ return dispatch::convex_hull_insert<\r
+ geometry::point_order<Geometry>::value,\r
+ geometry::closure<Geometry>::value\r
+ >::apply(geometry, out, strategy);\r
+ }\r
+\r
+ template <typename Geometry, typename OutputIterator>\r
+ static inline OutputIterator apply(Geometry const& geometry,\r
+ OutputIterator& out,\r
+ default_strategy)\r
+ {\r
+ typedef typename strategy_convex_hull<\r
+ Geometry,\r
+ typename point_type<Geometry>::type\r
+ >::type strategy_type;\r
+\r
+ return apply(geometry, out, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct convex_hull\r
+{\r
+ template <typename OutputGeometry, typename Strategy>\r
+ static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy)\r
+ {\r
+ concepts::check_concepts_and_equal_dimensions<\r
+ const Geometry,\r
+ OutputGeometry\r
+ >();\r
+\r
+ resolve_strategy::convex_hull::apply(geometry, out, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename OutputGeometry, typename Strategy>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ OutputGeometry& m_out;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(OutputGeometry& out, Strategy const& strategy)\r
+ : m_out(out), m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ void operator()(Geometry const& geometry) const\r
+ {\r
+ convex_hull<Geometry>::apply(geometry, m_out, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename OutputGeometry, typename Strategy>\r
+ static inline void\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ OutputGeometry& out,\r
+ Strategy const& strategy)\r
+ {\r
+ boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy), geometry);\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct convex_hull_insert\r
+{\r
+ template <typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy)\r
+ {\r
+ // Concept: output point type = point type of input geometry\r
+ concepts::check<Geometry const>();\r
+ concepts::check<typename point_type<Geometry>::type>();\r
+\r
+ return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename OutputIterator, typename Strategy>\r
+ struct visitor: boost::static_visitor<OutputIterator>\r
+ {\r
+ OutputIterator& m_out;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(OutputIterator& out, Strategy const& strategy)\r
+ : m_out(out), m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ OutputIterator operator()(Geometry const& geometry) const\r
+ {\r
+ return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ OutputIterator& out,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+template<typename Geometry, typename OutputGeometry, typename Strategy>\r
+inline void convex_hull(Geometry const& geometry,\r
+ OutputGeometry& out, Strategy const& strategy)\r
+{\r
+ if (geometry::is_empty(geometry))\r
+ {\r
+ // Leave output empty\r
+ return;\r
+ }\r
+\r
+ resolve_variant::convex_hull<Geometry>::apply(geometry, out, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc{convex hull}\r
+\ingroup convex_hull\r
+\details \details_calc{convex_hull,convex hull}.\r
+\tparam Geometry the input geometry type\r
+\tparam OutputGeometry the output geometry type\r
+\param geometry \param_geometry, input geometry\r
+\param hull \param_geometry \param_set{convex hull}\r
+\r
+\qbk{[include reference/algorithms/convex_hull.qbk]}\r
+ */\r
+template<typename Geometry, typename OutputGeometry>\r
+inline void convex_hull(Geometry const& geometry,\r
+ OutputGeometry& hull)\r
+{\r
+ geometry::convex_hull(geometry, hull, default_strategy());\r
+}\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace convex_hull\r
+{\r
+\r
+\r
+template<typename Geometry, typename OutputIterator, typename Strategy>\r
+inline OutputIterator convex_hull_insert(Geometry const& geometry,\r
+ OutputIterator out, Strategy const& strategy)\r
+{\r
+ return resolve_variant::convex_hull_insert<Geometry>\r
+ ::apply(geometry, out, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief Calculate the convex hull of a geometry, output-iterator version\r
+\ingroup convex_hull\r
+\tparam Geometry the input geometry type\r
+\tparam OutputIterator: an output-iterator\r
+\param geometry the geometry to calculate convex hull from\r
+\param out an output iterator outputing points of the convex hull\r
+\note This overloaded version outputs to an output iterator.\r
+In this case, nothing is known about its point-type or\r
+ about its clockwise order. Therefore, the input point-type\r
+ and order are copied\r
+\r
+ */\r
+template<typename Geometry, typename OutputIterator>\r
+inline OutputIterator convex_hull_insert(Geometry const& geometry,\r
+ OutputIterator out)\r
+{\r
+ return convex_hull_insert(geometry, out, default_strategy());\r
+}\r
+\r
+\r
+}} // namespace detail::convex_hull\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP\r
+\r
+\r
+#include <algorithm>\r
+#include <cstddef>\r
+#include <functional>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+#include <boost/geometry/algorithms/detail/multi_modify.hpp>\r
+#include <boost/geometry/util/order_as_direction.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace correct\r
+{\r
+\r
+template <typename Geometry>\r
+struct correct_nop\r
+{\r
+ static inline void apply(Geometry& )\r
+ {}\r
+};\r
+\r
+\r
+template <typename Box, std::size_t Dimension, std::size_t DimensionCount>\r
+struct correct_box_loop\r
+{\r
+ typedef typename coordinate_type<Box>::type coordinate_type;\r
+\r
+ static inline void apply(Box& box)\r
+ {\r
+ if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))\r
+ {\r
+ // Swap the coordinates\r
+ coordinate_type max_value = get<min_corner, Dimension>(box);\r
+ coordinate_type min_value = get<max_corner, Dimension>(box);\r
+ set<min_corner, Dimension>(box, min_value);\r
+ set<max_corner, Dimension>(box, max_value);\r
+ }\r
+\r
+ correct_box_loop\r
+ <\r
+ Box, Dimension + 1, DimensionCount\r
+ >::apply(box);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename Box, std::size_t DimensionCount>\r
+struct correct_box_loop<Box, DimensionCount, DimensionCount>\r
+{\r
+ static inline void apply(Box& )\r
+ {}\r
+\r
+};\r
+\r
+\r
+// Correct a box: make min/max correct\r
+template <typename Box>\r
+struct correct_box\r
+{\r
+\r
+ static inline void apply(Box& box)\r
+ {\r
+ // Currently only for Cartesian coordinates\r
+ // (or spherical without crossing dateline)\r
+ // Future version: adapt using strategies\r
+ correct_box_loop\r
+ <\r
+ Box, 0, dimension<Box>::type::value\r
+ >::apply(box);\r
+ }\r
+};\r
+\r
+\r
+// Close a ring, if not closed\r
+template <typename Ring, typename Predicate>\r
+struct correct_ring\r
+{\r
+ typedef typename point_type<Ring>::type point_type;\r
+ typedef typename coordinate_type<Ring>::type coordinate_type;\r
+\r
+ typedef typename strategy::area::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type,\r
+ point_type\r
+ >::type strategy_type;\r
+\r
+ typedef detail::area::ring_area\r
+ <\r
+ order_as_direction<geometry::point_order<Ring>::value>::value,\r
+ geometry::closure<Ring>::value\r
+ > ring_area_type;\r
+\r
+\r
+ static inline void apply(Ring& r)\r
+ {\r
+ // Check close-ness\r
+ if (boost::size(r) > 2)\r
+ {\r
+ // check if closed, if not, close it\r
+ bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));\r
+ closure_selector const s = geometry::closure<Ring>::value;\r
+\r
+ if (disjoint && (s == closed))\r
+ {\r
+ geometry::append(r, *boost::begin(r));\r
+ }\r
+ if (! disjoint && s != closed)\r
+ {\r
+ // Open it by removing last point\r
+ geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);\r
+ }\r
+ }\r
+ // Check area\r
+ Predicate predicate;\r
+ typedef typename default_area_result<Ring>::type area_result_type;\r
+ area_result_type const zero = area_result_type();\r
+ if (predicate(ring_area_type::apply(r, strategy_type()), zero))\r
+ {\r
+ std::reverse(boost::begin(r), boost::end(r));\r
+ }\r
+ }\r
+};\r
+\r
+// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all\r
+// inner rings counter clockwise (or vice versa depending on orientation)\r
+template <typename Polygon>\r
+struct correct_polygon\r
+{\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+ typedef typename default_area_result<Polygon>::type area_result_type;\r
+\r
+ static inline void apply(Polygon& poly)\r
+ {\r
+ correct_ring\r
+ <\r
+ ring_type,\r
+ std::less<area_result_type>\r
+ >::apply(exterior_ring(poly));\r
+\r
+ typename interior_return_type<Polygon>::type\r
+ rings = interior_rings(poly);\r
+ for (typename detail::interior_iterator<Polygon>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ correct_ring\r
+ <\r
+ ring_type,\r
+ std::greater<area_result_type>\r
+ >::apply(*it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::correct\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct correct: not_implemented<Tag>\r
+{};\r
+\r
+template <typename Point>\r
+struct correct<Point, point_tag>\r
+ : detail::correct::correct_nop<Point>\r
+{};\r
+\r
+template <typename LineString>\r
+struct correct<LineString, linestring_tag>\r
+ : detail::correct::correct_nop<LineString>\r
+{};\r
+\r
+template <typename Segment>\r
+struct correct<Segment, segment_tag>\r
+ : detail::correct::correct_nop<Segment>\r
+{};\r
+\r
+\r
+template <typename Box>\r
+struct correct<Box, box_tag>\r
+ : detail::correct::correct_box<Box>\r
+{};\r
+\r
+template <typename Ring>\r
+struct correct<Ring, ring_tag>\r
+ : detail::correct::correct_ring\r
+ <\r
+ Ring,\r
+ std::less<typename default_area_result<Ring>::type>\r
+ >\r
+{};\r
+\r
+template <typename Polygon>\r
+struct correct<Polygon, polygon_tag>\r
+ : detail::correct::correct_polygon<Polygon>\r
+{};\r
+\r
+\r
+template <typename MultiPoint>\r
+struct correct<MultiPoint, multi_point_tag>\r
+ : detail::correct::correct_nop<MultiPoint>\r
+{};\r
+\r
+\r
+template <typename MultiLineString>\r
+struct correct<MultiLineString, multi_linestring_tag>\r
+ : detail::correct::correct_nop<MultiLineString>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct correct<Geometry, multi_polygon_tag>\r
+ : detail::multi_modify\r
+ <\r
+ Geometry,\r
+ detail::correct::correct_polygon\r
+ <\r
+ typename boost::range_value<Geometry>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct correct\r
+{\r
+ static inline void apply(Geometry& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+ dispatch::correct<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ template <typename Geometry>\r
+ void operator()(Geometry& geometry) const\r
+ {\r
+ correct<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline void\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)\r
+ {\r
+ boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Corrects a geometry\r
+\details Corrects a geometry: all rings which are wrongly oriented with respect\r
+ to their expected orientation are reversed. To all rings which do not have a\r
+ closing point and are typed as they should have one, the first point is\r
+ appended. Also boxes can be corrected.\r
+\ingroup correct\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry which will be corrected if necessary\r
+\r
+\qbk{[include reference/algorithms/correct.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline void correct(Geometry& geometry)\r
+{\r
+ resolve_variant::correct<Geometry>::apply(geometry);\r
+}\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>\r
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace covered_by {\r
+\r
+struct use_point_in_geometry\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;\r
+ }\r
+};\r
+\r
+struct use_relate\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)\r
+ {\r
+ return Strategy::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+}} // namespace detail::covered_by\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag2 = typename tag<Geometry2>::type\r
+>\r
+struct covered_by\r
+ : not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+\r
+template <typename Point, typename Box>\r
+struct covered_by<Point, Box, point_tag, box_tag>\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)\r
+ {\r
+ ::boost::ignore_unused_variable_warning(strategy);\r
+ return strategy.apply(point, box);\r
+ }\r
+};\r
+\r
+template <typename Box1, typename Box2>\r
+struct covered_by<Box1, Box2, box_tag, box_tag>\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)\r
+ {\r
+ assert_dimension_equal<Box1, Box2>();\r
+ ::boost::ignore_unused_variable_warning(strategy);\r
+ return strategy.apply(box1, box2);\r
+ }\r
+};\r
+\r
+\r
+// P/P\r
+\r
+template <typename Point1, typename Point2>\r
+struct covered_by<Point1, Point2, point_tag, point_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+// P/L\r
+\r
+template <typename Point, typename Segment>\r
+struct covered_by<Point, Segment, point_tag, segment_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename Linestring>\r
+struct covered_by<Point, Linestring, point_tag, linestring_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename MultiLinestring>\r
+struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+// P/A\r
+\r
+template <typename Point, typename Ring>\r
+struct covered_by<Point, Ring, point_tag, ring_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename Polygon>\r
+struct covered_by<Point, Polygon, point_tag, polygon_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename MultiPolygon>\r
+struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>\r
+ : public detail::covered_by::use_point_in_geometry\r
+{};\r
+\r
+// L/L\r
+\r
+template <typename Linestring1, typename Linestring2>\r
+struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Linestring, typename MultiLinestring>\r
+struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename Linestring>\r
+struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring1, typename MultiLinestring2>\r
+struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+// L/A\r
+\r
+template <typename Linestring, typename Ring>\r
+struct covered_by<Linestring, Ring, linestring_tag, ring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename Ring>\r
+struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Linestring, typename Polygon>\r
+struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename Polygon>\r
+struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Linestring, typename MultiPolygon>\r
+struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename MultiPolygon>\r
+struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+// A/A\r
+\r
+template <typename Ring1, typename Ring2>\r
+struct covered_by<Ring1, Ring2, ring_tag, ring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Ring, typename Polygon>\r
+struct covered_by<Ring, Polygon, ring_tag, polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Polygon, typename Ring>\r
+struct covered_by<Polygon, Ring, polygon_tag, ring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Polygon1, typename Polygon2>\r
+struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Ring, typename MultiPolygon>\r
+struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiPolygon, typename Ring>\r
+struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename Polygon, typename MultiPolygon>\r
+struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiPolygon, typename Polygon>\r
+struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+template <typename MultiPolygon1, typename MultiPolygon2>\r
+struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>\r
+ : public detail::covered_by::use_relate\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy {\r
+\r
+struct covered_by\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ concepts::within::check\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,\r
+ Strategy\r
+ >();\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ assert_dimension_equal<Geometry1, Geometry2>();\r
+\r
+ return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,\r
+ geometry2,\r
+ strategy);\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ default_strategy)\r
+ {\r
+ typedef typename point_type<Geometry1>::type point_type1;\r
+ typedef typename point_type<Geometry2>::type point_type2;\r
+\r
+ typedef typename strategy::covered_by::services::default_strategy\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ typename tag<Geometry1>::type,\r
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type1>::type, spherical_tag\r
+ >::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type2>::type, spherical_tag\r
+ >::type,\r
+ Geometry1,\r
+ Geometry2\r
+ >::type strategy_type;\r
+\r
+ return covered_by::apply(geometry1, geometry2, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct covered_by\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return resolve_strategy::covered_by\r
+ ::apply(geometry1, geometry2, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)\r
+ : m_geometry2(geometry2), m_strategy(strategy) {}\r
+\r
+ template <typename Geometry1>\r
+ bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return covered_by<Geometry1, Geometry2>\r
+ ::apply(geometry1, m_geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)\r
+ : m_geometry1(geometry1), m_strategy(strategy) {}\r
+\r
+ template <typename Geometry2>\r
+ bool operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return covered_by<Geometry1, Geometry2>\r
+ ::apply(m_geometry1, geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);\r
+ }\r
+};\r
+\r
+template <\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct covered_by<\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+>\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy): m_strategy(strategy) {}\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ bool operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return covered_by<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_check12{is inside or on border}\r
+\ingroup covered_by\r
+\details \details_check12{covered_by, is inside or on border}.\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry which might be inside or on the border of the second geometry\r
+\param geometry2 \param_geometry which might cover the first geometry\r
+\return true if geometry1 is inside of or on the border of geometry2,\r
+ else false\r
+\note The default strategy is used for covered_by detection\r
+\r
+\qbk{[include reference/algorithms/covered_by.qbk]}\r
+\r
+ */\r
+template<typename Geometry1, typename Geometry2>\r
+inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::covered_by<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2, default_strategy());\r
+}\r
+\r
+/*!\r
+\brief \brief_check12{is inside or on border} \brief_strategy\r
+\ingroup covered_by\r
+\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry which might be inside or on the border of the second geometry\r
+\param geometry2 \param_geometry which might cover the first geometry\r
+\param strategy strategy to be used\r
+\return true if geometry1 is inside of or on the border of geometry2,\r
+ else false\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/covered_by.qbk]}\r
+\r
+*/\r
+template<typename Geometry1, typename Geometry2, typename Strategy>\r
+inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+{\r
+ return resolve_variant::covered_by<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/relate.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag2 = typename tag<Geometry2>::type\r
+>\r
+struct crosses\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_crosses_type,\r
+ Geometry1,\r
+ Geometry2\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+ template <typename Geometry1, typename Geometry2>\r
+ struct crosses\r
+ {\r
+ static inline bool\r
+ apply(\r
+ const Geometry1& geometry1,\r
+ const Geometry2& geometry2)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ \r
+ return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+ }\r
+ };\r
+ \r
+ \r
+ template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+ struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+ {\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ \r
+ visitor(Geometry2 const& geometry2)\r
+ : m_geometry2(geometry2)\r
+ {}\r
+ \r
+ template <typename Geometry1>\r
+ result_type operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return crosses\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, m_geometry2);\r
+ }\r
+ };\r
+ \r
+ static inline bool\r
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry2), geometry1);\r
+ }\r
+ };\r
+ \r
+ \r
+ template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+ struct crosses<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+ {\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ \r
+ visitor(Geometry1 const& geometry1)\r
+ : m_geometry1(geometry1)\r
+ {}\r
+ \r
+ template <typename Geometry2>\r
+ result_type operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return crosses\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(m_geometry1, geometry2);\r
+ }\r
+ };\r
+ \r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry1), geometry2);\r
+ }\r
+ };\r
+ \r
+ \r
+ template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>\r
+ struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >\r
+ {\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ template <typename Geometry1, typename Geometry2>\r
+ result_type operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return crosses\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2);\r
+ }\r
+ };\r
+ \r
+ static inline bool\r
+ apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,\r
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry1, geometry2);\r
+ }\r
+ };\r
+ \r
+} // namespace resolve_variant\r
+ \r
+ \r
+/*!\r
+\brief \brief_check2{crosses}\r
+\ingroup crosses\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_check2{crosses}\r
+\r
+\qbk{[include reference/algorithms/crosses.qbk]}\r
+*/\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP\r
+\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/flattening.hpp>\r
+#include <boost/geometry/algorithms/detail/result_inverse.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace detail\r
+{\r
+\r
+/*!\r
+\brief The solution of the inverse problem of geodesics on latlong coordinates,\r
+ Forsyth-Andoyer-Lambert type approximation with first order terms.\r
+\author See\r
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965\r
+ http://www.dtic.mil/docs/citations/AD0627893\r
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970\r
+ http://www.dtic.mil/docs/citations/AD703541\r
+*/\r
+\r
+template <typename CT, bool EnableDistance, bool EnableAzimuth>\r
+struct andoyer_inverse\r
+{\r
+ typedef result_inverse<CT> result_type;\r
+\r
+ template <typename T1, typename T2, typename Spheroid>\r
+ static inline result_type apply(T1 const& lon1,\r
+ T1 const& lat1,\r
+ T2 const& lon2,\r
+ T2 const& lat2,\r
+ Spheroid const& spheroid)\r
+ {\r
+ CT const c0 = CT(0);\r
+ CT const c1 = CT(1);\r
+ CT const pi = math::pi<CT>();\r
+\r
+ result_type result;\r
+\r
+ // coordinates in radians\r
+\r
+ if ( math::equals(lon1, lon2) && math::equals(lat1, lat2) )\r
+ {\r
+ result.set(c0, c0);\r
+ return result;\r
+ }\r
+\r
+ CT const dlon = lon2 - lon1;\r
+ CT const sin_dlon = sin(dlon);\r
+ CT const cos_dlon = cos(dlon);\r
+ CT const sin_lat1 = sin(lat1);\r
+ CT const cos_lat1 = cos(lat1);\r
+ CT const sin_lat2 = sin(lat2);\r
+ CT const cos_lat2 = cos(lat2);\r
+\r
+ // H,G,T = infinity if cos_d = 1 or cos_d = -1\r
+ // lat1 == +-90 && lat2 == +-90\r
+ // lat1 == lat2 && lon1 == lon2\r
+ CT cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon;\r
+ // on some platforms cos_d may be outside valid range\r
+ if (cos_d < -c1)\r
+ cos_d = -c1;\r
+ else if (cos_d > c1)\r
+ cos_d = c1;\r
+\r
+ CT const d = acos(cos_d); // [0, pi]\r
+ CT const sin_d = sin(d); // [-1, 1]\r
+ \r
+ CT const f = detail::flattening<CT>(spheroid);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )\r
+ {\r
+ CT const K = math::sqr(sin_lat1-sin_lat2);\r
+ CT const L = math::sqr(sin_lat1+sin_lat2);\r
+ CT const three_sin_d = CT(3) * sin_d;\r
+\r
+ CT const one_minus_cos_d = c1 - cos_d;\r
+ CT const one_plus_cos_d = c1 + cos_d;\r
+ // cos_d = 1 or cos_d = -1 means that the points are antipodal\r
+\r
+ CT const H = math::equals(one_minus_cos_d, c0) ?\r
+ c0 :\r
+ (d + three_sin_d) / one_minus_cos_d;\r
+ CT const G = math::equals(one_plus_cos_d, c0) ?\r
+ c0 :\r
+ (d - three_sin_d) / one_plus_cos_d;\r
+\r
+ CT const dd = -(f/CT(4))*(H*K+G*L);\r
+\r
+ CT const a = get_radius<0>(spheroid);\r
+\r
+ result.distance = a * (d + dd);\r
+ }\r
+ else\r
+ {\r
+ result.distance = c0;\r
+ }\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )\r
+ {\r
+ // sin_d = 0 <=> antipodal points\r
+ if (math::equals(sin_d, c0))\r
+ {\r
+ // T = inf\r
+ // dA = inf\r
+ // azimuth = -inf\r
+ if (lat1 <= lat2)\r
+ result.azimuth = c0;\r
+ else\r
+ result.azimuth = pi;\r
+ }\r
+ else\r
+ {\r
+ CT const c2 = CT(2);\r
+\r
+ CT A = c0;\r
+ CT U = c0;\r
+ if ( ! math::equals(cos_lat2, c0) )\r
+ {\r
+ CT const tan_lat2 = sin_lat2/cos_lat2;\r
+ CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon;\r
+ A = atan2(sin_dlon, M);\r
+ CT const sin_2A = sin(c2*A);\r
+ U = (f/ c2)*math::sqr(cos_lat1)*sin_2A;\r
+ }\r
+\r
+ CT V = c0;\r
+ if ( ! math::equals(cos_lat1, c0) )\r
+ {\r
+ CT const tan_lat1 = sin_lat1/cos_lat1;\r
+ CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon;\r
+ CT const B = atan2(sin_dlon, N);\r
+ CT const sin_2B = sin(c2*B);\r
+ V = (f/ c2)*math::sqr(cos_lat2)*sin_2B;\r
+ }\r
+\r
+ CT const T = d / sin_d;\r
+ CT const dA = V*T-U;\r
+\r
+ result.azimuth = A - dA;\r
+\r
+ // even with sin_d == 0 checked above if the second point\r
+ // is somewhere in the antipodal area T may still be great\r
+ // therefore dA may be great and the resulting azimuth\r
+ // may be some more or less arbitrary angle\r
+ if (A >= c0) // A indicates Eastern hemisphere\r
+ {\r
+ if (dA >= c0) // A altered towards 0\r
+ {\r
+ if ((result.azimuth) < c0)\r
+ result.azimuth = c0;\r
+ }\r
+ else // dA < 0, A altered towards pi\r
+ {\r
+ if (result.azimuth > pi)\r
+ result.azimuth = pi;\r
+ }\r
+ }\r
+ else // A indicates Western hemisphere\r
+ {\r
+ if (dA <= c0) // A altered towards 0\r
+ {\r
+ if (result.azimuth > c0)\r
+ result.azimuth = c0;\r
+ }\r
+ else // dA > 0, A altered towards -pi\r
+ {\r
+ CT const minus_pi = -pi;\r
+ if ((result.azimuth) < minus_pi)\r
+ result.azimuth = minus_pi;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ result.azimuth = c0;\r
+ }\r
+\r
+ return result;\r
+ }\r
+};\r
+\r
+}}} // namespace boost::geometry::detail\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP\r
+\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/add_const_if_c.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename GeometryTag, typename Geometry, typename Range, bool IsConst>\r
+struct as_range\r
+{\r
+ static inline typename add_const_if_c<IsConst, Range>::type& get(\r
+ typename add_const_if_c<IsConst, Geometry>::type& input)\r
+ {\r
+ return input;\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry, typename Range, bool IsConst>\r
+struct as_range<polygon_tag, Geometry, Range, IsConst>\r
+{\r
+ static inline typename add_const_if_c<IsConst, Range>::type& get(\r
+ typename add_const_if_c<IsConst, Geometry>::type& input)\r
+ {\r
+ return exterior_ring(input);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+// Will probably be replaced by the more generic "view_as", therefore in detail\r
+namespace detail\r
+{\r
+\r
+/*!\r
+\brief Function getting either the range (ring, linestring) itself\r
+or the outer ring (polygon)\r
+\details Utility to handle polygon's outer ring as a range\r
+\ingroup utility\r
+*/\r
+template <typename Range, typename Geometry>\r
+inline Range& as_range(Geometry& input)\r
+{\r
+ return dispatch::as_range\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ Range,\r
+ false\r
+ >::get(input);\r
+}\r
+\r
+\r
+/*!\r
+\brief Function getting either the range (ring, linestring) itself\r
+or the outer ring (polygon), const version\r
+\details Utility to handle polygon's outer ring as a range\r
+\ingroup utility\r
+*/\r
+template <typename Range, typename Geometry>\r
+inline Range const& as_range(Geometry const& input)\r
+{\r
+ return dispatch::as_range\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ Range,\r
+ true\r
+ >::get(input);\r
+}\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_values.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+// Note: this is moved to namespace detail because the names and parameter orders\r
+// are not yet 100% clear.\r
+\r
+/*!\r
+\brief Assign the four points of a 2D box\r
+\ingroup assign\r
+\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT\r
+ so this is how it is implemented.\r
+\tparam Box \tparam_box\r
+\tparam Point \tparam_point\r
+\param box \param_box\r
+\param lower_left point being assigned to lower left coordinates of the box\r
+\param lower_right point being assigned to lower right coordinates of the box\r
+\param upper_left point being assigned to upper left coordinates of the box\r
+\param upper_right point being assigned to upper right coordinates of the box\r
+\r
+\qbk{\r
+[heading Example]\r
+[assign_box_corners] [assign_box_corners_output]\r
+}\r
+*/\r
+template <typename Box, typename Point>\r
+inline void assign_box_corners(Box const& box,\r
+ Point& lower_left, Point& lower_right,\r
+ Point& upper_left, Point& upper_right)\r
+{\r
+ concepts::check<Box const>();\r
+ concepts::check<Point>();\r
+\r
+ detail::assign::assign_box_2d_corner\r
+ <min_corner, min_corner>(box, lower_left);\r
+ detail::assign::assign_box_2d_corner\r
+ <max_corner, min_corner>(box, lower_right);\r
+ detail::assign::assign_box_2d_corner\r
+ <min_corner, max_corner>(box, upper_left);\r
+ detail::assign::assign_box_2d_corner\r
+ <max_corner, max_corner>(box, upper_right);\r
+}\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+\r
+template <bool Reverse, typename Box, typename Range>\r
+inline void assign_box_corners_oriented(Box const& box, Range& corners)\r
+{\r
+ if (Reverse)\r
+ {\r
+ // make counterclockwise ll,lr,ur,ul\r
+ assign_box_corners(box,\r
+ range::at(corners, 0), range::at(corners, 1),\r
+ range::at(corners, 3), range::at(corners, 2));\r
+ }\r
+ else\r
+ {\r
+ // make clockwise ll,ul,ur,lr\r
+ assign_box_corners(box,\r
+ range::at(corners, 0), range::at(corners, 3),\r
+ range::at(corners, 1), range::at(corners, 2));\r
+ }\r
+}\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_values.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+/*!\r
+\brief Assign a box or segment with the value of a point\r
+\ingroup assign\r
+\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)\r
+ or which point of segment (0/1)\r
+\tparam Point \tparam_point\r
+\tparam Geometry \tparam_box_or_segment\r
+\param point \param_point\r
+\param geometry \param_box_or_segment\r
+\r
+\qbk{\r
+[heading Example]\r
+[assign_point_to_index] [assign_point_to_index_output]\r
+}\r
+*/\r
+template <std::size_t Index, typename Geometry, typename Point>\r
+inline void assign_point_to_index(Point const& point, Geometry& geometry)\r
+{\r
+ concepts::check<Point const>();\r
+ concepts::check<Geometry>();\r
+\r
+ detail::assign::assign_point_to_index\r
+ <\r
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value\r
+ >::apply(point, geometry);\r
+}\r
+\r
+\r
+/*!\r
+\brief Assign a point with a point of a box or segment\r
+\ingroup assign\r
+\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)\r
+ or which point of segment (0/1)\r
+\tparam Geometry \tparam_box_or_segment\r
+\tparam Point \tparam_point\r
+\param geometry \param_box_or_segment\r
+\param point \param_point\r
+\r
+\qbk{\r
+[heading Example]\r
+[assign_point_from_index] [assign_point_from_index_output]\r
+}\r
+*/\r
+template <std::size_t Index, typename Point, typename Geometry>\r
+inline void assign_point_from_index(Geometry const& geometry, Point& point)\r
+{\r
+ concepts::check<Geometry const>();\r
+ concepts::check<Point>();\r
+\r
+ detail::assign::assign_point_from_index\r
+ <\r
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value\r
+ >::apply(geometry, point);\r
+}\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/numeric/conversion/bounds.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+#include <boost/geometry/util/for_each_coordinate.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace assign\r
+{\r
+\r
+\r
+template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>\r
+struct initialize\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)\r
+ {\r
+ geometry::set<Index, Dimension>(box, value);\r
+ initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t Index, std::size_t DimensionCount>\r
+struct initialize<Index, DimensionCount, DimensionCount>\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Box&, typename coordinate_type<Box>::type const&)\r
+ {}\r
+};\r
+\r
+\r
+struct assign_zero_point\r
+{\r
+ template <typename Point>\r
+ static inline void apply(Point& point)\r
+ {\r
+ geometry::assign_value(point, 0);\r
+ }\r
+};\r
+\r
+\r
+struct assign_inverse_box_or_segment\r
+{\r
+\r
+ template <typename BoxOrSegment>\r
+ static inline void apply(BoxOrSegment& geometry)\r
+ {\r
+ typedef typename point_type<BoxOrSegment>::type point_type;\r
+ typedef typename coordinate_type<point_type>::type bound_type;\r
+\r
+ initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(\r
+ geometry, boost::numeric::bounds<bound_type>::highest()\r
+ );\r
+ initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(\r
+ geometry, boost::numeric::bounds<bound_type>::lowest()\r
+ );\r
+ }\r
+};\r
+\r
+\r
+struct assign_zero_box_or_segment\r
+{\r
+ template <typename BoxOrSegment>\r
+ static inline void apply(BoxOrSegment& geometry)\r
+ {\r
+ typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;\r
+\r
+ initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(\r
+ geometry, coordinate_type()\r
+ );\r
+ initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(\r
+ geometry, coordinate_type()\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ std::size_t Corner1, std::size_t Corner2,\r
+ typename Box, typename Point\r
+>\r
+inline void assign_box_2d_corner(Box const& box, Point& point)\r
+{\r
+ // Be sure both are 2-Dimensional\r
+ assert_dimension<Box, 2>();\r
+ assert_dimension<Point, 2>();\r
+\r
+ // Copy coordinates\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));\r
+ geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));\r
+}\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Geometry, typename Point,\r
+ std::size_t Index,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct assign_point_to_index\r
+{\r
+\r
+ static inline void apply(Point const& point, Geometry& geometry)\r
+ {\r
+ geometry::set<Index, Dimension>(geometry, boost::numeric_cast\r
+ <\r
+ typename coordinate_type<Geometry>::type\r
+ >(geometry::get<Dimension>(point)));\r
+\r
+ assign_point_to_index\r
+ <\r
+ Geometry, Point, Index, Dimension + 1, DimensionCount\r
+ >::apply(point, geometry);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry, typename Point,\r
+ std::size_t Index,\r
+ std::size_t DimensionCount\r
+>\r
+struct assign_point_to_index\r
+ <\r
+ Geometry, Point,\r
+ Index,\r
+ DimensionCount, DimensionCount\r
+ >\r
+{\r
+ static inline void apply(Point const& , Geometry& )\r
+ {\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry, typename Point,\r
+ std::size_t Index,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct assign_point_from_index\r
+{\r
+\r
+ static inline void apply(Geometry const& geometry, Point& point)\r
+ {\r
+ geometry::set<Dimension>( point, boost::numeric_cast\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >(geometry::get<Index, Dimension>(geometry)));\r
+\r
+ assign_point_from_index\r
+ <\r
+ Geometry, Point, Index, Dimension + 1, DimensionCount\r
+ >::apply(geometry, point);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry, typename Point,\r
+ std::size_t Index,\r
+ std::size_t DimensionCount\r
+>\r
+struct assign_point_from_index\r
+ <\r
+ Geometry, Point,\r
+ Index,\r
+ DimensionCount, DimensionCount\r
+ >\r
+{\r
+ static inline void apply(Geometry const&, Point&)\r
+ {\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct assign_2d_box_or_segment\r
+{\r
+ typedef typename coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ // Here we assign 4 coordinates to a box of segment\r
+ // -> Most logical is: x1,y1,x2,y2\r
+ // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)\r
+\r
+ template <typename Type>\r
+ static inline void apply(Geometry& geometry,\r
+ Type const& x1, Type const& y1, Type const& x2, Type const& y2)\r
+ {\r
+ geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));\r
+ geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));\r
+ geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));\r
+ geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::assign\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>\r
+struct assign\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+template <typename Point>\r
+struct assign<point_tag, Point, 2>\r
+{\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ template <typename T>\r
+ static inline void apply(Point& point, T const& c1, T const& c2)\r
+ {\r
+ set<0>(point, boost::numeric_cast<coordinate_type>(c1));\r
+ set<1>(point, boost::numeric_cast<coordinate_type>(c2));\r
+ }\r
+};\r
+\r
+template <typename Point>\r
+struct assign<point_tag, Point, 3>\r
+{\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ template <typename T>\r
+ static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)\r
+ {\r
+ set<0>(point, boost::numeric_cast<coordinate_type>(c1));\r
+ set<1>(point, boost::numeric_cast<coordinate_type>(c2));\r
+ set<2>(point, boost::numeric_cast<coordinate_type>(c3));\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct assign<box_tag, Box, 2>\r
+ : detail::assign::assign_2d_box_or_segment<Box>\r
+{};\r
+\r
+template <typename Segment>\r
+struct assign<segment_tag, Segment, 2>\r
+ : detail::assign::assign_2d_box_or_segment<Segment>\r
+{};\r
+\r
+\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct assign_zero {};\r
+\r
+\r
+template <typename Point>\r
+struct assign_zero<point_tag, Point>\r
+ : detail::assign::assign_zero_point\r
+{};\r
+\r
+template <typename Box>\r
+struct assign_zero<box_tag, Box>\r
+ : detail::assign::assign_zero_box_or_segment\r
+{};\r
+\r
+template <typename Segment>\r
+struct assign_zero<segment_tag, Segment>\r
+ : detail::assign::assign_zero_box_or_segment\r
+{};\r
+\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct assign_inverse {};\r
+\r
+template <typename Box>\r
+struct assign_inverse<box_tag, Box>\r
+ : detail::assign::assign_inverse_box_or_segment\r
+{};\r
+\r
+template <typename Segment>\r
+struct assign_inverse<segment_tag, Segment>\r
+ : detail::assign::assign_inverse_box_or_segment\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// An azimuth is an angle between a vector/segment from origin to a point of\r
+// interest and a reference vector. Typically north-based azimuth is used.\r
+// North direction is used as a reference, angle is measured clockwise\r
+// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS\r
+// the reference vector is Y axis, angle is measured clockwise.\r
+// http://en.wikipedia.org/wiki/Azimuth\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch\r
+{\r
+\r
+template <typename ReturnType, typename Tag>\r
+struct azimuth\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+template <typename ReturnType>\r
+struct azimuth<ReturnType, geographic_tag>\r
+{\r
+ template <typename P1, typename P2, typename Spheroid>\r
+ static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)\r
+ {\r
+ return geometry::detail::vincenty_inverse<ReturnType, false, true>().apply\r
+ ( get_as_radian<0>(p1), get_as_radian<1>(p1),\r
+ get_as_radian<0>(p2), get_as_radian<1>(p2),\r
+ spheroid ).azimuth;\r
+ }\r
+\r
+ template <typename P1, typename P2>\r
+ static inline ReturnType apply(P1 const& p1, P2 const& p2)\r
+ {\r
+ return apply(p1, p2, srs::spheroid<ReturnType>());\r
+ }\r
+};\r
+\r
+template <typename ReturnType>\r
+struct azimuth<ReturnType, spherical_equatorial_tag>\r
+{\r
+ template <typename P1, typename P2, typename Sphere>\r
+ static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)\r
+ {\r
+ // http://williams.best.vwh.net/avform.htm#Crs\r
+ ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);\r
+ ReturnType cos_p2lat = cos(get_as_radian<1>(p2));\r
+\r
+ // An optimization which should kick in often for Boxes\r
+ //if ( math::equals(dlon, ReturnType(0)) )\r
+ //if ( get<0>(p1) == get<0>(p2) )\r
+ //{\r
+ // return - sin(get_as_radian<1>(p1)) * cos_p2lat);\r
+ //}\r
+\r
+ // "An alternative formula, not requiring the pre-computation of d"\r
+ // In the formula below dlon is used as "d"\r
+ return atan2(sin(dlon) * cos_p2lat,\r
+ cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))\r
+ - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));\r
+ }\r
+\r
+ template <typename P1, typename P2>\r
+ static inline ReturnType apply(P1 const& p1, P2 const& p2)\r
+ {\r
+ return apply(p1, p2, 0); // dummy model\r
+ }\r
+};\r
+\r
+template <typename ReturnType>\r
+struct azimuth<ReturnType, spherical_polar_tag>\r
+ : azimuth<ReturnType, spherical_equatorial_tag>\r
+{};\r
+\r
+template <typename ReturnType>\r
+struct azimuth<ReturnType, cartesian_tag>\r
+{\r
+ template <typename P1, typename P2, typename Plane>\r
+ static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/)\r
+ {\r
+ ReturnType x = get<0>(p2) - get<0>(p1);\r
+ ReturnType y = get<1>(p2) - get<1>(p1);\r
+\r
+ // NOTE: azimuth 0 is at Y axis, increasing right\r
+ // as in spherical/geographic where 0 is at North axis\r
+ return atan2(x, y);\r
+ }\r
+\r
+ template <typename P1, typename P2>\r
+ static inline ReturnType apply(P1 const& p1, P2 const& p2)\r
+ {\r
+ return apply(p1, p2, 0); // dummy model\r
+ }\r
+};\r
+\r
+} // detail_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+/// Calculate azimuth between two points.\r
+/// The result is in radians.\r
+template <typename ReturnType, typename Point1, typename Point2>\r
+inline ReturnType azimuth(Point1 const& p1, Point2 const& p2)\r
+{\r
+ return detail_dispatch::azimuth\r
+ <\r
+ ReturnType,\r
+ typename geometry::cs_tag<Point1>::type\r
+ >::apply(p1, p2);\r
+}\r
+\r
+/// Calculate azimuth between two points.\r
+/// The result is in radians.\r
+template <typename ReturnType, typename Point1, typename Point2, typename Model>\r
+inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model)\r
+{\r
+ return detail_dispatch::azimuth\r
+ <\r
+ ReturnType,\r
+ typename geometry::cs_tag<Point1>::type\r
+ >::apply(p1, p2, model);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP\r
+\r
+#include <cstddef>\r
+#include <iterator>\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+#include <boost/geometry/algorithms/simplify.hpp>\r
+\r
+#include <boost/geometry/views/detail/normalized_view.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)\r
+#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+template <typename Range, typename DistanceStrategy>\r
+inline void simplify_input(Range const& range,\r
+ DistanceStrategy const& distance,\r
+ Range& simplified)\r
+{\r
+ // We have to simplify the ring before to avoid very small-scaled\r
+ // features in the original (convex/concave/convex) being enlarged\r
+ // in a very large scale and causing issues (IP's within pieces).\r
+ // This might be reconsidered later. Simplifying with a very small\r
+ // distance (1%% of the buffer) will never be visible in the result,\r
+ // if it is using round joins. For miter joins they are even more\r
+ // sensitive to small scale input features, however the result will\r
+ // look better.\r
+ // It also gets rid of duplicate points\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)\r
+ geometry::simplify(range, simplified, distance.simplify_distance());\r
+#else\r
+\r
+ typedef typename boost::range_value<Range>::type point_type;\r
+ typedef strategy::distance::detail::projected_point_ax<> ax_type;\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ strategy::distance::detail::projected_point_ax<>,\r
+ point_type,\r
+ point_type\r
+ >::type return_type;\r
+\r
+ typedef strategy::distance::detail::projected_point_ax_less\r
+ <\r
+ return_type\r
+ > comparator_type;\r
+\r
+ typedef strategy::simplify::detail::douglas_peucker\r
+ <\r
+ point_type,\r
+ strategy::distance::detail::projected_point_ax<>,\r
+ comparator_type\r
+ > dp_ax;\r
+\r
+ return_type max_distance(distance.simplify_distance() * 2.0,\r
+ distance.simplify_distance());\r
+ comparator_type comparator(max_distance);\r
+ dp_ax strategy(comparator);\r
+\r
+ geometry::simplify(range, simplified, max_distance, strategy);\r
+#endif\r
+\r
+ if (boost::size(simplified) == 2\r
+ && geometry::equals(geometry::range::front(simplified),\r
+ geometry::range::back(simplified)))\r
+ {\r
+ traits::resize<Range>::apply(simplified, 1);\r
+ }\r
+}\r
+\r
+\r
+template <typename RingOutput>\r
+struct buffer_range\r
+{\r
+ typedef typename point_type<RingOutput>::type output_point_type;\r
+ typedef typename coordinate_type<RingOutput>::type coordinate_type;\r
+\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename Point,\r
+ typename DistanceStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline\r
+ void add_join(Collection& collection,\r
+ Point const& penultimate_input,\r
+ Point const& previous_input,\r
+ output_point_type const& prev_perp1,\r
+ output_point_type const& prev_perp2,\r
+ Point const& input,\r
+ output_point_type const& perp1,\r
+ output_point_type const& perp2,\r
+ strategy::buffer::buffer_side_selector side,\r
+ DistanceStrategy const& distance,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ RobustPolicy const& )\r
+ {\r
+ output_point_type intersection_point;\r
+ geometry::assign_zero(intersection_point);\r
+\r
+ strategy::buffer::join_selector join\r
+ = get_join_type(penultimate_input, previous_input, input);\r
+ if (join == strategy::buffer::join_convex)\r
+ {\r
+ // Calculate the intersection-point formed by the two sides.\r
+ // It might be that the two sides are not convex, but continue\r
+ // or spikey, we then change the join-type\r
+ join = line_line_intersection::apply(\r
+ perp1, perp2, prev_perp1, prev_perp2,\r
+ intersection_point);\r
+\r
+ }\r
+\r
+ switch(join)\r
+ {\r
+ case strategy::buffer::join_continue :\r
+ // No join, we get two consecutive sides\r
+ break;\r
+ case strategy::buffer::join_concave :\r
+ {\r
+ std::vector<output_point_type> range_out;\r
+ range_out.push_back(prev_perp2);\r
+ range_out.push_back(previous_input);\r
+ collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);\r
+\r
+ range_out.clear();\r
+ range_out.push_back(previous_input);\r
+ range_out.push_back(perp1);\r
+ collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);\r
+ }\r
+ break;\r
+ case strategy::buffer::join_spike :\r
+ {\r
+ // For linestrings, only add spike at one side to avoid\r
+ // duplicates\r
+ std::vector<output_point_type> range_out;\r
+ end_strategy.apply(penultimate_input, prev_perp2, previous_input, perp1, side, distance, range_out);\r
+ collection.add_endcap(end_strategy, range_out, previous_input);\r
+ collection.set_current_ring_concave();\r
+ }\r
+ break;\r
+ case strategy::buffer::join_convex :\r
+ {\r
+ // The corner is convex, we create a join\r
+ // TODO (future) - avoid a separate vector, add the piece directly\r
+ std::vector<output_point_type> range_out;\r
+ if (join_strategy.apply(intersection_point,\r
+ previous_input, prev_perp2, perp1,\r
+ distance.apply(previous_input, input, side),\r
+ range_out))\r
+ {\r
+ collection.add_piece(strategy::buffer::buffered_join,\r
+ previous_input, range_out);\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ static inline strategy::buffer::join_selector get_join_type(\r
+ output_point_type const& p0,\r
+ output_point_type const& p1,\r
+ output_point_type const& p2)\r
+ {\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<output_point_type>::type\r
+ >::type side_strategy;\r
+\r
+ int const side = side_strategy::apply(p0, p1, p2);\r
+ return side == -1 ? strategy::buffer::join_convex\r
+ : side == 1 ? strategy::buffer::join_concave\r
+ : parallel_continue\r
+ (\r
+ get<0>(p2) - get<0>(p1),\r
+ get<1>(p2) - get<1>(p1),\r
+ get<0>(p1) - get<0>(p0),\r
+ get<1>(p1) - get<1>(p0)\r
+ ) ? strategy::buffer::join_continue\r
+ : strategy::buffer::join_spike;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename Iterator,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline strategy::buffer::result_code iterate(Collection& collection,\r
+ Iterator begin, Iterator end,\r
+ strategy::buffer::buffer_side_selector side,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ RobustPolicy const& robust_policy,\r
+ output_point_type& first_p1,\r
+ output_point_type& first_p2,\r
+ output_point_type& last_p1,\r
+ output_point_type& last_p2)\r
+ {\r
+ boost::ignore_unused(side_strategy);\r
+\r
+ typedef typename std::iterator_traits\r
+ <\r
+ Iterator\r
+ >::value_type point_type;\r
+\r
+ point_type second_point, penultimate_point, ultimate_point; // last two points from begin/end\r
+\r
+ /*\r
+ * last.p1 last.p2 these are the "previous (last) perpendicular points"\r
+ * --------------\r
+ * | |\r
+ * *------------*____ <- *prev\r
+ * pup | | p1 "current perpendicular point 1"\r
+ * | |\r
+ * | | this forms a "side", a side is a piece\r
+ * | |\r
+ * *____| p2\r
+ *\r
+ * ^\r
+ * *it\r
+ *\r
+ * pup: penultimate_point\r
+ */\r
+\r
+ strategy::buffer::result_code result = strategy::buffer::result_no_output;\r
+ bool first = true;\r
+\r
+ Iterator it = begin;\r
+\r
+ std::vector<output_point_type> generated_side;\r
+ generated_side.reserve(2);\r
+\r
+ for (Iterator prev = it++; it != end; ++it)\r
+ {\r
+ generated_side.clear();\r
+ strategy::buffer::result_code error_code\r
+ = side_strategy.apply(*prev, *it, side,\r
+ distance_strategy, generated_side);\r
+\r
+ if (error_code == strategy::buffer::result_no_output)\r
+ {\r
+ // Because input is simplified, this is improbable,\r
+ // but it can happen for degenerate geometries\r
+ // Further handling of this side is skipped\r
+ continue;\r
+ }\r
+ else if (error_code == strategy::buffer::result_error_numerical)\r
+ {\r
+ return error_code;\r
+ }\r
+\r
+ BOOST_GEOMETRY_ASSERT(! generated_side.empty());\r
+\r
+ result = strategy::buffer::result_normal;\r
+\r
+ if (! first)\r
+ {\r
+ add_join(collection,\r
+ penultimate_point,\r
+ *prev, last_p1, last_p2,\r
+ *it, generated_side.front(), generated_side.back(),\r
+ side,\r
+ distance_strategy, join_strategy, end_strategy,\r
+ robust_policy);\r
+ }\r
+\r
+ collection.add_side_piece(*prev, *it, generated_side, first);\r
+\r
+ penultimate_point = *prev;\r
+ ultimate_point = *it;\r
+ last_p1 = generated_side.front();\r
+ last_p2 = generated_side.back();\r
+ prev = it;\r
+ if (first)\r
+ {\r
+ first = false;\r
+ second_point = *it;\r
+ first_p1 = generated_side.front();\r
+ first_p2 = generated_side.back();\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Multi,\r
+ typename PolygonOutput,\r
+ typename Policy\r
+>\r
+struct buffer_multi\r
+{\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void apply(Multi const& multi,\r
+ Collection& collection,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ for (typename boost::range_iterator<Multi const>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ Policy::apply(*it, collection,\r
+ distance_strategy, side_strategy,\r
+ join_strategy, end_strategy, point_strategy,\r
+ robust_policy);\r
+ }\r
+ }\r
+};\r
+\r
+struct visit_pieces_default_policy\r
+{\r
+ template <typename Collection>\r
+ static inline void apply(Collection const&, int)\r
+ {}\r
+};\r
+\r
+template\r
+<\r
+ typename OutputPointType,\r
+ typename Point,\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename PointStrategy\r
+>\r
+inline void buffer_point(Point const& point, Collection& collection,\r
+ DistanceStrategy const& distance_strategy,\r
+ PointStrategy const& point_strategy)\r
+{\r
+ collection.start_new_ring();\r
+ std::vector<OutputPointType> range_out;\r
+ point_strategy.apply(point, distance_strategy, range_out);\r
+ collection.add_piece(strategy::buffer::buffered_point, range_out, false);\r
+ collection.set_piece_center(point);\r
+ collection.finish_ring(strategy::buffer::result_normal);\r
+}\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename RingInput,\r
+ typename RingOutput\r
+>\r
+struct buffer_inserter\r
+{};\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename RingOutput\r
+>\r
+struct buffer_inserter<point_tag, Point, RingOutput>\r
+{\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void apply(Point const& point, Collection& collection,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& ,\r
+ JoinStrategy const& ,\r
+ EndStrategy const& ,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& )\r
+ {\r
+ detail::buffer::buffer_point\r
+ <\r
+ typename point_type<RingOutput>::type\r
+ >(point, collection, distance_strategy, point_strategy);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename RingInput,\r
+ typename RingOutput\r
+>\r
+struct buffer_inserter<ring_tag, RingInput, RingOutput>\r
+{\r
+ typedef typename point_type<RingOutput>::type output_point_type;\r
+\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename Iterator,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline strategy::buffer::result_code iterate(Collection& collection,\r
+ Iterator begin, Iterator end,\r
+ strategy::buffer::buffer_side_selector side,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ output_point_type first_p1, first_p2, last_p1, last_p2;\r
+\r
+ typedef detail::buffer::buffer_range<RingOutput> buffer_range;\r
+\r
+ strategy::buffer::result_code result\r
+ = buffer_range::iterate(collection, begin, end,\r
+ side,\r
+ distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,\r
+ first_p1, first_p2, last_p1, last_p2);\r
+\r
+ // Generate closing join\r
+ if (result == strategy::buffer::result_normal)\r
+ {\r
+ buffer_range::add_join(collection,\r
+ *(end - 2),\r
+ *(end - 1), last_p1, last_p2,\r
+ *(begin + 1), first_p1, first_p2,\r
+ side,\r
+ distance_strategy, join_strategy, end_strategy,\r
+ robust_policy);\r
+ }\r
+\r
+ // Buffer is closed automatically by last closing corner\r
+ return result;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline strategy::buffer::result_code apply(RingInput const& ring,\r
+ Collection& collection,\r
+ DistanceStrategy const& distance,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ RingInput simplified;\r
+ detail::buffer::simplify_input(ring, distance, simplified);\r
+\r
+ strategy::buffer::result_code code = strategy::buffer::result_no_output;\r
+\r
+ std::size_t n = boost::size(simplified);\r
+ std::size_t const min_points = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<RingInput>::value\r
+ >::value;\r
+\r
+ if (n >= min_points)\r
+ {\r
+ detail::normalized_view<RingInput const> view(simplified);\r
+ if (distance.negative())\r
+ {\r
+ // Walk backwards (rings will be reversed afterwards)\r
+ code = iterate(collection, boost::rbegin(view), boost::rend(view),\r
+ strategy::buffer::buffer_side_right,\r
+ distance, side_strategy, join_strategy, end_strategy, robust_policy);\r
+ }\r
+ else\r
+ {\r
+ code = iterate(collection, boost::begin(view), boost::end(view),\r
+ strategy::buffer::buffer_side_left,\r
+ distance, side_strategy, join_strategy, end_strategy, robust_policy);\r
+ }\r
+ }\r
+\r
+ if (code == strategy::buffer::result_no_output && n >= 1)\r
+ {\r
+ // Use point_strategy to buffer degenerated ring\r
+ detail::buffer::buffer_point<output_point_type>\r
+ (\r
+ geometry::range::front(simplified),\r
+ collection, distance, point_strategy\r
+ );\r
+ }\r
+ return code;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring,\r
+ typename Polygon\r
+>\r
+struct buffer_inserter<linestring_tag, Linestring, Polygon>\r
+{\r
+ typedef typename ring_type<Polygon>::type output_ring_type;\r
+ typedef typename point_type<output_ring_type>::type output_point_type;\r
+ typedef typename point_type<Linestring>::type input_point_type;\r
+\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename Iterator,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline strategy::buffer::result_code iterate(Collection& collection,\r
+ Iterator begin, Iterator end,\r
+ strategy::buffer::buffer_side_selector side,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ RobustPolicy const& robust_policy,\r
+ output_point_type& first_p1)\r
+ {\r
+ input_point_type const& ultimate_point = *(end - 1);\r
+ input_point_type const& penultimate_point = *(end - 2);\r
+\r
+ // For the end-cap, we need to have the last perpendicular point on the\r
+ // other side of the linestring. If it is the second pass (right),\r
+ // we have it already from the first phase (left).\r
+ // But for the first pass, we have to generate it\r
+ output_point_type reverse_p1;\r
+ if (side == strategy::buffer::buffer_side_right)\r
+ {\r
+ reverse_p1 = first_p1;\r
+ }\r
+ else\r
+ {\r
+ std::vector<output_point_type> generated_side;\r
+ strategy::buffer::result_code code\r
+ = side_strategy.apply(ultimate_point, penultimate_point,\r
+ strategy::buffer::buffer_side_right,\r
+ distance_strategy, generated_side);\r
+ if (code != strategy::buffer::result_normal)\r
+ {\r
+ // No output or numerical error\r
+ return code;\r
+ }\r
+ reverse_p1 = generated_side.front();\r
+ }\r
+\r
+ output_point_type first_p2, last_p1, last_p2;\r
+\r
+ strategy::buffer::result_code result\r
+ = detail::buffer::buffer_range<output_ring_type>::iterate(collection,\r
+ begin, end, side,\r
+ distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,\r
+ first_p1, first_p2, last_p1, last_p2);\r
+\r
+ if (result == strategy::buffer::result_normal)\r
+ {\r
+ std::vector<output_point_type> range_out;\r
+ end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);\r
+ collection.add_endcap(end_strategy, range_out, ultimate_point);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection,\r
+ DistanceStrategy const& distance,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ Linestring simplified;\r
+ detail::buffer::simplify_input(linestring, distance, simplified);\r
+\r
+ strategy::buffer::result_code code = strategy::buffer::result_no_output;\r
+ std::size_t n = boost::size(simplified);\r
+ if (n > 1)\r
+ {\r
+ collection.start_new_ring();\r
+ output_point_type first_p1;\r
+ code = iterate(collection,\r
+ boost::begin(simplified), boost::end(simplified),\r
+ strategy::buffer::buffer_side_left,\r
+ distance, side_strategy, join_strategy, end_strategy, robust_policy,\r
+ first_p1);\r
+\r
+ if (code == strategy::buffer::result_normal)\r
+ {\r
+ code = iterate(collection,\r
+ boost::rbegin(simplified), boost::rend(simplified),\r
+ strategy::buffer::buffer_side_right,\r
+ distance, side_strategy, join_strategy, end_strategy, robust_policy,\r
+ first_p1);\r
+ }\r
+ collection.finish_ring(code);\r
+ }\r
+ if (code == strategy::buffer::result_no_output && n >= 1)\r
+ {\r
+ // Use point_strategy to buffer degenerated linestring\r
+ detail::buffer::buffer_point<output_point_type>\r
+ (\r
+ geometry::range::front(simplified),\r
+ collection, distance, point_strategy\r
+ );\r
+ }\r
+ return code;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename PolygonInput,\r
+ typename PolygonOutput\r
+>\r
+struct buffer_inserter<polygon_tag, PolygonInput, PolygonOutput>\r
+{\r
+private:\r
+ typedef typename ring_type<PolygonInput>::type input_ring_type;\r
+ typedef typename ring_type<PolygonOutput>::type output_ring_type;\r
+\r
+ typedef buffer_inserter<ring_tag, input_ring_type, output_ring_type> policy;\r
+\r
+\r
+ template\r
+ <\r
+ typename Iterator,\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline\r
+ void iterate(Iterator begin, Iterator end,\r
+ Collection& collection,\r
+ DistanceStrategy const& distance,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy,\r
+ bool is_interior)\r
+ {\r
+ for (Iterator it = begin; it != end; ++it)\r
+ {\r
+ collection.start_new_ring();\r
+ strategy::buffer::result_code const code\r
+ = policy::apply(*it, collection, distance, side_strategy,\r
+ join_strategy, end_strategy, point_strategy,\r
+ robust_policy);\r
+\r
+ collection.finish_ring(code, is_interior);\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ typename InteriorRings,\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline\r
+ void apply_interior_rings(InteriorRings const& interior_rings,\r
+ Collection& collection,\r
+ DistanceStrategy const& distance,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ iterate(boost::begin(interior_rings), boost::end(interior_rings),\r
+ collection, distance, side_strategy,\r
+ join_strategy, end_strategy, point_strategy,\r
+ robust_policy, true);\r
+ }\r
+\r
+public:\r
+ template\r
+ <\r
+ typename Collection,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void apply(PolygonInput const& polygon,\r
+ Collection& collection,\r
+ DistanceStrategy const& distance,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ {\r
+ collection.start_new_ring();\r
+\r
+ strategy::buffer::result_code const code\r
+ = policy::apply(exterior_ring(polygon), collection,\r
+ distance, side_strategy,\r
+ join_strategy, end_strategy, point_strategy,\r
+ robust_policy);\r
+\r
+ collection.finish_ring(code, false,\r
+ geometry::num_interior_rings(polygon) > 0u);\r
+ }\r
+\r
+ apply_interior_rings(interior_rings(polygon),\r
+ collection, distance, side_strategy,\r
+ join_strategy, end_strategy, point_strategy,\r
+ robust_policy);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Multi,\r
+ typename PolygonOutput\r
+>\r
+struct buffer_inserter<multi_tag, Multi, PolygonOutput>\r
+ : public detail::buffer::buffer_multi\r
+ <\r
+ Multi,\r
+ PolygonOutput,\r
+ dispatch::buffer_inserter\r
+ <\r
+ typename single_tag_of\r
+ <\r
+ typename tag<Multi>::type\r
+ >::type,\r
+ typename boost::range_value<Multi const>::type,\r
+ typename geometry::ring_type<PolygonOutput>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+template\r
+<\r
+ typename GeometryOutput,\r
+ typename GeometryInput,\r
+ typename OutputIterator,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy,\r
+ typename VisitPiecesPolicy\r
+>\r
+inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy,\r
+ VisitPiecesPolicy& visit_pieces_policy\r
+ )\r
+{\r
+ boost::ignore_unused(visit_pieces_policy);\r
+\r
+ typedef detail::buffer::buffered_piece_collection\r
+ <\r
+ typename geometry::ring_type<GeometryOutput>::type,\r
+ RobustPolicy\r
+ > collection_type;\r
+ collection_type collection(robust_policy);\r
+ collection_type const& const_collection = collection;\r
+\r
+ bool const areal = boost::is_same\r
+ <\r
+ typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,\r
+ areal_tag\r
+ >::type::value;\r
+ bool const linear = boost::is_same\r
+ <\r
+ typename tag_cast<typename tag<GeometryInput>::type, linear_tag>::type,\r
+ linear_tag\r
+ >::type::value;\r
+\r
+ dispatch::buffer_inserter\r
+ <\r
+ typename tag_cast\r
+ <\r
+ typename tag<GeometryInput>::type,\r
+ multi_tag\r
+ >::type,\r
+ GeometryInput,\r
+ GeometryOutput\r
+ >::apply(geometry_input, collection,\r
+ distance_strategy, side_strategy, join_strategy,\r
+ end_strategy, point_strategy,\r
+ robust_policy);\r
+\r
+ collection.get_turns();\r
+ collection.classify_turns(linear);\r
+ if (BOOST_GEOMETRY_CONDITION(areal))\r
+ {\r
+ collection.check_remaining_points(distance_strategy);\r
+ }\r
+\r
+ // Visit the piece collection. This does nothing (by default), but\r
+ // optionally a debugging tool can be attached (e.g. console or svg),\r
+ // or the piece collection can be unit-tested\r
+ // phase 0: turns (before discarded)\r
+ visit_pieces_policy.apply(const_collection, 0);\r
+\r
+ collection.discard_rings();\r
+ collection.block_turns();\r
+ collection.enrich();\r
+\r
+ // phase 1: turns (after enrichment/clustering)\r
+ visit_pieces_policy.apply(const_collection, 1);\r
+\r
+ collection.traverse();\r
+\r
+ // Reverse all offsetted rings / traversed rings if:\r
+ // - they were generated on the negative side (deflate) of polygons\r
+ // - the output is counter clockwise\r
+ // and avoid reversing twice\r
+ bool reverse = distance_strategy.negative() && areal;\r
+ if (BOOST_GEOMETRY_CONDITION(\r
+ geometry::point_order<GeometryOutput>::value == counterclockwise))\r
+ {\r
+ reverse = ! reverse;\r
+ }\r
+ if (reverse)\r
+ {\r
+ collection.reverse();\r
+ }\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal))\r
+ {\r
+ collection.discard_nonintersecting_deflated_rings();\r
+ }\r
+\r
+ collection.template assign<GeometryOutput>(out);\r
+\r
+ // Visit collection again\r
+ // phase 2: rings (after traversing)\r
+ visit_pieces_policy.apply(const_collection, 2);\r
+}\r
+\r
+template\r
+<\r
+ typename GeometryOutput,\r
+ typename GeometryInput,\r
+ typename OutputIterator,\r
+ typename DistanceStrategy,\r
+ typename SideStrategy,\r
+ typename JoinStrategy,\r
+ typename EndStrategy,\r
+ typename PointStrategy,\r
+ typename RobustPolicy\r
+>\r
+inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,\r
+ DistanceStrategy const& distance_strategy,\r
+ SideStrategy const& side_strategy,\r
+ JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy,\r
+ PointStrategy const& point_strategy,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+ detail::buffer::visit_pieces_default_policy visitor;\r
+ buffer_inserter<GeometryOutput>(geometry_input, out,\r
+ distance_strategy, side_strategy, join_strategy,\r
+ end_strategy, point_strategy,\r
+ robust_policy, visitor);\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace detail::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP\r
+\r
+#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)\r
+# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION\r
+#endif\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+\r
+enum intersection_location_type\r
+{\r
+ location_ok, inside_buffer, location_discard\r
+};\r
+\r
+class backtrack_for_buffer\r
+{\r
+public :\r
+ typedef detail::overlay::backtrack_state state_type;\r
+\r
+ template\r
+ <\r
+ typename Operation,\r
+ typename Rings,\r
+ typename Turns,\r
+ typename Geometry,\r
+ typename RobustPolicy,\r
+ typename Visitor\r
+ >\r
+ static inline void apply(std::size_t size_at_start,\r
+ Rings& rings, typename boost::range_value<Rings>::type& ring,\r
+ Turns& turns,\r
+ typename boost::range_value<Turns>::type const& /*turn*/,\r
+ Operation& operation,\r
+ detail::overlay::traverse_error_type /*traverse_error*/,\r
+ Geometry const& ,\r
+ Geometry const& ,\r
+ RobustPolicy const& ,\r
+ state_type& state,\r
+ Visitor& /*visitor*/\r
+ )\r
+ {\r
+#if defined(BOOST_GEOMETRY_COUNT_BACKTRACK_WARNINGS)\r
+extern int g_backtrack_warning_count;\r
+g_backtrack_warning_count++;\r
+#endif\r
+//std::cout << "!";\r
+//std::cout << "WARNING " << traverse_error_string(traverse_error) << std::endl;\r
+\r
+ state.m_good = false;\r
+\r
+ // Make bad output clean\r
+ rings.resize(size_at_start);\r
+ ring.clear();\r
+\r
+ // Reject this as a starting point\r
+ operation.visited.set_rejected();\r
+\r
+ // And clear all visit info\r
+ clear_visit_info(turns);\r
+ }\r
+};\r
+\r
+struct buffer_overlay_visitor\r
+{\r
+public :\r
+ void print(char const* /*header*/)\r
+ {\r
+ }\r
+\r
+ template <typename Turns>\r
+ void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)\r
+ {\r
+ }\r
+\r
+ template <typename Turns>\r
+ void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)\r
+ {\r
+ }\r
+\r
+ template <typename Turns>\r
+ void visit_turns(int , Turns const& ) {}\r
+\r
+ template <typename Clusters, typename Turns>\r
+ void visit_clusters(Clusters const& , Turns const& ) {}\r
+\r
+ template <typename Turns, typename Turn, typename Operation>\r
+ void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/)\r
+ {\r
+ }\r
+\r
+ template <typename Turns, typename Turn, typename Operation>\r
+ void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,\r
+ detail::overlay::traverse_error_type )\r
+ {}\r
+};\r
+\r
+\r
+// Should follow traversal-turn-concept (enrichment, visit structure)\r
+// and adds index in piece vector to find it back\r
+template <typename Point, typename SegmentRatio>\r
+struct buffer_turn_operation\r
+ : public detail::overlay::traversal_turn_operation<Point, SegmentRatio>\r
+{\r
+ signed_size_type piece_index;\r
+ signed_size_type index_in_robust_ring;\r
+\r
+ inline buffer_turn_operation()\r
+ : piece_index(-1)\r
+ , index_in_robust_ring(-1)\r
+ {}\r
+};\r
+\r
+// Version for buffer including type of location, is_opposite, and helper variables\r
+template <typename Point, typename RobustPoint, typename SegmentRatio>\r
+struct buffer_turn_info\r
+ : public detail::overlay::turn_info\r
+ <\r
+ Point,\r
+ SegmentRatio,\r
+ buffer_turn_operation<Point, SegmentRatio>\r
+ >\r
+{\r
+ typedef Point point_type;\r
+ typedef RobustPoint robust_point_type;\r
+\r
+ std::size_t turn_index; // TODO: this might go if partition can operate on non-const input\r
+\r
+ RobustPoint robust_point;\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ // Will (most probably) be removed later\r
+ RobustPoint mapped_robust_point; // alas... we still need to adapt our points, offsetting them 1 integer to be co-located with neighbours\r
+#endif\r
+\r
+\r
+ inline RobustPoint const& get_robust_point() const\r
+ {\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ return mapped_robust_point;\r
+#endif\r
+ return robust_point;\r
+ }\r
+\r
+ intersection_location_type location;\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;\r
+#endif\r
+\r
+ std::size_t count_within;\r
+\r
+ bool within_original;\r
+ std::size_t count_on_original_boundary;\r
+ signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring\r
+\r
+ std::size_t count_on_offsetted;\r
+ std::size_t count_on_helper;\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ std::size_t count_within_near_offsetted;\r
+#endif\r
+\r
+ bool remove_on_multi;\r
+\r
+ // Obsolete:\r
+ std::size_t count_on_occupied;\r
+ std::size_t count_on_multi;\r
+\r
+ inline buffer_turn_info()\r
+ : turn_index(0)\r
+ , location(location_ok)\r
+ , count_within(0)\r
+ , within_original(false)\r
+ , count_on_original_boundary(0)\r
+ , count_in_original(0)\r
+ , count_on_offsetted(0)\r
+ , count_on_helper(0)\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ , count_within_near_offsetted(0)\r
+#endif\r
+ , remove_on_multi(false)\r
+ , count_on_occupied(0)\r
+ , count_on_multi(0)\r
+ {}\r
+};\r
+\r
+struct buffer_operation_less\r
+{\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ segment_identifier const& sl = left.seg_id;\r
+ segment_identifier const& sr = right.seg_id;\r
+\r
+ // Sort them descending\r
+ return sl == sr\r
+ ? left.fraction < right.fraction\r
+ : sl < sr;\r
+ }\r
+};\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP\r
+\r
+#include <algorithm>\r
+#include <cstddef>\r
+#include <set>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/comparable_distance.hpp>\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/is_convex.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+#include <boost/geometry/geometries/ring.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/buffer/buffered_ring.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/occupation_info.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+enum segment_relation_code\r
+{\r
+ segment_relation_on_left,\r
+ segment_relation_on_right,\r
+ segment_relation_within,\r
+ segment_relation_disjoint\r
+};\r
+\r
+/*\r
+ * Terminology\r
+ *\r
+ * Suppose we make a buffer (using blocked corners) of this rectangle:\r
+ *\r
+ * +-------+\r
+ * | |\r
+ * | rect |\r
+ * | |\r
+ * +-------+\r
+ *\r
+ * For the sides we get these four buffered side-pieces (marked with s)\r
+ * and four buffered corner pieces (marked with c)\r
+ *\r
+ * c---+---s---+---c\r
+ * | | piece | | <- see below for details of the middle top-side-piece\r
+ * +---+-------+---+\r
+ * | | | |\r
+ * s | rect | s <- two side pieces left/right of rect\r
+ * | | | |\r
+ * +---+-------+---+\r
+ * | | piece | | <- one side-piece below, and two corner pieces\r
+ * c---+---s---+---c\r
+ *\r
+ * The outer part of the picture above, using all pieces,\r
+ * form together the offsetted ring (marked with o below)\r
+ * The 8 pieces are part of the piece collection and use for inside-checks\r
+ * The inner parts form (using 1 or 2 points per piece, often co-located)\r
+ * form together the robust_polygons (marked with r below)\r
+ * The remaining piece-segments are helper-segments (marked with h)\r
+ *\r
+ * ooooooooooooooooo\r
+ * o h h o\r
+ * ohhhrrrrrrrrrhhho\r
+ * o r r o\r
+ * o r r o\r
+ * o r r o\r
+ * ohhhrrrrrrrrrhhho\r
+ * o h h o\r
+ * ooooooooooooooooo\r
+ *\r
+ */\r
+\r
+\r
+template <typename Ring, typename RobustPolicy>\r
+struct buffered_piece_collection\r
+{\r
+ typedef buffered_piece_collection<Ring, RobustPolicy> this_type;\r
+\r
+ typedef typename geometry::point_type<Ring>::type point_type;\r
+ typedef typename geometry::coordinate_type<Ring>::type coordinate_type;\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ point_type,\r
+ RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ // Robust ring/polygon type, always clockwise\r
+ typedef geometry::model::ring<robust_point_type> robust_ring_type;\r
+ typedef geometry::model::box<robust_point_type> robust_box_type;\r
+\r
+ typedef typename default_comparable_distance_result\r
+ <\r
+ robust_point_type\r
+ >::type robust_comparable_radius_type;\r
+\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type\r
+ >::type side_strategy;\r
+\r
+ typedef typename geometry::rescale_policy_type\r
+ <\r
+ typename geometry::point_type<Ring>::type\r
+ >::type rescale_policy_type;\r
+\r
+ typedef typename geometry::segment_ratio_type\r
+ <\r
+ point_type,\r
+ RobustPolicy\r
+ >::type segment_ratio_type;\r
+\r
+ typedef buffer_turn_info\r
+ <\r
+ point_type,\r
+ robust_point_type,\r
+ segment_ratio_type\r
+ > buffer_turn_info_type;\r
+\r
+ typedef buffer_turn_operation\r
+ <\r
+ point_type,\r
+ segment_ratio_type\r
+ > buffer_turn_operation_type;\r
+\r
+ typedef std::vector<buffer_turn_info_type> turn_vector_type;\r
+\r
+ struct robust_turn\r
+ {\r
+ std::size_t turn_index;\r
+ int operation_index;\r
+ robust_point_type point;\r
+ segment_identifier seg_id;\r
+ segment_ratio_type fraction;\r
+ };\r
+\r
+ struct piece\r
+ {\r
+ typedef robust_ring_type piece_robust_ring_type;\r
+ typedef geometry::section<robust_box_type, 1> section_type;\r
+\r
+ strategy::buffer::piece_type type;\r
+ signed_size_type index;\r
+\r
+ signed_size_type left_index; // points to previous piece of same ring\r
+ signed_size_type right_index; // points to next piece of same ring\r
+\r
+ // The next two members (1, 2) form together a complete clockwise ring\r
+ // for each piece (with one dupped point)\r
+ // The complete clockwise ring is also included as a robust ring (3)\r
+\r
+ // 1: half, part of offsetted_rings\r
+ segment_identifier first_seg_id;\r
+ signed_size_type last_segment_index; // no segment-identifier - it is the same as first_seg_id\r
+ signed_size_type offsetted_count; // part in robust_ring which is part of offsetted ring\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS)\r
+ // 2: half, not part of offsetted rings - part of robust ring\r
+ std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end\r
+#endif\r
+\r
+ bool is_convex;\r
+ bool is_monotonic_increasing[2]; // 0=x, 1=y\r
+ bool is_monotonic_decreasing[2]; // 0=x, 1=y\r
+\r
+ // Monotonic sections of pieces around points\r
+ std::vector<section_type> sections;\r
+\r
+ // Robust representations\r
+ // 3: complete ring\r
+ robust_ring_type robust_ring;\r
+\r
+ robust_box_type robust_envelope;\r
+ robust_box_type robust_offsetted_envelope;\r
+\r
+ std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead\r
+\r
+ robust_point_type robust_center;\r
+ robust_comparable_radius_type robust_min_comparable_radius;\r
+ robust_comparable_radius_type robust_max_comparable_radius;\r
+\r
+ piece()\r
+ : type(strategy::buffer::piece_type_unknown)\r
+ , index(-1)\r
+ , left_index(-1)\r
+ , right_index(-1)\r
+ , last_segment_index(-1)\r
+ , offsetted_count(-1)\r
+ , is_convex(false)\r
+ , robust_min_comparable_radius(0)\r
+ , robust_max_comparable_radius(0)\r
+ {\r
+ is_monotonic_increasing[0] = false;\r
+ is_monotonic_increasing[1] = false;\r
+ is_monotonic_decreasing[0] = false;\r
+ is_monotonic_decreasing[1] = false;\r
+ }\r
+ };\r
+\r
+ struct robust_original\r
+ {\r
+ typedef robust_ring_type original_robust_ring_type;\r
+ typedef geometry::sections<robust_box_type, 1> sections_type;\r
+\r
+ inline robust_original()\r
+ : m_is_interior(false)\r
+ , m_has_interiors(true)\r
+ {}\r
+\r
+ inline robust_original(robust_ring_type const& ring,\r
+ bool is_interior, bool has_interiors)\r
+ : m_ring(ring)\r
+ , m_is_interior(is_interior)\r
+ , m_has_interiors(has_interiors)\r
+ {\r
+ geometry::envelope(m_ring, m_box);\r
+\r
+ // create monotonic sections in x-dimension\r
+ // The dimension is critical because the direction is later used\r
+ // in the optimization for within checks using winding strategy\r
+ // and this strategy is scanning in x direction.\r
+ typedef boost::mpl::vector_c<std::size_t, 0> dimensions;\r
+ geometry::sectionalize<false, dimensions>(m_ring,\r
+ detail::no_rescale_policy(), m_sections);\r
+ }\r
+\r
+ robust_ring_type m_ring;\r
+ robust_box_type m_box;\r
+ sections_type m_sections;\r
+\r
+ bool m_is_interior;\r
+ bool m_has_interiors;\r
+ };\r
+\r
+ typedef std::vector<piece> piece_vector_type;\r
+\r
+ piece_vector_type m_pieces;\r
+ turn_vector_type m_turns;\r
+ signed_size_type m_first_piece_index;\r
+\r
+ buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index\r
+ std::vector<robust_original> robust_originals; // robust representation of the original(s)\r
+ robust_ring_type current_robust_ring;\r
+ buffered_ring_collection<Ring> traversed_rings;\r
+ segment_identifier current_segment_id;\r
+\r
+ // Specificly for offsetted rings around points\r
+ // but also for large joins with many points\r
+ typedef geometry::sections<robust_box_type, 2> sections_type;\r
+ sections_type monotonic_sections;\r
+\r
+ // Define the clusters, mapping cluster_id -> turns\r
+ typedef std::map\r
+ <\r
+ signed_size_type,\r
+ detail::overlay::cluster_info\r
+ > cluster_type;\r
+\r
+ cluster_type m_clusters;\r
+\r
+\r
+ RobustPolicy const& m_robust_policy;\r
+\r
+ struct redundant_turn\r
+ {\r
+ inline bool operator()(buffer_turn_info_type const& turn) const\r
+ {\r
+ return turn.remove_on_multi;\r
+ }\r
+ };\r
+\r
+ buffered_piece_collection(RobustPolicy const& robust_policy)\r
+ : m_first_piece_index(-1)\r
+ , m_robust_policy(robust_policy)\r
+ {}\r
+\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ // Will (most probably) be removed later\r
+ template <typename OccupationMap>\r
+ inline void adapt_mapped_robust_point(OccupationMap const& map,\r
+ buffer_turn_info_type& turn, int distance) const\r
+ {\r
+ for (int x = -distance; x <= distance; x++)\r
+ {\r
+ for (int y = -distance; y <= distance; y++)\r
+ {\r
+ robust_point_type rp = turn.robust_point;\r
+ geometry::set<0>(rp, geometry::get<0>(rp) + x);\r
+ geometry::set<1>(rp, geometry::get<1>(rp) + y);\r
+ if (map.find(rp) != map.end())\r
+ {\r
+ turn.mapped_robust_point = rp;\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+#endif\r
+\r
+ inline void get_occupation(\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ int distance = 0\r
+#endif\r
+ )\r
+ {\r
+ typedef occupation_info<angle_info<robust_point_type, coordinate_type> >\r
+ buffer_occupation_info;\r
+\r
+ typedef std::map\r
+ <\r
+ robust_point_type,\r
+ buffer_occupation_info,\r
+ geometry::less<robust_point_type>\r
+ > occupation_map_type;\r
+\r
+ occupation_map_type occupation_map;\r
+\r
+ // 1: Add all intersection points to occupation map\r
+ typedef typename boost::range_iterator<turn_vector_type>::type\r
+ iterator_type;\r
+\r
+ for (iterator_type it = boost::begin(m_turns);\r
+ it != boost::end(m_turns);\r
+ ++it)\r
+ {\r
+ if (it->location == location_ok)\r
+ {\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ if (distance > 0 && ! occupation_map.empty())\r
+ {\r
+ adapt_mapped_robust_point(occupation_map, *it, distance);\r
+ }\r
+#endif\r
+ occupation_map[it->get_robust_point()].count++;\r
+ }\r
+ }\r
+\r
+ // Remove all points with one or more u/u points from the map\r
+ // (Alternatively, we could NOT do this here and change all u/u\r
+ // behaviour in overlay. Currently nothing is done: each polygon is\r
+ // just followed there. We could also always switch polygons there. For\r
+ // buffer behaviour, where 3 pieces might meet of which 2 (or more) form\r
+ // a u/u turn, this last option would have been better, probably).\r
+ for (iterator_type it = boost::begin(m_turns);\r
+ it != boost::end(m_turns);\r
+ ++it)\r
+ {\r
+ if (it->both(detail::overlay::operation_union))\r
+ {\r
+ typename occupation_map_type::iterator mit =\r
+ occupation_map.find(it->get_robust_point());\r
+\r
+ if (mit != occupation_map.end())\r
+ {\r
+ occupation_map.erase(mit);\r
+ }\r
+ }\r
+ }\r
+\r
+ // 2: Remove all points from map which has only one\r
+ typename occupation_map_type::iterator it = occupation_map.begin();\r
+ while (it != occupation_map.end())\r
+ {\r
+ if (it->second.count <= 1)\r
+ {\r
+ typename occupation_map_type::iterator to_erase = it;\r
+ ++it;\r
+ occupation_map.erase(to_erase);\r
+ }\r
+ else\r
+ {\r
+ ++it;\r
+ }\r
+ }\r
+\r
+ if (occupation_map.empty())\r
+ {\r
+ return;\r
+ }\r
+\r
+ // 3: Add vectors (incoming->intersection-point,\r
+ // intersection-point -> outgoing)\r
+ // for all (co-located) points still present in the map\r
+\r
+ for (iterator_type it = boost::begin(m_turns);\r
+ it != boost::end(m_turns);\r
+ ++it)\r
+ {\r
+ typename occupation_map_type::iterator mit =\r
+ occupation_map.find(it->get_robust_point());\r
+\r
+ if (mit != occupation_map.end())\r
+ {\r
+ buffer_occupation_info& info = mit->second;\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ add_incoming_and_outgoing_angles(it->get_robust_point(), *it,\r
+ m_pieces,\r
+ i, it->operations[i].seg_id,\r
+ info);\r
+ }\r
+\r
+ it->count_on_multi++;\r
+ }\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ // X: Check rounding issues\r
+ if (distance == 0)\r
+ {\r
+ for (typename occupation_map_type::const_iterator it = occupation_map.begin();\r
+ it != occupation_map.end(); ++it)\r
+ {\r
+ if (it->second.has_rounding_issues(it->first))\r
+ {\r
+ if(distance == 0)\r
+ {\r
+ get_occupation(distance + 1);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+#endif\r
+\r
+ // Get left turns from all clusters\r
+ for (typename occupation_map_type::iterator it = occupation_map.begin();\r
+ it != occupation_map.end(); ++it)\r
+ {\r
+ it->second.get_left_turns(it->first, m_turns);\r
+ }\r
+ }\r
+\r
+ inline void classify_turns(bool linear)\r
+ {\r
+ for (typename boost::range_iterator<turn_vector_type>::type it =\r
+ boost::begin(m_turns); it != boost::end(m_turns); ++it)\r
+ {\r
+ if (it->count_within > 0)\r
+ {\r
+ it->location = inside_buffer;\r
+ }\r
+ if (it->count_on_original_boundary > 0 && ! linear)\r
+ {\r
+ it->location = inside_buffer;\r
+ }\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ if (it->count_within_near_offsetted > 0)\r
+ {\r
+ // Within can have in rare cases a rounding issue. We don't discard this\r
+ // point, so it can be used to continue started rings in traversal. But\r
+ // will never start a new ring from this type of points.\r
+ it->operations[0].enriched.startable = false;\r
+ it->operations[1].enriched.startable = false;\r
+ }\r
+#endif\r
+ }\r
+ }\r
+\r
+ template <typename DistanceStrategy>\r
+ inline void check_remaining_points(DistanceStrategy const& distance_strategy)\r
+ {\r
+ // Check if a turn is inside any of the originals\r
+\r
+ turn_in_original_visitor<turn_vector_type> visitor(m_turns);\r
+ geometry::partition\r
+ <\r
+ robust_box_type,\r
+ turn_get_box, turn_in_original_ovelaps_box,\r
+ original_get_box, original_ovelaps_box,\r
+ include_turn_policy, detail::partition::include_all_policy\r
+ >::apply(m_turns, robust_originals, visitor);\r
+\r
+ bool const deflate = distance_strategy.negative();\r
+\r
+ for (typename boost::range_iterator<turn_vector_type>::type it =\r
+ boost::begin(m_turns); it != boost::end(m_turns); ++it)\r
+ {\r
+ buffer_turn_info_type& turn = *it;\r
+ if (turn.location == location_ok)\r
+ {\r
+ if (deflate && turn.count_in_original <= 0)\r
+ {\r
+ // For deflate: it is not in original, discard\r
+ turn.location = location_discard;\r
+ }\r
+ else if (! deflate && turn.count_in_original > 0)\r
+ {\r
+ // For inflate: it is in original, discard\r
+ turn.location = location_discard;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ inline bool assert_indices_in_robust_rings() const\r
+ {\r
+ geometry::equal_to<robust_point_type> comparator;\r
+ for (typename boost::range_iterator<turn_vector_type const>::type it =\r
+ boost::begin(m_turns); it != boost::end(m_turns); ++it)\r
+ {\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ robust_point_type const &p1\r
+ = m_pieces[it->operations[i].piece_index].robust_ring\r
+ [it->operations[i].index_in_robust_ring];\r
+ robust_point_type const &p2 = it->robust_point;\r
+ if (! comparator(p1, p2))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ inline void insert_rescaled_piece_turns()\r
+ {\r
+ // Add rescaled turn points to corresponding pieces\r
+ // (after this, each turn occurs twice)\r
+ std::size_t index = 0;\r
+ for (typename boost::range_iterator<turn_vector_type>::type it =\r
+ boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)\r
+ {\r
+ geometry::recalculate(it->robust_point, it->point, m_robust_policy);\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ it->mapped_robust_point = it->robust_point;\r
+#endif\r
+\r
+ robust_turn turn;\r
+ it->turn_index = index;\r
+ turn.turn_index = index;\r
+ turn.point = it->robust_point;\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn.operation_index = i;\r
+ turn.seg_id = it->operations[i].seg_id;\r
+ turn.fraction = it->operations[i].fraction;\r
+\r
+ piece& pc = m_pieces[it->operations[i].piece_index];\r
+ pc.robust_turns.push_back(turn);\r
+\r
+ // Take into account for the box (intersection points should fall inside,\r
+ // but in theory they can be one off because of rounding\r
+ geometry::expand(pc.robust_envelope, it->robust_point);\r
+ geometry::expand(pc.robust_offsetted_envelope, it->robust_point);\r
+ }\r
+ }\r
+\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ // Insert all rescaled turn-points into these rings, to form a\r
+ // reliable integer-based ring. All turns can be compared (inside) to this\r
+ // rings to see if they are inside.\r
+\r
+ for (typename boost::range_iterator<piece_vector_type>::type\r
+ it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)\r
+ {\r
+ piece& pc = *it;\r
+ signed_size_type piece_segment_index = pc.first_seg_id.segment_index;\r
+ if (! pc.robust_turns.empty())\r
+ {\r
+ if (pc.robust_turns.size() > 1u)\r
+ {\r
+ std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());\r
+ }\r
+ // Walk through them, in reverse to insert at right index\r
+ signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;\r
+ for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type\r
+ rit = boost::const_rbegin(pc.robust_turns);\r
+ rit != boost::const_rend(pc.robust_turns);\r
+ ++rit, --index_offset)\r
+ {\r
+ signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ index_in_vector > 0\r
+ && index_in_vector < pc.offsetted_count\r
+ );\r
+\r
+ pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point);\r
+ pc.offsetted_count++;\r
+\r
+ m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset;\r
+ }\r
+ }\r
+ }\r
+\r
+ BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());\r
+#endif\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ static inline void determine_monotonicity(piece& pc,\r
+ robust_point_type const& current,\r
+ robust_point_type const& next)\r
+ {\r
+ if (geometry::get<Dimension>(current) >= geometry::get<Dimension>(next))\r
+ {\r
+ pc.is_monotonic_increasing[Dimension] = false;\r
+ }\r
+ if (geometry::get<Dimension>(current) <= geometry::get<Dimension>(next))\r
+ {\r
+ pc.is_monotonic_decreasing[Dimension] = false;\r
+ }\r
+ }\r
+\r
+ static inline void determine_properties(piece& pc)\r
+ {\r
+ pc.is_monotonic_increasing[0] = true;\r
+ pc.is_monotonic_increasing[1] = true;\r
+ pc.is_monotonic_decreasing[0] = true;\r
+ pc.is_monotonic_decreasing[1] = true;\r
+\r
+ pc.is_convex = geometry::is_convex(pc.robust_ring);\r
+\r
+ if (pc.offsetted_count < 2)\r
+ {\r
+ return;\r
+ }\r
+\r
+ typename robust_ring_type::const_iterator current = pc.robust_ring.begin();\r
+ typename robust_ring_type::const_iterator next = current + 1;\r
+\r
+ for (signed_size_type i = 1; i < pc.offsetted_count; i++)\r
+ {\r
+ determine_monotonicity<0>(pc, *current, *next);\r
+ determine_monotonicity<1>(pc, *current, *next);\r
+ current = next;\r
+ ++next;\r
+ }\r
+ }\r
+\r
+ void determine_properties()\r
+ {\r
+ for (typename piece_vector_type::iterator it = boost::begin(m_pieces);\r
+ it != boost::end(m_pieces);\r
+ ++it)\r
+ {\r
+ determine_properties(*it);\r
+ }\r
+ }\r
+\r
+ inline void reverse_negative_robust_rings()\r
+ {\r
+ for (typename piece_vector_type::iterator it = boost::begin(m_pieces);\r
+ it != boost::end(m_pieces);\r
+ ++it)\r
+ {\r
+ piece& pc = *it;\r
+ if (geometry::area(pc.robust_ring) < 0)\r
+ {\r
+ // Rings can be ccw:\r
+ // - in a concave piece\r
+ // - in a line-buffer with a negative buffer-distance\r
+ std::reverse(pc.robust_ring.begin(), pc.robust_ring.end());\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void prepare_buffered_point_piece(piece& pc)\r
+ {\r
+ // create monotonic sections in y-dimension\r
+ typedef boost::mpl::vector_c<std::size_t, 1> dimensions;\r
+ geometry::sectionalize<false, dimensions>(pc.robust_ring,\r
+ detail::no_rescale_policy(), pc.sections);\r
+\r
+ // Determine min/max radius\r
+ typedef geometry::model::referring_segment<robust_point_type const>\r
+ robust_segment_type;\r
+\r
+ typename robust_ring_type::const_iterator current = pc.robust_ring.begin();\r
+ typename robust_ring_type::const_iterator next = current + 1;\r
+\r
+ for (signed_size_type i = 1; i < pc.offsetted_count; i++)\r
+ {\r
+ robust_segment_type s(*current, *next);\r
+ robust_comparable_radius_type const d\r
+ = geometry::comparable_distance(pc.robust_center, s);\r
+\r
+ if (i == 1 || d < pc.robust_min_comparable_radius)\r
+ {\r
+ pc.robust_min_comparable_radius = d;\r
+ }\r
+ if (i == 1 || d > pc.robust_max_comparable_radius)\r
+ {\r
+ pc.robust_max_comparable_radius = d;\r
+ }\r
+\r
+ current = next;\r
+ ++next;\r
+ }\r
+ }\r
+\r
+ inline void prepare_buffered_point_pieces()\r
+ {\r
+ for (typename piece_vector_type::iterator it = boost::begin(m_pieces);\r
+ it != boost::end(m_pieces);\r
+ ++it)\r
+ {\r
+ if (it->type == geometry::strategy::buffer::buffered_point)\r
+ {\r
+ prepare_buffered_point_piece(*it);\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void get_turns()\r
+ {\r
+ for(typename boost::range_iterator<sections_type>::type it\r
+ = boost::begin(monotonic_sections);\r
+ it != boost::end(monotonic_sections);\r
+ ++it)\r
+ {\r
+ enlarge_box(it->bounding_box, 1);\r
+ }\r
+\r
+ {\r
+ // Calculate the turns\r
+ piece_turn_visitor\r
+ <\r
+ piece_vector_type,\r
+ buffered_ring_collection<buffered_ring<Ring> >,\r
+ turn_vector_type,\r
+ RobustPolicy\r
+ > visitor(m_pieces, offsetted_rings, m_turns, m_robust_policy);\r
+\r
+ geometry::partition\r
+ <\r
+ robust_box_type,\r
+ detail::section::get_section_box,\r
+ detail::section::overlaps_section_box\r
+ >::apply(monotonic_sections, visitor);\r
+ }\r
+\r
+ insert_rescaled_piece_turns();\r
+\r
+ reverse_negative_robust_rings();\r
+\r
+ determine_properties();\r
+\r
+ prepare_buffered_point_pieces();\r
+\r
+ {\r
+ // Check if it is inside any of the pieces\r
+ turn_in_piece_visitor\r
+ <\r
+ turn_vector_type, piece_vector_type\r
+ > visitor(m_turns, m_pieces);\r
+\r
+ geometry::partition\r
+ <\r
+ robust_box_type,\r
+ turn_get_box, turn_ovelaps_box,\r
+ piece_get_box, piece_ovelaps_box\r
+ >::apply(m_turns, m_pieces, visitor);\r
+\r
+ }\r
+ }\r
+\r
+ inline void start_new_ring()\r
+ {\r
+ signed_size_type const n = static_cast<signed_size_type>(offsetted_rings.size());\r
+ current_segment_id.source_index = 0;\r
+ current_segment_id.multi_index = n;\r
+ current_segment_id.ring_index = -1;\r
+ current_segment_id.segment_index = 0;\r
+\r
+ offsetted_rings.resize(n + 1);\r
+ current_robust_ring.clear();\r
+\r
+ m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces));\r
+ }\r
+\r
+ inline void abort_ring()\r
+ {\r
+ // Remove all created pieces for this ring, sections, last offsetted\r
+ while (! m_pieces.empty()\r
+ && m_pieces.back().first_seg_id.multi_index\r
+ == current_segment_id.multi_index)\r
+ {\r
+ m_pieces.erase(m_pieces.end() - 1);\r
+ }\r
+\r
+ while (! monotonic_sections.empty()\r
+ && monotonic_sections.back().ring_id.multi_index\r
+ == current_segment_id.multi_index)\r
+ {\r
+ monotonic_sections.erase(monotonic_sections.end() - 1);\r
+ }\r
+\r
+ offsetted_rings.erase(offsetted_rings.end() - 1);\r
+ current_robust_ring.clear();\r
+\r
+ m_first_piece_index = -1;\r
+ }\r
+\r
+ inline void update_closing_point()\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(! offsetted_rings.empty());\r
+ buffered_ring<Ring>& added = offsetted_rings.back();\r
+ if (! boost::empty(added))\r
+ {\r
+ range::back(added) = range::front(added);\r
+ }\r
+ }\r
+\r
+ inline void update_last_point(point_type const& p,\r
+ buffered_ring<Ring>& ring)\r
+ {\r
+ // For the first point of a new piece, and there were already\r
+ // points in the offsetted ring, for some piece types the first point\r
+ // is a duplicate of the last point of the previous piece.\r
+\r
+ // TODO: disable that, that point should not be added\r
+\r
+ // For now, it is made equal because due to numerical instability,\r
+ // it can be a tiny bit off, possibly causing a self-intersection\r
+\r
+ BOOST_GEOMETRY_ASSERT(boost::size(m_pieces) > 0);\r
+ if (! ring.empty()\r
+ && current_segment_id.segment_index\r
+ == m_pieces.back().first_seg_id.segment_index)\r
+ {\r
+ ring.back() = p;\r
+ }\r
+ }\r
+\r
+ inline void set_piece_center(point_type const& center)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(! m_pieces.empty());\r
+ geometry::recalculate(m_pieces.back().robust_center, center,\r
+ m_robust_policy);\r
+ }\r
+\r
+ inline void finish_ring(strategy::buffer::result_code code,\r
+ bool is_interior = false, bool has_interiors = false)\r
+ {\r
+ if (code == strategy::buffer::result_error_numerical)\r
+ {\r
+ abort_ring();\r
+ return;\r
+ }\r
+\r
+ if (m_first_piece_index == -1)\r
+ {\r
+ return;\r
+ }\r
+\r
+ if (m_first_piece_index < static_cast<signed_size_type>(boost::size(m_pieces)))\r
+ {\r
+ // If piece was added\r
+ // Reassign left-of-first and right-of-last\r
+ geometry::range::at(m_pieces, m_first_piece_index).left_index\r
+ = static_cast<signed_size_type>(boost::size(m_pieces)) - 1;\r
+ geometry::range::back(m_pieces).right_index = m_first_piece_index;\r
+ }\r
+ m_first_piece_index = -1;\r
+\r
+ update_closing_point();\r
+\r
+ if (! current_robust_ring.empty())\r
+ {\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ geometry::equals(current_robust_ring.front(),\r
+ current_robust_ring.back())\r
+ );\r
+\r
+ robust_originals.push_back(\r
+ robust_original(current_robust_ring,\r
+ is_interior, has_interiors));\r
+ }\r
+ }\r
+\r
+ inline void set_current_ring_concave()\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);\r
+ offsetted_rings.back().has_concave = true;\r
+ }\r
+\r
+ inline signed_size_type add_point(point_type const& p)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0);\r
+\r
+ buffered_ring<Ring>& current_ring = offsetted_rings.back();\r
+ update_last_point(p, current_ring);\r
+\r
+ current_segment_id.segment_index++;\r
+ current_ring.push_back(p);\r
+ return static_cast<signed_size_type>(current_ring.size());\r
+ }\r
+\r
+ //-------------------------------------------------------------------------\r
+\r
+ inline piece& create_piece(strategy::buffer::piece_type type,\r
+ bool decrease_segment_index_by_one)\r
+ {\r
+ if (type == strategy::buffer::buffered_concave)\r
+ {\r
+ offsetted_rings.back().has_concave = true;\r
+ }\r
+\r
+ piece pc;\r
+ pc.type = type;\r
+ pc.index = static_cast<signed_size_type>(boost::size(m_pieces));\r
+\r
+ current_segment_id.piece_index = pc.index;\r
+\r
+ pc.first_seg_id = current_segment_id;\r
+\r
+\r
+ // Assign left/right (for first/last piece per ring they will be re-assigned later)\r
+ pc.left_index = pc.index - 1;\r
+ pc.right_index = pc.index + 1;\r
+\r
+ std::size_t const n = boost::size(offsetted_rings.back());\r
+ pc.first_seg_id.segment_index = decrease_segment_index_by_one ? n - 1 : n;\r
+ pc.last_segment_index = pc.first_seg_id.segment_index;\r
+\r
+ m_pieces.push_back(pc);\r
+ return m_pieces.back();\r
+ }\r
+\r
+ inline void init_rescale_piece(piece& pc, std::size_t helper_points_size)\r
+ {\r
+ if (pc.first_seg_id.segment_index < 0)\r
+ {\r
+ // This indicates an error situation: an earlier piece was empty\r
+ // It currently does not happen\r
+ // std::cout << "EMPTY " << pc.type << " " << pc.index << " " << pc.first_seg_id.multi_index << std::endl;\r
+ pc.offsetted_count = 0;\r
+ return;\r
+ }\r
+\r
+ BOOST_GEOMETRY_ASSERT(pc.first_seg_id.multi_index >= 0);\r
+ BOOST_GEOMETRY_ASSERT(pc.last_segment_index >= 0);\r
+\r
+ pc.offsetted_count = pc.last_segment_index - pc.first_seg_id.segment_index;\r
+ BOOST_GEOMETRY_ASSERT(pc.offsetted_count >= 0);\r
+\r
+ pc.robust_ring.reserve(pc.offsetted_count + helper_points_size);\r
+\r
+ // Add rescaled offsetted segments\r
+ {\r
+ buffered_ring<Ring> const& ring = offsetted_rings[pc.first_seg_id.multi_index];\r
+\r
+ typedef typename boost::range_iterator<const buffered_ring<Ring> >::type it_type;\r
+ for (it_type it = boost::begin(ring) + pc.first_seg_id.segment_index;\r
+ it != boost::begin(ring) + pc.last_segment_index;\r
+ ++it)\r
+ {\r
+ robust_point_type point;\r
+ geometry::recalculate(point, *it, m_robust_policy);\r
+ pc.robust_ring.push_back(point);\r
+ }\r
+ }\r
+ }\r
+\r
+ inline robust_point_type add_helper_point(piece& pc, const point_type& point)\r
+ {\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS)\r
+ pc.helper_points.push_back(point);\r
+#endif\r
+\r
+ robust_point_type rob_point;\r
+ geometry::recalculate(rob_point, point, m_robust_policy);\r
+ pc.robust_ring.push_back(rob_point);\r
+ return rob_point;\r
+ }\r
+\r
+ // TODO: this is shared with sectionalize, move to somewhere else (assign?)\r
+ template <typename Box, typename Value>\r
+ inline void enlarge_box(Box& box, Value value)\r
+ {\r
+ geometry::set<0, 0>(box, geometry::get<0, 0>(box) - value);\r
+ geometry::set<0, 1>(box, geometry::get<0, 1>(box) - value);\r
+ geometry::set<1, 0>(box, geometry::get<1, 0>(box) + value);\r
+ geometry::set<1, 1>(box, geometry::get<1, 1>(box) + value);\r
+ }\r
+\r
+ inline void calculate_robust_envelope(piece& pc)\r
+ {\r
+ if (pc.offsetted_count == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ geometry::envelope(pc.robust_ring, pc.robust_envelope);\r
+\r
+ geometry::assign_inverse(pc.robust_offsetted_envelope);\r
+ for (signed_size_type i = 0; i < pc.offsetted_count; i++)\r
+ {\r
+ geometry::expand(pc.robust_offsetted_envelope, pc.robust_ring[i]);\r
+ }\r
+\r
+ // Take roundings into account, enlarge boxes with 1 integer\r
+ enlarge_box(pc.robust_envelope, 1);\r
+ enlarge_box(pc.robust_offsetted_envelope, 1);\r
+ }\r
+\r
+ inline void sectionalize(piece& pc)\r
+ {\r
+\r
+ buffered_ring<Ring> const& ring = offsetted_rings.back();\r
+\r
+ typedef geometry::detail::sectionalize::sectionalize_part\r
+ <\r
+ point_type,\r
+ boost::mpl::vector_c<std::size_t, 0, 1> // x,y dimension\r
+ > sectionalizer;\r
+\r
+ // Create a ring-identifier. The source-index is the piece index\r
+ // The multi_index is as in this collection (the ring), but not used here\r
+ // The ring_index is not used\r
+ ring_identifier ring_id(pc.index, pc.first_seg_id.multi_index, -1);\r
+\r
+ sectionalizer::apply(monotonic_sections,\r
+ boost::begin(ring) + pc.first_seg_id.segment_index,\r
+ boost::begin(ring) + pc.last_segment_index,\r
+ m_robust_policy,\r
+ ring_id, 10);\r
+ }\r
+\r
+ inline void finish_piece(piece& pc)\r
+ {\r
+ init_rescale_piece(pc, 0u);\r
+ calculate_robust_envelope(pc);\r
+ sectionalize(pc);\r
+ }\r
+\r
+ inline void finish_piece(piece& pc,\r
+ const point_type& point1,\r
+ const point_type& point2,\r
+ const point_type& point3)\r
+ {\r
+ init_rescale_piece(pc, 3u);\r
+ if (pc.offsetted_count == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ add_helper_point(pc, point1);\r
+ robust_point_type mid_point = add_helper_point(pc, point2);\r
+ add_helper_point(pc, point3);\r
+ calculate_robust_envelope(pc);\r
+ sectionalize(pc);\r
+\r
+ current_robust_ring.push_back(mid_point);\r
+ }\r
+\r
+ inline void finish_piece(piece& pc,\r
+ const point_type& point1,\r
+ const point_type& point2,\r
+ const point_type& point3,\r
+ const point_type& point4)\r
+ {\r
+ init_rescale_piece(pc, 4u);\r
+ add_helper_point(pc, point1);\r
+ robust_point_type mid_point2 = add_helper_point(pc, point2);\r
+ robust_point_type mid_point1 = add_helper_point(pc, point3);\r
+ add_helper_point(pc, point4);\r
+ sectionalize(pc);\r
+ calculate_robust_envelope(pc);\r
+\r
+ // Add mid-points in other order to current helper_ring\r
+ current_robust_ring.push_back(mid_point1);\r
+ current_robust_ring.push_back(mid_point2);\r
+ }\r
+\r
+ inline void add_piece(strategy::buffer::piece_type type, point_type const& p,\r
+ point_type const& b1, point_type const& b2)\r
+ {\r
+ piece& pc = create_piece(type, false);\r
+ add_point(b1);\r
+ pc.last_segment_index = add_point(b2);\r
+ finish_piece(pc, b2, p, b1);\r
+ }\r
+\r
+ template <typename Range>\r
+ inline void add_range_to_piece(piece& pc, Range const& range, bool add_front)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u);\r
+\r
+ typename Range::const_iterator it = boost::begin(range);\r
+\r
+ // If it follows a non-join (so basically the same piece-type) point b1 should be added.\r
+ // There should be two intersections later and it should be discarded.\r
+ // But for now we need it to calculate intersections\r
+ if (add_front)\r
+ {\r
+ add_point(*it);\r
+ }\r
+\r
+ for (++it; it != boost::end(range); ++it)\r
+ {\r
+ pc.last_segment_index = add_point(*it);\r
+ }\r
+ }\r
+\r
+\r
+ template <typename Range>\r
+ inline void add_piece(strategy::buffer::piece_type type, Range const& range,\r
+ bool decrease_segment_index_by_one)\r
+ {\r
+ piece& pc = create_piece(type, decrease_segment_index_by_one);\r
+\r
+ if (boost::size(range) > 0u)\r
+ {\r
+ add_range_to_piece(pc, range, offsetted_rings.back().empty());\r
+ }\r
+ finish_piece(pc);\r
+ }\r
+\r
+ template <typename Range>\r
+ inline void add_side_piece(point_type const& p1, point_type const& p2,\r
+ Range const& range, bool first)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u);\r
+\r
+ piece& pc = create_piece(strategy::buffer::buffered_segment, ! first);\r
+ add_range_to_piece(pc, range, first);\r
+ finish_piece(pc, range.back(), p2, p1, range.front());\r
+ }\r
+\r
+ template <typename Range>\r
+ inline void add_piece(strategy::buffer::piece_type type,\r
+ point_type const& p, Range const& range)\r
+ {\r
+ piece& pc = create_piece(type, true);\r
+\r
+ if (boost::size(range) > 0u)\r
+ {\r
+ add_range_to_piece(pc, range, offsetted_rings.back().empty());\r
+ finish_piece(pc, range.back(), p, range.front());\r
+ }\r
+ else\r
+ {\r
+ finish_piece(pc);\r
+ }\r
+ }\r
+\r
+ template <typename EndcapStrategy, typename Range>\r
+ inline void add_endcap(EndcapStrategy const& strategy, Range const& range,\r
+ point_type const& end_point)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+\r
+ if (range.empty())\r
+ {\r
+ return;\r
+ }\r
+ strategy::buffer::piece_type pt = strategy.get_piece_type();\r
+ if (pt == strategy::buffer::buffered_flat_end)\r
+ {\r
+ // It is flat, should just be added, without helper segments\r
+ add_piece(pt, range, true);\r
+ }\r
+ else\r
+ {\r
+ // Normal case, it has an "inside", helper segments should be added\r
+ add_piece(pt, end_point, range);\r
+ }\r
+ }\r
+\r
+ //-------------------------------------------------------------------------\r
+\r
+ inline void enrich()\r
+ {\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Ring>::type\r
+ >::type side_strategy_type;\r
+\r
+ enrich_intersection_points<false, false, overlay_buffer>(m_turns,\r
+ m_clusters, offsetted_rings, offsetted_rings,\r
+ m_robust_policy, side_strategy_type());\r
+ }\r
+\r
+ // Discards all rings which do have not-OK intersection points only.\r
+ // Those can never be traversed and should not be part of the output.\r
+ inline void discard_rings()\r
+ {\r
+ for (typename boost::range_iterator<turn_vector_type const>::type it =\r
+ boost::begin(m_turns); it != boost::end(m_turns); ++it)\r
+ {\r
+ if (it->location != location_ok)\r
+ {\r
+ offsetted_rings[it->operations[0].seg_id.multi_index].has_discarded_intersections = true;\r
+ offsetted_rings[it->operations[1].seg_id.multi_index].has_discarded_intersections = true;\r
+ }\r
+ else\r
+ {\r
+ offsetted_rings[it->operations[0].seg_id.multi_index].has_accepted_intersections = true;\r
+ offsetted_rings[it->operations[1].seg_id.multi_index].has_accepted_intersections = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ inline bool point_coveredby_original(point_type const& point)\r
+ {\r
+ robust_point_type any_point;\r
+ geometry::recalculate(any_point, point, m_robust_policy);\r
+\r
+ signed_size_type count_in_original = 0;\r
+\r
+ // Check of the robust point of this outputted ring is in\r
+ // any of the robust original rings\r
+ // This can go quadratic if the input has many rings, and there\r
+ // are many untouched deflated rings around\r
+ for (typename std::vector<robust_original>::const_iterator it\r
+ = robust_originals.begin();\r
+ it != robust_originals.end();\r
+ ++it)\r
+ {\r
+ robust_original const& original = *it;\r
+ if (detail::disjoint::disjoint_point_box(any_point,\r
+ original.m_box))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ int const geometry_code\r
+ = detail::within::point_in_geometry(any_point,\r
+ original.m_ring);\r
+\r
+ if (geometry_code == -1)\r
+ {\r
+ // Outside, continue\r
+ continue;\r
+ }\r
+\r
+ // Apply for possibly nested interior rings\r
+ if (original.m_is_interior)\r
+ {\r
+ count_in_original--;\r
+ }\r
+ else if (original.m_has_interiors)\r
+ {\r
+ count_in_original++;\r
+ }\r
+ else\r
+ {\r
+ // Exterior ring without interior rings\r
+ return true;\r
+ }\r
+ }\r
+ return count_in_original > 0;\r
+ }\r
+\r
+ // For a deflate, all rings around inner rings which are untouched\r
+ // (no intersections/turns) and which are OUTSIDE the original should\r
+ // be discarded\r
+ inline void discard_nonintersecting_deflated_rings()\r
+ {\r
+ for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it\r
+ = boost::begin(offsetted_rings);\r
+ it != boost::end(offsetted_rings);\r
+ ++it)\r
+ {\r
+ buffered_ring<Ring>& ring = *it;\r
+ if (! ring.has_intersections()\r
+ && boost::size(ring) > 0u\r
+ && geometry::area(ring) < 0)\r
+ {\r
+ if (! point_coveredby_original(geometry::range::front(ring)))\r
+ {\r
+ ring.is_untouched_outside_original = true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void block_turns()\r
+ {\r
+ // To fix left-turn issues like #rt_u13\r
+ // But currently it causes more other issues than it fixes\r
+// m_turns.erase\r
+// (\r
+// std::remove_if(boost::begin(m_turns), boost::end(m_turns),\r
+// redundant_turn()),\r
+// boost::end(m_turns)\r
+// );\r
+\r
+ for (typename boost::range_iterator<turn_vector_type>::type it =\r
+ boost::begin(m_turns); it != boost::end(m_turns); ++it)\r
+ {\r
+ buffer_turn_info_type& turn = *it;\r
+ if (turn.location != location_ok)\r
+ {\r
+ // Discard this turn (don't set it to blocked to avoid colocated\r
+ // clusters being discarded afterwards\r
+ turn.discarded = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void traverse()\r
+ {\r
+ typedef detail::overlay::traverse\r
+ <\r
+ false, false,\r
+ buffered_ring_collection<buffered_ring<Ring> >,\r
+ buffered_ring_collection<buffered_ring<Ring > >,\r
+ overlay_buffer,\r
+ backtrack_for_buffer\r
+ > traverser;\r
+\r
+ traversed_rings.clear();\r
+ buffer_overlay_visitor visitor;\r
+ traverser::apply(offsetted_rings, offsetted_rings,\r
+ m_robust_policy, m_turns, traversed_rings,\r
+ m_clusters, visitor);\r
+ }\r
+\r
+ inline void reverse()\r
+ {\r
+ for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it = boost::begin(offsetted_rings);\r
+ it != boost::end(offsetted_rings);\r
+ ++it)\r
+ {\r
+ if (! it->has_intersections())\r
+ {\r
+ std::reverse(it->begin(), it->end());\r
+ }\r
+ }\r
+ for (typename boost::range_iterator<buffered_ring_collection<Ring> >::type\r
+ it = boost::begin(traversed_rings);\r
+ it != boost::end(traversed_rings);\r
+ ++it)\r
+ {\r
+ std::reverse(it->begin(), it->end());\r
+ }\r
+\r
+ }\r
+\r
+ template <typename GeometryOutput, typename OutputIterator>\r
+ inline OutputIterator assign(OutputIterator out) const\r
+ {\r
+ typedef detail::overlay::ring_properties<point_type> properties;\r
+\r
+ std::map<ring_identifier, properties> selected;\r
+\r
+ // Select all rings which do not have any self-intersection\r
+ // Inner rings, for deflate, which do not have intersections, and\r
+ // which are outside originals, are skipped\r
+ // (other ones should be traversed)\r
+ signed_size_type index = 0;\r
+ for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);\r
+ it != boost::end(offsetted_rings);\r
+ ++it, ++index)\r
+ {\r
+ if (! it->has_intersections()\r
+ && ! it->is_untouched_outside_original)\r
+ {\r
+ properties p = properties(*it);\r
+ if (p.valid)\r
+ {\r
+ ring_identifier id(0, index, -1);\r
+ selected[id] = p;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Select all created rings\r
+ index = 0;\r
+ for (typename boost::range_iterator<buffered_ring_collection<Ring> const>::type\r
+ it = boost::begin(traversed_rings);\r
+ it != boost::end(traversed_rings);\r
+ ++it, ++index)\r
+ {\r
+ properties p = properties(*it);\r
+ if (p.valid)\r
+ {\r
+ ring_identifier id(2, index, -1);\r
+ selected[id] = p;\r
+ }\r
+ }\r
+\r
+ detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);\r
+ return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+struct buffered_ring_collection_tag : polygonal_tag, multi_tag\r
+{};\r
+\r
+\r
+template <typename Ring>\r
+struct buffered_ring : public Ring\r
+{\r
+ bool has_concave;\r
+ bool has_accepted_intersections;\r
+ bool has_discarded_intersections;\r
+ bool is_untouched_outside_original;\r
+\r
+ inline buffered_ring()\r
+ : has_concave(false)\r
+ , has_accepted_intersections(false)\r
+ , has_discarded_intersections(false)\r
+ , is_untouched_outside_original(false)\r
+ {}\r
+\r
+ inline bool discarded() const\r
+ {\r
+ return has_discarded_intersections && ! has_accepted_intersections;\r
+ }\r
+ inline bool has_intersections() const\r
+ {\r
+ return has_discarded_intersections || has_accepted_intersections;\r
+ }\r
+};\r
+\r
+// This is a collection now special for overlay (needs vector of rings)\r
+template <typename Ring>\r
+struct buffered_ring_collection : public std::vector<Ring>\r
+{\r
+};\r
+\r
+}} // namespace detail::buffer\r
+\r
+\r
+// Turn off concept checking (for now)\r
+namespace dispatch\r
+{\r
+template <typename Geometry, bool IsConst>\r
+struct check<Geometry, detail::buffer::buffered_ring_collection_tag, IsConst>\r
+{\r
+};\r
+\r
+}\r
+\r
+\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+// Register the types\r
+namespace traits\r
+{\r
+\r
+\r
+template <typename Ring>\r
+struct tag<geometry::detail::buffer::buffered_ring<Ring> >\r
+{\r
+ typedef ring_tag type;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct point_order<geometry::detail::buffer::buffered_ring<Ring> >\r
+{\r
+ static const order_selector value = geometry::point_order<Ring>::value;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct closure<geometry::detail::buffer::buffered_ring<Ring> >\r
+{\r
+ static const closure_selector value = geometry::closure<Ring>::value;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct point_type<geometry::detail::buffer::buffered_ring_collection<Ring> >\r
+{\r
+ typedef typename geometry::point_type<Ring>::type type;\r
+};\r
+\r
+template <typename Ring>\r
+struct tag<geometry::detail::buffer::buffered_ring_collection<Ring> >\r
+{\r
+ typedef geometry::detail::buffer::buffered_ring_collection_tag type;\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+\r
+\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename Ring>\r
+struct ring_type\r
+<\r
+ detail::buffer::buffered_ring_collection_tag,\r
+ detail::buffer::buffered_ring_collection<Ring>\r
+>\r
+{\r
+ typedef Ring type;\r
+};\r
+\r
+\r
+// There is a specific tag, so this specialization cannot be placed in traits\r
+template <typename Ring>\r
+struct point_order<detail::buffer::buffered_ring_collection_tag,\r
+ geometry::detail::buffer::buffered_ring_collection\r
+ <\r
+ geometry::detail::buffer::buffered_ring<Ring>\r
+ > >\r
+{\r
+ static const order_selector value\r
+ = core_dispatch::point_order<ring_tag, Ring>::value;\r
+};\r
+\r
+\r
+}\r
+\r
+\r
+template <>\r
+struct single_tag_of<detail::buffer::buffered_ring_collection_tag>\r
+{\r
+ typedef ring_tag type;\r
+};\r
+\r
+\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename MultiRing,\r
+ bool Reverse,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+struct copy_segment_point\r
+ <\r
+ detail::buffer::buffered_ring_collection_tag,\r
+ MultiRing,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >\r
+ : detail::copy_segments::copy_segment_point_multi\r
+ <\r
+ MultiRing,\r
+ SegmentIdentifier,\r
+ PointOut,\r
+ detail::copy_segments::copy_segment_point_range\r
+ <\r
+ typename boost::range_value<MultiRing>::type,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+template<bool Reverse>\r
+struct copy_segments\r
+ <\r
+ detail::buffer::buffered_ring_collection_tag,\r
+ Reverse\r
+ >\r
+ : detail::copy_segments::copy_segments_multi\r
+ <\r
+ detail::copy_segments::copy_segments_ring<Reverse>\r
+ >\r
+{};\r
+\r
+template <typename Point, typename MultiGeometry>\r
+struct within\r
+<\r
+ Point,\r
+ MultiGeometry,\r
+ point_tag,\r
+ detail::buffer::buffered_ring_collection_tag\r
+>\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Point const& point,\r
+ MultiGeometry const& multi, Strategy const& strategy)\r
+ {\r
+ return detail::within::point_in_geometry(point, multi, strategy) == 1;\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, detail::buffer::buffered_ring_collection_tag>\r
+ : detail::is_empty::multi_is_empty<detail::is_empty::range_is_empty>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct envelope<Geometry, detail::buffer::buffered_ring_collection_tag>\r
+ : detail::envelope::envelope_multi_range\r
+ <\r
+ detail::envelope::envelope_range\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template<>\r
+struct get_ring<detail::buffer::buffered_ring_collection_tag>\r
+{\r
+ template<typename MultiGeometry>\r
+ static inline typename ring_type<MultiGeometry>::type const& apply(\r
+ ring_identifier const& id,\r
+ MultiGeometry const& multi_ring)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ id.multi_index >= 0\r
+ && id.multi_index < int(boost::size(multi_ring))\r
+ );\r
+ return get_ring<ring_tag>::apply(id, multi_ring[id.multi_index]);\r
+ }\r
+};\r
+\r
+}}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+struct buffer_assign_turn\r
+{\r
+ static bool const include_no_turn = false;\r
+ static bool const include_degenerate = false;\r
+ static bool const include_opposite = false;\r
+\r
+ template\r
+ <\r
+ typename Info,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline void apply(Info& info,\r
+ Point1 const& /*p1*/,\r
+ Point2 const& /*p2*/,\r
+ IntersectionInfo const& iinfo)\r
+ {\r
+ info.rob_pi = iinfo.rpi();\r
+ info.rob_pj = iinfo.rpj();\r
+ info.rob_qi = iinfo.rqi();\r
+ info.rob_qj = iinfo.rqj();\r
+ }\r
+\r
+};\r
+#endif\r
+\r
+template\r
+<\r
+ typename Pieces,\r
+ typename Rings,\r
+ typename Turns,\r
+ typename RobustPolicy\r
+>\r
+class piece_turn_visitor\r
+{\r
+ Pieces const& m_pieces;\r
+ Rings const& m_rings;\r
+ Turns& m_turns;\r
+ RobustPolicy const& m_robust_policy;\r
+\r
+ template <typename Piece>\r
+ inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const\r
+ {\r
+ if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return piece1.index == piece2.left_index\r
+ || piece1.index == piece2.right_index;\r
+ }\r
+\r
+ template <typename Piece>\r
+ inline bool is_on_same_convex_ring(Piece const& piece1, Piece const& piece2) const\r
+ {\r
+ if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return ! m_rings[piece1.first_seg_id.multi_index].has_concave;\r
+ }\r
+\r
+ template <typename Range, typename Iterator>\r
+ inline void move_to_next_point(Range const& range, Iterator& next) const\r
+ {\r
+ ++next;\r
+ if (next == boost::end(range))\r
+ {\r
+ next = boost::begin(range) + 1;\r
+ }\r
+ }\r
+\r
+ template <typename Range, typename Iterator>\r
+ inline Iterator next_point(Range const& range, Iterator it) const\r
+ {\r
+ Iterator result = it;\r
+ move_to_next_point(range, result);\r
+ // TODO: we could use either piece-boundaries, or comparison with\r
+ // robust points, to check if the point equals the last one\r
+ while(geometry::equals(*it, *result))\r
+ {\r
+ move_to_next_point(range, result);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ template <std::size_t Dimension, typename Iterator, typename Box>\r
+ inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,\r
+ signed_size_type& index, int dir, Box const& other_bounding_box)\r
+ {\r
+ for(; it_begin != it_beyond\r
+ && it_begin + 1 != it_beyond\r
+ && detail::section::preceding<Dimension>(dir, *(it_begin + 1),\r
+ other_bounding_box, m_robust_policy);\r
+ ++it_begin, index++)\r
+ {}\r
+ }\r
+\r
+ template <std::size_t Dimension, typename Iterator, typename Box>\r
+ inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,\r
+ int dir, Box const& other_bounding_box)\r
+ {\r
+ while (it_beyond != it_begin\r
+ && it_beyond - 1 != it_begin\r
+ && it_beyond - 2 != it_begin)\r
+ {\r
+ if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),\r
+ other_bounding_box, m_robust_policy))\r
+ {\r
+ --it_beyond;\r
+ }\r
+ else\r
+ {\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+ template <typename Piece, typename Section>\r
+ inline void calculate_turns(Piece const& piece1, Piece const& piece2,\r
+ Section const& section1, Section const& section2)\r
+ {\r
+ typedef typename boost::range_value<Rings const>::type ring_type;\r
+ typedef typename boost::range_value<Turns const>::type turn_type;\r
+ typedef typename boost::range_iterator<ring_type const>::type iterator;\r
+\r
+ signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;\r
+ signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;\r
+ if (piece1_first_index < 0 || piece2_first_index < 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ // Get indices of part of offsetted_rings for this monotonic section:\r
+ signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index;\r
+ signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index;\r
+\r
+ // index of last point in section, beyond-end is one further\r
+ signed_size_type const sec1_last_index = piece1_first_index + section1.end_index;\r
+ signed_size_type const sec2_last_index = piece2_first_index + section2.end_index;\r
+\r
+ // get geometry and iterators over these sections\r
+ ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];\r
+ iterator it1_first = boost::begin(ring1) + sec1_first_index;\r
+ iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;\r
+\r
+ ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];\r
+ iterator it2_first = boost::begin(ring2) + sec2_first_index;\r
+ iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;\r
+\r
+ // Set begin/end of monotonic ranges, in both x/y directions\r
+ signed_size_type index1 = sec1_first_index;\r
+ move_begin_iterator<0>(it1_first, it1_beyond, index1,\r
+ section1.directions[0], section2.bounding_box);\r
+ move_end_iterator<0>(it1_first, it1_beyond,\r
+ section1.directions[0], section2.bounding_box);\r
+ move_begin_iterator<1>(it1_first, it1_beyond, index1,\r
+ section1.directions[1], section2.bounding_box);\r
+ move_end_iterator<1>(it1_first, it1_beyond,\r
+ section1.directions[1], section2.bounding_box);\r
+\r
+ signed_size_type index2 = sec2_first_index;\r
+ move_begin_iterator<0>(it2_first, it2_beyond, index2,\r
+ section2.directions[0], section1.bounding_box);\r
+ move_end_iterator<0>(it2_first, it2_beyond,\r
+ section2.directions[0], section1.bounding_box);\r
+ move_begin_iterator<1>(it2_first, it2_beyond, index2,\r
+ section2.directions[1], section1.bounding_box);\r
+ move_end_iterator<1>(it2_first, it2_beyond,\r
+ section2.directions[1], section1.bounding_box);\r
+\r
+ turn_type the_model;\r
+ the_model.operations[0].piece_index = piece1.index;\r
+ the_model.operations[0].seg_id = piece1.first_seg_id;\r
+ the_model.operations[0].seg_id.segment_index = index1; // override\r
+\r
+ iterator it1 = it1_first;\r
+ for (iterator prev1 = it1++;\r
+ it1 != it1_beyond;\r
+ prev1 = it1++, the_model.operations[0].seg_id.segment_index++)\r
+ {\r
+ the_model.operations[1].piece_index = piece2.index;\r
+ the_model.operations[1].seg_id = piece2.first_seg_id;\r
+ the_model.operations[1].seg_id.segment_index = index2; // override\r
+\r
+ iterator next1 = next_point(ring1, it1);\r
+\r
+ iterator it2 = it2_first;\r
+ for (iterator prev2 = it2++;\r
+ it2 != it2_beyond;\r
+ prev2 = it2++, the_model.operations[1].seg_id.segment_index++)\r
+ {\r
+ iterator next2 = next_point(ring2, it2);\r
+\r
+ // TODO: internally get_turn_info calculates robust points.\r
+ // But they are already calculated.\r
+ // We should be able to use them.\r
+ // this means passing them to this visitor,\r
+ // and iterating in sync with them...\r
+ typedef detail::overlay::get_turn_info\r
+ <\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ buffer_assign_turn\r
+#else\r
+ detail::overlay::assign_null_policy\r
+#endif\r
+ > turn_policy;\r
+\r
+ turn_policy::apply(*prev1, *it1, *next1,\r
+ *prev2, *it2, *next2,\r
+ false, false, false, false,\r
+ the_model, m_robust_policy,\r
+ std::back_inserter(m_turns));\r
+ }\r
+ }\r
+ }\r
+\r
+public:\r
+\r
+ piece_turn_visitor(Pieces const& pieces,\r
+ Rings const& ring_collection,\r
+ Turns& turns,\r
+ RobustPolicy const& robust_policy)\r
+ : m_pieces(pieces)\r
+ , m_rings(ring_collection)\r
+ , m_turns(turns)\r
+ , m_robust_policy(robust_policy)\r
+ {}\r
+\r
+ template <typename Section>\r
+ inline void apply(Section const& section1, Section const& section2,\r
+ bool first = true)\r
+ {\r
+ boost::ignore_unused_variable_warning(first);\r
+\r
+ typedef typename boost::range_value<Pieces const>::type piece_type;\r
+ piece_type const& piece1 = m_pieces[section1.ring_id.source_index];\r
+ piece_type const& piece2 = m_pieces[section2.ring_id.source_index];\r
+\r
+ if ( piece1.index == piece2.index\r
+ || is_adjacent(piece1, piece2)\r
+ || is_on_same_convex_ring(piece1, piece2)\r
+ || detail::disjoint::disjoint_box_box(section1.bounding_box,\r
+ section2.bounding_box) )\r
+ {\r
+ return;\r
+ }\r
+\r
+ calculate_turns(piece1, piece2, section1, section2);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP\r
+\r
+\r
+#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+\r
+// TODO: once change this to proper strategy\r
+// It is different from current segment intersection because these are not segments but lines\r
+// If we have the Line concept, we can create a strategy\r
+// Assumes a convex corner\r
+struct line_line_intersection\r
+{\r
+\r
+ template <typename Point>\r
+ static inline strategy::buffer::join_selector apply(Point const& pi, Point const& pj,\r
+ Point const& qi, Point const& qj, Point& ip)\r
+ {\r
+ // See http://mathworld.wolfram.com/Line-LineIntersection.html\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ coordinate_type const denominator\r
+ = determinant<coordinate_type>(get<0>(pi) - get<0>(pj),\r
+ get<1>(pi) - get<1>(pj),\r
+ get<0>(qi) - get<0>(qj),\r
+ get<1>(qi) - get<1>(qj));\r
+\r
+ // Even if the corner was checked before (so it is convex now), that\r
+ // was done on the original geometry. This function runs on the buffered\r
+ // geometries, where sides are generated and might be slightly off. In\r
+ // Floating Point, that slightly might just exceed the limit and we have\r
+ // to check it again.\r
+\r
+ // For round joins, it will not be used at all.\r
+ // For miter joints, there is a miter limit\r
+ // If segments are parallel/collinear we must be distinguish two cases:\r
+ // they continue each other, or they form a spike\r
+ if (math::equals(denominator, coordinate_type()))\r
+ {\r
+ return parallel_continue(get<0>(qj) - get<0>(qi),\r
+ get<1>(qj) - get<1>(qi),\r
+ get<0>(pj) - get<0>(pi),\r
+ get<1>(pj) - get<1>(pi))\r
+ ? strategy::buffer::join_continue\r
+ : strategy::buffer::join_spike\r
+ ;\r
+ }\r
+\r
+ coordinate_type d1 = determinant<coordinate_type>(get<0>(pi), get<1>(pi), get<0>(pj), get<1>(pj));\r
+ coordinate_type d2 = determinant<coordinate_type>(get<0>(qi), get<1>(qi), get<0>(qj), get<1>(qj));\r
+\r
+ double const multiplier = 1.0 / denominator;\r
+\r
+ set<0>(ip, determinant<coordinate_type>(d1, get<0>(pi) - get<0>(pj), d2, get<0>(qi) - get<0>(qj)) * multiplier);\r
+ set<1>(ip, determinant<coordinate_type>(d1, get<1>(pi) - get<1>(pj), d2, get<1>(qi) - get<1>(qj)) * multiplier);\r
+\r
+ return strategy::buffer::join_convex;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+template <typename T>\r
+inline bool parallel_continue(T dx1, T dy1, T dx2, T dy2)\r
+{\r
+ T const dot = dx1 * dx2 + dy1 * dy2;\r
+ return dot > 0;\r
+}\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+struct original_get_box\r
+{\r
+ template <typename Box, typename Original>\r
+ static inline void apply(Box& total, Original const& original)\r
+ {\r
+ geometry::expand(total, original.m_box);\r
+ }\r
+};\r
+\r
+struct original_ovelaps_box\r
+{\r
+ template <typename Box, typename Original>\r
+ static inline bool apply(Box const& box, Original const& original)\r
+ {\r
+ return ! detail::disjoint::disjoint_box_box(box, original.m_box);\r
+ }\r
+};\r
+\r
+struct include_turn_policy\r
+{\r
+ template <typename Turn>\r
+ static inline bool apply(Turn const& turn)\r
+ {\r
+ return turn.location == location_ok;\r
+ }\r
+};\r
+\r
+struct turn_in_original_ovelaps_box\r
+{\r
+ template <typename Box, typename Turn>\r
+ static inline bool apply(Box const& box, Turn const& turn)\r
+ {\r
+ if (turn.location != location_ok || turn.within_original)\r
+ {\r
+ // Skip all points already processed\r
+ return false;\r
+ }\r
+\r
+ return ! geometry::detail::disjoint::disjoint_point_box(\r
+ turn.robust_point, box);\r
+ }\r
+};\r
+\r
+//! Check if specified is in range of specified iterators\r
+//! Return value of strategy (true if we can bail out)\r
+template\r
+<\r
+ typename Strategy,\r
+ typename State,\r
+ typename Point,\r
+ typename Iterator\r
+>\r
+inline bool point_in_range(Strategy& strategy, State& state,\r
+ Point const& point, Iterator begin, Iterator end)\r
+{\r
+ boost::ignore_unused(strategy);\r
+\r
+ Iterator it = begin;\r
+ for (Iterator previous = it++; it != end; ++previous, ++it)\r
+ {\r
+ if (! strategy.apply(point, *previous, *it, state))\r
+ {\r
+ // We're probably on the boundary\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+}\r
+\r
+template\r
+<\r
+ typename Strategy,\r
+ typename State,\r
+ typename Point,\r
+ typename CoordinateType,\r
+ typename Iterator\r
+>\r
+inline bool point_in_section(Strategy& strategy, State& state,\r
+ Point const& point, CoordinateType const& point_x,\r
+ Iterator begin, Iterator end,\r
+ int direction)\r
+{\r
+ if (direction == 0)\r
+ {\r
+ // Not a monotonic section, or no change in X-direction\r
+ return point_in_range(strategy, state, point, begin, end);\r
+ }\r
+\r
+ // We're in a monotonic section in x-direction\r
+ Iterator it = begin;\r
+\r
+ for (Iterator previous = it++; it != end; ++previous, ++it)\r
+ {\r
+ // Depending on sections.direction we can quit for this section\r
+ CoordinateType const previous_x = geometry::get<0>(*previous);\r
+\r
+ if (direction == 1 && point_x < previous_x)\r
+ {\r
+ // Section goes upwards, x increases, point is is below section\r
+ return true;\r
+ }\r
+ else if (direction == -1 && point_x > previous_x)\r
+ {\r
+ // Section goes downwards, x decreases, point is above section\r
+ return true;\r
+ }\r
+\r
+ if (! strategy.apply(point, *previous, *it, state))\r
+ {\r
+ // We're probably on the boundary\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+}\r
+\r
+\r
+template <typename Point, typename Original>\r
+inline int point_in_original(Point const& point, Original const& original)\r
+{\r
+ // The winding strategy is scanning in x direction\r
+ // therefore it's critical to pass direction calculated\r
+ // for x dimension below.\r
+ typedef strategy::within::winding<Point> strategy_type;\r
+\r
+ typename strategy_type::state_type state;\r
+ strategy_type strategy;\r
+\r
+ if (boost::size(original.m_sections) == 0\r
+ || boost::size(original.m_ring) - boost::size(original.m_sections) < 16)\r
+ {\r
+ // There are no sections, or it does not profit to walk over sections\r
+ // instead of over points. Boundary of 16 is arbitrary but can influence\r
+ // performance\r
+ point_in_range(strategy, state, point,\r
+ original.m_ring.begin(), original.m_ring.end());\r
+ return strategy.result(state);\r
+ }\r
+\r
+ typedef typename Original::sections_type sections_type;\r
+ typedef typename boost::range_iterator<sections_type const>::type iterator_type;\r
+ typedef typename boost::range_value<sections_type const>::type section_type;\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ coordinate_type const point_x = geometry::get<0>(point);\r
+\r
+ // Walk through all monotonic sections of this original\r
+ for (iterator_type it = boost::begin(original.m_sections);\r
+ it != boost::end(original.m_sections);\r
+ ++it)\r
+ {\r
+ section_type const& section = *it;\r
+\r
+ if (! section.duplicate\r
+ && section.begin_index < section.end_index\r
+ && point_x >= geometry::get<min_corner, 0>(section.bounding_box)\r
+ && point_x <= geometry::get<max_corner, 0>(section.bounding_box))\r
+ {\r
+ // x-coordinate of point overlaps with section\r
+ if (! point_in_section(strategy, state, point, point_x,\r
+ boost::begin(original.m_ring) + section.begin_index,\r
+ boost::begin(original.m_ring) + section.end_index + 1,\r
+ section.directions[0]))\r
+ {\r
+ // We're probably on the boundary\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return strategy.result(state);\r
+}\r
+\r
+\r
+template <typename Turns>\r
+class turn_in_original_visitor\r
+{\r
+public:\r
+ turn_in_original_visitor(Turns& turns)\r
+ : m_mutable_turns(turns)\r
+ {}\r
+\r
+ template <typename Turn, typename Original>\r
+ inline void apply(Turn const& turn, Original const& original, bool first = true)\r
+ {\r
+ boost::ignore_unused_variable_warning(first);\r
+\r
+ if (turn.location != location_ok || turn.within_original)\r
+ {\r
+ // Skip all points already processed\r
+ return;\r
+ }\r
+\r
+ if (geometry::disjoint(turn.robust_point, original.m_box))\r
+ {\r
+ // Skip all disjoint\r
+ return;\r
+ }\r
+\r
+ int const code = point_in_original(turn.robust_point, original);\r
+\r
+ if (code == -1)\r
+ {\r
+ return;\r
+ }\r
+\r
+ Turn& mutable_turn = m_mutable_turns[turn.turn_index];\r
+\r
+ if (code == 0)\r
+ {\r
+ // On border of original: always discard\r
+ mutable_turn.location = location_discard;\r
+ }\r
+\r
+ // Point is inside an original ring\r
+ if (original.m_is_interior)\r
+ {\r
+ mutable_turn.count_in_original--;\r
+ }\r
+ else if (original.m_has_interiors)\r
+ {\r
+ mutable_turn.count_in_original++;\r
+ }\r
+ else\r
+ {\r
+ // It is an exterior ring and there are no interior rings.\r
+ // Then we are completely ready with this turn\r
+ mutable_turn.within_original = true;\r
+ mutable_turn.count_in_original = 1;\r
+ }\r
+ }\r
+\r
+private :\r
+ Turns& m_mutable_turns;\r
+};\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/arithmetic/dot_product.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/comparable_distance.hpp>\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace buffer\r
+{\r
+\r
+struct piece_get_box\r
+{\r
+ template <typename Box, typename Piece>\r
+ static inline void apply(Box& total, Piece const& piece)\r
+ {\r
+ geometry::expand(total, piece.robust_envelope);\r
+ }\r
+};\r
+\r
+struct piece_ovelaps_box\r
+{\r
+ template <typename Box, typename Piece>\r
+ static inline bool apply(Box const& box, Piece const& piece)\r
+ {\r
+ if (piece.type == strategy::buffer::buffered_flat_end\r
+ || piece.type == strategy::buffer::buffered_concave)\r
+ {\r
+ // Turns cannot be inside a flat end (though they can be on border)\r
+ // Neither we need to check if they are inside concave helper pieces\r
+\r
+ // Skip all pieces not used as soon as possible\r
+ return false;\r
+ }\r
+\r
+ return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);\r
+ }\r
+};\r
+\r
+struct turn_get_box\r
+{\r
+ template <typename Box, typename Turn>\r
+ static inline void apply(Box& total, Turn const& turn)\r
+ {\r
+ geometry::expand(total, turn.robust_point);\r
+ }\r
+};\r
+\r
+struct turn_ovelaps_box\r
+{\r
+ template <typename Box, typename Turn>\r
+ static inline bool apply(Box const& box, Turn const& turn)\r
+ {\r
+ return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box);\r
+ }\r
+};\r
+\r
+\r
+enum analyse_result\r
+{\r
+ analyse_unknown,\r
+ analyse_continue,\r
+ analyse_disjoint,\r
+ analyse_within,\r
+ analyse_on_original_boundary,\r
+ analyse_on_offsetted\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ , analyse_near_offsetted\r
+#endif\r
+};\r
+\r
+template <typename Point>\r
+inline bool in_box(Point const& previous,\r
+ Point const& current, Point const& point)\r
+{\r
+ // Get its box (TODO: this can be prepared-on-demand later)\r
+ typedef geometry::model::box<Point> box_type;\r
+ box_type box;\r
+ geometry::assign_inverse(box);\r
+ geometry::expand(box, previous);\r
+ geometry::expand(box, current);\r
+\r
+ return geometry::covered_by(point, box);\r
+}\r
+\r
+template <typename Point, typename Turn>\r
+inline analyse_result check_segment(Point const& previous,\r
+ Point const& current, Turn const& turn,\r
+ bool from_monotonic)\r
+{\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ typedef geometry::model::referring_segment<Point const> segment_type;\r
+ segment_type const p(turn.rob_pi, turn.rob_pj);\r
+ segment_type const q(turn.rob_qi, turn.rob_qj);\r
+ segment_type const r(previous, current);\r
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,\r
+ turn.robust_point);\r
+\r
+ if (side == 0)\r
+ {\r
+ return analyse_on_offsetted;\r
+ }\r
+ if (side == -1 && from_monotonic)\r
+ {\r
+ return analyse_within;\r
+ }\r
+ if (side == 1 && from_monotonic)\r
+ {\r
+ return analyse_disjoint;\r
+ }\r
+ return analyse_continue;\r
+\r
+#else\r
+\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type side_strategy;\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ coordinate_type const twice_area\r
+ = side_strategy::template side_value\r
+ <\r
+ coordinate_type,\r
+ coordinate_type\r
+ >(previous, current, turn.robust_point);\r
+\r
+ if (twice_area == 0)\r
+ {\r
+ // Collinear, only on segment if it is covered by its bbox\r
+ if (in_box(previous, current, turn.robust_point))\r
+ {\r
+ return analyse_on_offsetted;\r
+ }\r
+ }\r
+ else if (twice_area < 0)\r
+ {\r
+ // It is in the triangle right-of the segment where the\r
+ // segment is the hypothenusa. Check if it is close\r
+ // (within rounding-area)\r
+ if (twice_area * twice_area < geometry::comparable_distance(previous, current)\r
+ && in_box(previous, current, turn.robust_point))\r
+ {\r
+ return analyse_near_offsetted;\r
+ }\r
+ else if (from_monotonic)\r
+ {\r
+ return analyse_within;\r
+ }\r
+ }\r
+ else if (twice_area > 0 && from_monotonic)\r
+ {\r
+ // Left of segment\r
+ return analyse_disjoint;\r
+ }\r
+\r
+ // Not monotonic, on left or right side: continue analysing\r
+ return analyse_continue;\r
+#endif\r
+}\r
+\r
+\r
+class analyse_turn_wrt_point_piece\r
+{\r
+public :\r
+ template <typename Turn, typename Piece>\r
+ static inline analyse_result apply(Turn const& turn, Piece const& piece)\r
+ {\r
+ typedef typename Piece::section_type section_type;\r
+ typedef typename Turn::robust_point_type point_type;\r
+ typedef typename geometry::coordinate_type<point_type>::type coordinate_type;\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ typedef geometry::model::referring_segment<point_type const> segment_type;\r
+ segment_type const p(turn.rob_pi, turn.rob_pj);\r
+ segment_type const q(turn.rob_qi, turn.rob_qj);\r
+#else\r
+ typedef strategy::within::winding<point_type> strategy_type;\r
+\r
+ typename strategy_type::state_type state;\r
+ strategy_type strategy;\r
+ boost::ignore_unused(strategy);\r
+#endif\r
+\r
+ BOOST_GEOMETRY_ASSERT(! piece.sections.empty());\r
+\r
+ coordinate_type const point_x = geometry::get<0>(turn.robust_point);\r
+\r
+ for (std::size_t s = 0; s < piece.sections.size(); s++)\r
+ {\r
+ section_type const& section = piece.sections[s];\r
+ // If point within horizontal range of monotonic section:\r
+ if (! section.duplicate\r
+ && section.begin_index < section.end_index\r
+ && point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1\r
+ && point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)\r
+ {\r
+ for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)\r
+ {\r
+ point_type const& previous = piece.robust_ring[i - 1];\r
+ point_type const& current = piece.robust_ring[i];\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+\r
+ // First check if it is in range - if it is not, the\r
+ // expensive side_of_intersection does not need to be\r
+ // applied\r
+ coordinate_type x1 = geometry::get<0>(previous);\r
+ coordinate_type x2 = geometry::get<0>(current);\r
+\r
+ if (x1 > x2)\r
+ {\r
+ std::swap(x1, x2);\r
+ }\r
+\r
+ if (point_x >= x1 - 1 && point_x <= x2 + 1)\r
+ {\r
+ segment_type const r(previous, current);\r
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,\r
+ turn.robust_point);\r
+\r
+ // Sections are monotonic in x-dimension\r
+ if (side == 1)\r
+ {\r
+ // Left on segment\r
+ return analyse_disjoint;\r
+ }\r
+ else if (side == 0)\r
+ {\r
+ // Collinear - TODO: check if really on segment\r
+ return analyse_on_offsetted;\r
+ }\r
+ }\r
+#else\r
+ analyse_result code = check_segment(previous, current, turn, false);\r
+ if (code != analyse_continue)\r
+ {\r
+ return code;\r
+ }\r
+\r
+ // Get the state (to determine it is within), we don't have\r
+ // to cover the on-segment case (covered above)\r
+ strategy.apply(turn.robust_point, previous, current, state);\r
+#endif\r
+ }\r
+ }\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ // It is nowhere outside, and not on segment, so it is within\r
+ return analyse_within;\r
+#else\r
+ int const code = strategy.result(state);\r
+ if (code == 1)\r
+ {\r
+ return analyse_within;\r
+ }\r
+ else if (code == -1)\r
+ {\r
+ return analyse_disjoint;\r
+ }\r
+\r
+ // Should normally not occur - on-segment is covered\r
+ return analyse_unknown;\r
+#endif\r
+ }\r
+\r
+};\r
+\r
+class analyse_turn_wrt_piece\r
+{\r
+ template <typename Point, typename Turn>\r
+ static inline analyse_result check_helper_segment(Point const& s1,\r
+ Point const& s2, Turn const& turn,\r
+ bool is_original,\r
+ Point const& offsetted)\r
+ {\r
+ boost::ignore_unused(offsetted);\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ typedef geometry::model::referring_segment<Point const> segment_type;\r
+ segment_type const p(turn.rob_pi, turn.rob_pj);\r
+ segment_type const q(turn.rob_qi, turn.rob_qj);\r
+ segment_type const r(s1, s2);\r
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,\r
+ turn.robust_point);\r
+\r
+ if (side == 1)\r
+ {\r
+ // left of segment\r
+ return analyse_disjoint;\r
+ }\r
+ else if (side == 0)\r
+ {\r
+ // If is collinear, either on segment or before/after\r
+ typedef geometry::model::box<Point> box_type;\r
+\r
+ box_type box;\r
+ geometry::assign_inverse(box);\r
+ geometry::expand(box, s1);\r
+ geometry::expand(box, s2);\r
+\r
+ if (geometry::covered_by(turn.robust_point, box))\r
+ {\r
+ // Points on helper-segments are considered as within\r
+ // Points on original boundary are processed differently\r
+ return is_original\r
+ ? analyse_on_original_boundary\r
+ : analyse_within;\r
+ }\r
+\r
+ // It is collinear but not on the segment. Because these\r
+ // segments are convex, it is outside\r
+ // Unless the offsetted ring is collinear or concave w.r.t.\r
+ // helper-segment but that scenario is not yet supported\r
+ return analyse_disjoint;\r
+ }\r
+\r
+ // right of segment\r
+ return analyse_continue;\r
+#else\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type side_strategy;\r
+\r
+ switch(side_strategy::apply(s1, s2, turn.robust_point))\r
+ {\r
+ case 1 :\r
+ return analyse_disjoint; // left of segment\r
+ case 0 :\r
+ {\r
+ // If is collinear, either on segment or before/after\r
+ typedef geometry::model::box<Point> box_type;\r
+\r
+ box_type box;\r
+ geometry::assign_inverse(box);\r
+ geometry::expand(box, s1);\r
+ geometry::expand(box, s2);\r
+\r
+ if (geometry::covered_by(turn.robust_point, box))\r
+ {\r
+ // It is on the segment\r
+ if (! is_original\r
+ && geometry::comparable_distance(turn.robust_point, offsetted) <= 1)\r
+ {\r
+ // It is close to the offsetted-boundary, take\r
+ // any rounding-issues into account\r
+ return analyse_near_offsetted;\r
+ }\r
+\r
+ // Points on helper-segments are considered as within\r
+ // Points on original boundary are processed differently\r
+ return is_original\r
+ ? analyse_on_original_boundary\r
+ : analyse_within;\r
+ }\r
+\r
+ // It is collinear but not on the segment. Because these\r
+ // segments are convex, it is outside\r
+ // Unless the offsetted ring is collinear or concave w.r.t.\r
+ // helper-segment but that scenario is not yet supported\r
+ return analyse_disjoint;\r
+ }\r
+ break;\r
+ }\r
+\r
+ // right of segment\r
+ return analyse_continue;\r
+#endif\r
+ }\r
+\r
+ template <typename Turn, typename Piece>\r
+ static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)\r
+ {\r
+ typedef typename Turn::robust_point_type point_type;\r
+ geometry::equal_to<point_type> comparator;\r
+\r
+ point_type points[4];\r
+\r
+ signed_size_type helper_count = static_cast<signed_size_type>(piece.robust_ring.size())\r
+ - piece.offsetted_count;\r
+ if (helper_count == 4)\r
+ {\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ points[i] = piece.robust_ring[piece.offsetted_count + i];\r
+ }\r
+ }\r
+ else if (helper_count == 3)\r
+ {\r
+ // Triangular piece, assign points but assign second twice\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ int index = i < 2 ? i : i - 1;\r
+ points[i] = piece.robust_ring[piece.offsetted_count + index];\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Some pieces (e.g. around points) do not have helper segments.\r
+ // Others should have 3 (join) or 4 (side)\r
+ return analyse_continue;\r
+ }\r
+\r
+ // First check point-equality\r
+ point_type const& point = turn.robust_point;\r
+ if (comparator(point, points[0]) || comparator(point, points[3]))\r
+ {\r
+ return analyse_on_offsetted;\r
+ }\r
+ if (comparator(point, points[1]) || comparator(point, points[2]))\r
+ {\r
+ return analyse_on_original_boundary;\r
+ }\r
+\r
+ // Right side of the piece\r
+ analyse_result result\r
+ = check_helper_segment(points[0], points[1], turn,\r
+ false, points[0]);\r
+ if (result != analyse_continue)\r
+ {\r
+ return result;\r
+ }\r
+\r
+ // Left side of the piece\r
+ result = check_helper_segment(points[2], points[3], turn,\r
+ false, points[3]);\r
+ if (result != analyse_continue)\r
+ {\r
+ return result;\r
+ }\r
+\r
+ if (! comparator(points[1], points[2]))\r
+ {\r
+ // Side of the piece at side of original geometry\r
+ result = check_helper_segment(points[1], points[2], turn,\r
+ true, point);\r
+ if (result != analyse_continue)\r
+ {\r
+ return result;\r
+ }\r
+ }\r
+\r
+ // We are within the \/ or |_| shaped piece, where the top is the\r
+ // offsetted ring.\r
+ if (! geometry::covered_by(point, piece.robust_offsetted_envelope))\r
+ {\r
+ // Not in offsetted-area. This makes a cheap check possible\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type\r
+ >::type side_strategy;\r
+\r
+ switch(side_strategy::apply(points[3], points[0], point))\r
+ {\r
+ case 1 : return analyse_disjoint;\r
+ case -1 : return analyse_within;\r
+ case 0 : return analyse_disjoint;\r
+ }\r
+ }\r
+\r
+ return analyse_continue;\r
+ }\r
+\r
+ template <typename Turn, typename Piece, typename Compare>\r
+ static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare)\r
+ {\r
+ typedef typename Piece::piece_robust_ring_type ring_type;\r
+ typedef typename ring_type::const_iterator it_type;\r
+ it_type end = piece.robust_ring.begin() + piece.offsetted_count;\r
+ it_type it = std::lower_bound(piece.robust_ring.begin(),\r
+ end,\r
+ turn.robust_point,\r
+ compare);\r
+\r
+ if (it != end\r
+ && it != piece.robust_ring.begin())\r
+ {\r
+ // iterator points to point larger than point\r
+ // w.r.t. specified direction, and prev points to a point smaller\r
+ // We now know if it is inside/outside\r
+ it_type prev = it - 1;\r
+ return check_segment(*prev, *it, turn, true);\r
+ }\r
+ return analyse_continue;\r
+ }\r
+\r
+public :\r
+ template <typename Turn, typename Piece>\r
+ static inline analyse_result apply(Turn const& turn, Piece const& piece)\r
+ {\r
+ typedef typename Turn::robust_point_type point_type;\r
+ analyse_result code = check_helper_segments(turn, piece);\r
+ if (code != analyse_continue)\r
+ {\r
+ return code;\r
+ }\r
+\r
+ geometry::equal_to<point_type> comparator;\r
+\r
+ if (piece.offsetted_count > 8)\r
+ {\r
+ // If the offset contains some points and is monotonic, we try\r
+ // to avoid walking all points linearly.\r
+ // We try it only once.\r
+ if (piece.is_monotonic_increasing[0])\r
+ {\r
+ code = check_monotonic(turn, piece, geometry::less<point_type, 0>());\r
+ if (code != analyse_continue) return code;\r
+ }\r
+ else if (piece.is_monotonic_increasing[1])\r
+ {\r
+ code = check_monotonic(turn, piece, geometry::less<point_type, 1>());\r
+ if (code != analyse_continue) return code;\r
+ }\r
+ else if (piece.is_monotonic_decreasing[0])\r
+ {\r
+ code = check_monotonic(turn, piece, geometry::greater<point_type, 0>());\r
+ if (code != analyse_continue) return code;\r
+ }\r
+ else if (piece.is_monotonic_decreasing[1])\r
+ {\r
+ code = check_monotonic(turn, piece, geometry::greater<point_type, 1>());\r
+ if (code != analyse_continue) return code;\r
+ }\r
+ }\r
+\r
+ // It is small or not monotonic, walk linearly through offset\r
+ // TODO: this will be combined with winding strategy\r
+\r
+ for (signed_size_type i = 1; i < piece.offsetted_count; i++)\r
+ {\r
+ point_type const& previous = piece.robust_ring[i - 1];\r
+ point_type const& current = piece.robust_ring[i];\r
+\r
+ // The robust ring can contain duplicates\r
+ // (on which any side or side-value would return 0)\r
+ if (! comparator(previous, current))\r
+ {\r
+ code = check_segment(previous, current, turn, false);\r
+ if (code != analyse_continue)\r
+ {\r
+ return code;\r
+ }\r
+ }\r
+ }\r
+\r
+ return analyse_unknown;\r
+ }\r
+\r
+};\r
+\r
+\r
+template <typename Turns, typename Pieces>\r
+class turn_in_piece_visitor\r
+{\r
+ Turns& m_turns; // because partition is currently operating on const input only\r
+ Pieces const& m_pieces; // to check for piece-type\r
+\r
+ template <typename Operation, typename Piece>\r
+ inline bool skip(Operation const& op, Piece const& piece) const\r
+ {\r
+ if (op.piece_index == piece.index)\r
+ {\r
+ return true;\r
+ }\r
+ Piece const& pc = m_pieces[op.piece_index];\r
+ if (pc.left_index == piece.index || pc.right_index == piece.index)\r
+ {\r
+ if (pc.type == strategy::buffer::buffered_flat_end)\r
+ {\r
+ // If it is a flat end, don't compare against its neighbor:\r
+ // it will always be located on one of the helper segments\r
+ return true;\r
+ }\r
+ if (pc.type == strategy::buffer::buffered_concave)\r
+ {\r
+ // If it is concave, the same applies: the IP will be\r
+ // located on one of the helper segments\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ // NOTE: this function returns a side value in {-1, 0, 1}\r
+ template <typename Turn, typename Piece>\r
+ static inline int turn_in_convex_piece(Turn const& turn,\r
+ Piece const& piece)\r
+ {\r
+ typedef typename Turn::robust_point_type point_type;\r
+ typedef typename Piece::piece_robust_ring_type ring_type;\r
+ typedef geometry::model::referring_segment<point_type const> segment;\r
+\r
+ segment const p(turn.rob_pi, turn.rob_pj);\r
+ segment const q(turn.rob_qi, turn.rob_qj);\r
+\r
+ typedef typename boost::range_iterator<ring_type const>::type iterator_type;\r
+ iterator_type it = boost::begin(piece.robust_ring);\r
+ iterator_type end = boost::end(piece.robust_ring);\r
+\r
+ // A robust ring is always closed, and always clockwise\r
+ for (iterator_type previous = it++; it != end; ++previous, ++it)\r
+ {\r
+ geometry::equal_to<point_type> comparator;\r
+ if (comparator(*previous, *it))\r
+ {\r
+ // Points are the same\r
+ continue;\r
+ }\r
+\r
+ segment r(*previous, *it);\r
+\r
+ int const side = strategy::side::side_of_intersection::apply(p, q, r,\r
+ turn.robust_point);\r
+\r
+ if (side == 1)\r
+ {\r
+ // IP is left of segment, so it is outside\r
+ return -1; // outside\r
+ }\r
+ else if (side == 0)\r
+ {\r
+ // IP is collinear with segment. TODO: we should analyze this further\r
+ // For now we use the fallback point\r
+ if (in_box(*previous, *it, turn.robust_point))\r
+ {\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ return -1; // outside\r
+ }\r
+ }\r
+ }\r
+ return 1; // inside\r
+ }\r
+#endif\r
+\r
+\r
+public:\r
+\r
+ inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces)\r
+ : m_turns(turns)\r
+ , m_pieces(pieces)\r
+ {}\r
+\r
+ template <typename Turn, typename Piece>\r
+ inline void apply(Turn const& turn, Piece const& piece, bool first = true)\r
+ {\r
+ boost::ignore_unused_variable_warning(first);\r
+\r
+ if (turn.count_within > 0)\r
+ {\r
+ // Already inside - no need to check again\r
+ return;\r
+ }\r
+\r
+ if (piece.type == strategy::buffer::buffered_flat_end\r
+ || piece.type == strategy::buffer::buffered_concave)\r
+ {\r
+ // Turns cannot be located within flat-end or concave pieces\r
+ return;\r
+ }\r
+\r
+ if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))\r
+ {\r
+ // Easy check: if the turn is not in the envelope, we can safely return\r
+ return;\r
+ }\r
+\r
+ if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))\r
+ {\r
+ return;\r
+ }\r
+\r
+ // TODO: mutable_piece to make some on-demand preparations in analyse\r
+ Turn& mutable_turn = m_turns[turn.turn_index];\r
+\r
+ if (piece.type == geometry::strategy::buffer::buffered_point)\r
+ {\r
+ // Optimization for buffer around points: if distance from center\r
+ // is not between min/max radius, the result is clear\r
+ typedef typename default_comparable_distance_result\r
+ <\r
+ typename Turn::robust_point_type\r
+ >::type distance_type;\r
+\r
+ distance_type const cd\r
+ = geometry::comparable_distance(piece.robust_center,\r
+ turn.robust_point);\r
+\r
+ if (cd < piece.robust_min_comparable_radius)\r
+ {\r
+ mutable_turn.count_within++;\r
+ return;\r
+ }\r
+ if (cd > piece.robust_max_comparable_radius)\r
+ {\r
+ return;\r
+ }\r
+ }\r
+\r
+ analyse_result analyse_code =\r
+ piece.type == geometry::strategy::buffer::buffered_point\r
+ ? analyse_turn_wrt_point_piece::apply(turn, piece)\r
+ : analyse_turn_wrt_piece::apply(turn, piece);\r
+\r
+ switch(analyse_code)\r
+ {\r
+ case analyse_disjoint :\r
+ return;\r
+ case analyse_on_offsetted :\r
+ mutable_turn.count_on_offsetted++; // value is not used anymore\r
+ return;\r
+ case analyse_on_original_boundary :\r
+ mutable_turn.count_on_original_boundary++;\r
+ return;\r
+ case analyse_within :\r
+ mutable_turn.count_within++;\r
+ return;\r
+#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ case analyse_near_offsetted :\r
+ mutable_turn.count_within_near_offsetted++;\r
+ return;\r
+#endif\r
+ default :\r
+ break;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)\r
+ // We don't know (yet)\r
+ int geometry_code = 0;\r
+ if (piece.is_convex)\r
+ {\r
+ geometry_code = turn_in_convex_piece(turn, piece);\r
+ }\r
+ else\r
+ {\r
+\r
+ // TODO: this point_in_geometry is a performance-bottleneck here and\r
+ // will be replaced completely by extending analyse_piece functionality\r
+ geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);\r
+ }\r
+#else\r
+ int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);\r
+#endif\r
+\r
+ if (geometry_code == 1)\r
+ {\r
+ mutable_turn.count_within++;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::buffer\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+struct calculate_null\r
+{\r
+ template<typename ReturnType, typename Geometry, typename Strategy>\r
+ static inline ReturnType apply(Geometry const& , Strategy const&)\r
+ {\r
+ return ReturnType();\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+class calculate_polygon_sum\r
+{\r
+ template <typename ReturnType, typename Policy, typename Rings, typename Strategy>\r
+ static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)\r
+ {\r
+ ReturnType sum = ReturnType();\r
+ for (typename boost::range_iterator<Rings const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ sum += Policy::apply(*it, strategy);\r
+ }\r
+ return sum;\r
+ }\r
+\r
+public :\r
+ template <typename ReturnType, typename Policy, typename Polygon, typename Strategy>\r
+ static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)\r
+ {\r
+ return Policy::apply(exterior_ring(poly), strategy)\r
+ + sum_interior_rings<ReturnType, Policy>(interior_rings(poly), strategy)\r
+ ;\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/core/addressof.hpp>\r
+#include <boost/core/ref.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace centroid\r
+{\r
+\r
+\r
+// NOTE: There is no need to translate in other coordinate systems than\r
+// cartesian. But if it was needed then one should translate using\r
+// CS-specific technique, e.g. in spherical/geographic a translation\r
+// vector should contain coordinates being multiplies of 2PI or 360 deg.\r
+template <typename Geometry,\r
+ typename CastedTag = typename tag_cast\r
+ <\r
+ typename tag<Geometry>::type,\r
+ areal_tag\r
+ >::type,\r
+ typename CSTag = typename cs_tag<Geometry>::type>\r
+struct translating_transformer\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef boost::reference_wrapper<point_type const> result_type;\r
+\r
+ explicit translating_transformer(Geometry const&) {}\r
+ explicit translating_transformer(point_type const&) {}\r
+\r
+ result_type apply(point_type const& pt) const\r
+ {\r
+ return result_type(pt);\r
+ }\r
+\r
+ template <typename ResPt>\r
+ void apply_reverse(ResPt &) const {}\r
+};\r
+\r
+// Specialization for Areal Geometries in cartesian CS\r
+template <typename Geometry>\r
+struct translating_transformer<Geometry, areal_tag, cartesian_tag>\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef point_type result_type;\r
+ \r
+ explicit translating_transformer(Geometry const& geom)\r
+ : m_origin(NULL)\r
+ {\r
+ geometry::point_iterator<Geometry const>\r
+ pt_it = geometry::points_begin(geom);\r
+ if ( pt_it != geometry::points_end(geom) )\r
+ {\r
+ m_origin = boost::addressof(*pt_it);\r
+ }\r
+ }\r
+\r
+ explicit translating_transformer(point_type const& origin)\r
+ : m_origin(boost::addressof(origin))\r
+ {}\r
+\r
+ result_type apply(point_type const& pt) const\r
+ {\r
+ point_type res = pt;\r
+ if ( m_origin )\r
+ geometry::subtract_point(res, *m_origin);\r
+ return res;\r
+ }\r
+\r
+ template <typename ResPt>\r
+ void apply_reverse(ResPt & res_pt) const\r
+ {\r
+ if ( m_origin )\r
+ geometry::add_point(res_pt, *m_origin);\r
+ }\r
+\r
+ const point_type * m_origin;\r
+};\r
+\r
+\r
+}} // namespace detail::centroid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+// Check whether (each element of) an iterator range satisfies a given\r
+// predicate.\r
+// The predicate must be implemented as having a static apply unary\r
+// method that returns a bool.\r
+// By default an empty range is accepted\r
+template <typename Predicate, bool AllowEmptyRange = true>\r
+struct check_iterator_range\r
+{\r
+ template <typename InputIterator>\r
+ static inline bool apply(InputIterator first, InputIterator beyond)\r
+ {\r
+ for (InputIterator it = first; it != beyond; ++it)\r
+ {\r
+ if (! Predicate::apply(*it))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ return AllowEmptyRange || first != beyond;\r
+ }\r
+\r
+\r
+ // version where we can pass a predicate object\r
+ template <typename InputIterator>\r
+ static inline bool apply(InputIterator first,\r
+ InputIterator beyond,\r
+ Predicate const& predicate)\r
+ {\r
+ // in case predicate's apply method is static, MSVC will\r
+ // complain that predicate is not used\r
+ boost::ignore_unused(predicate);\r
+\r
+ for (InputIterator it = first; it != beyond; ++it)\r
+ {\r
+ if (! predicate.apply(*it))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ return AllowEmptyRange || first != beyond;\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace closest_feature\r
+{\r
+\r
+\r
+\r
+// returns the range iterator the realizes the closest\r
+// distance between the geometry and the element of the range\r
+class geometry_to_range\r
+{\r
+private:\r
+ template\r
+ <\r
+ typename Geometry,\r
+ typename RangeIterator,\r
+ typename Strategy,\r
+ typename Distance\r
+ >\r
+ static inline void apply(Geometry const& geometry,\r
+ RangeIterator first,\r
+ RangeIterator last,\r
+ Strategy const& strategy,\r
+ RangeIterator& it_min,\r
+ Distance& dist_min)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ Distance const zero = Distance(0);\r
+\r
+ // start with first distance\r
+ it_min = first;\r
+ dist_min = dispatch::distance\r
+ <\r
+ Geometry,\r
+ typename std::iterator_traits<RangeIterator>::value_type,\r
+ Strategy\r
+ >::apply(geometry, *it_min, strategy);\r
+\r
+ // check if other elements in the range are closer\r
+ for (RangeIterator it = ++first; it != last; ++it)\r
+ {\r
+ Distance dist = dispatch::distance\r
+ <\r
+ Geometry,\r
+ typename std::iterator_traits<RangeIterator>::value_type,\r
+ Strategy\r
+ >::apply(geometry, *it, strategy);\r
+\r
+ if (geometry::math::equals(dist, zero))\r
+ {\r
+ dist_min = dist;\r
+ it_min = it;\r
+ return;\r
+ }\r
+ else if (dist < dist_min)\r
+ {\r
+ dist_min = dist;\r
+ it_min = it;\r
+ }\r
+ }\r
+ }\r
+\r
+public:\r
+ template\r
+ <\r
+ typename Geometry,\r
+ typename RangeIterator,\r
+ typename Strategy,\r
+ typename Distance\r
+ > \r
+ static inline RangeIterator apply(Geometry const& geometry,\r
+ RangeIterator first,\r
+ RangeIterator last,\r
+ Strategy const& strategy,\r
+ Distance& dist_min)\r
+ {\r
+ RangeIterator it_min;\r
+ apply(geometry, first, last, strategy, it_min, dist_min);\r
+\r
+ return it_min;\r
+ }\r
+\r
+\r
+ template\r
+ <\r
+ typename Geometry,\r
+ typename RangeIterator,\r
+ typename Strategy\r
+ > \r
+ static inline RangeIterator apply(Geometry const& geometry,\r
+ RangeIterator first,\r
+ RangeIterator last,\r
+ Strategy const& strategy)\r
+ {\r
+ typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Geometry>::type,\r
+ typename point_type\r
+ <\r
+ typename std::iterator_traits\r
+ <\r
+ RangeIterator\r
+ >::value_type\r
+ >::type\r
+ >::type dist_min;\r
+\r
+ return apply(geometry, first, last, strategy, dist_min);\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::closest_feature\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP\r
+\r
+#include <utility>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace closest_feature\r
+{\r
+\r
+\r
+// returns the segment (pair of iterators) that realizes the closest\r
+// distance of the point to the range\r
+template\r
+<\r
+ typename Point,\r
+ typename Range,\r
+ closure_selector Closure,\r
+ typename Strategy\r
+>\r
+class point_to_point_range\r
+{\r
+protected:\r
+ typedef typename boost::range_iterator<Range const>::type iterator_type;\r
+\r
+ template <typename Distance>\r
+ static inline void apply(Point const& point,\r
+ iterator_type first,\r
+ iterator_type last,\r
+ Strategy const& strategy,\r
+ iterator_type& it_min1,\r
+ iterator_type& it_min2,\r
+ Distance& dist_min)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ Distance const zero = Distance(0);\r
+\r
+ iterator_type it = first;\r
+ iterator_type prev = it++;\r
+ if (it == last)\r
+ {\r
+ it_min1 = it_min2 = first;\r
+ dist_min = strategy.apply(point, *first, *first);\r
+ return;\r
+ }\r
+\r
+ // start with first segment distance\r
+ dist_min = strategy.apply(point, *prev, *it);\r
+ iterator_type prev_min_dist = prev;\r
+\r
+ // check if other segments are closer\r
+ for (++prev, ++it; it != last; ++prev, ++it)\r
+ {\r
+ Distance dist = strategy.apply(point, *prev, *it);\r
+ if (geometry::math::equals(dist, zero))\r
+ {\r
+ dist_min = zero;\r
+ it_min1 = prev;\r
+ it_min2 = it;\r
+ return;\r
+ }\r
+ else if (dist < dist_min)\r
+ {\r
+ dist_min = dist;\r
+ prev_min_dist = prev;\r
+ }\r
+ }\r
+\r
+ it_min1 = it_min2 = prev_min_dist;\r
+ ++it_min2;\r
+ }\r
+\r
+public:\r
+ typedef typename std::pair<iterator_type, iterator_type> return_type;\r
+\r
+ template <typename Distance>\r
+ static inline return_type apply(Point const& point,\r
+ iterator_type first,\r
+ iterator_type last,\r
+ Strategy const& strategy,\r
+ Distance& dist_min)\r
+ {\r
+ iterator_type it_min1, it_min2;\r
+ apply(point, first, last, strategy, it_min1, it_min2, dist_min);\r
+\r
+ return std::make_pair(it_min1, it_min2);\r
+ }\r
+\r
+ static inline return_type apply(Point const& point,\r
+ iterator_type first,\r
+ iterator_type last,\r
+ Strategy const& strategy)\r
+ {\r
+ typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ typename boost::range_value<Range>::type\r
+ >::type dist_min;\r
+\r
+ return apply(point, first, last, strategy, dist_min);\r
+ }\r
+\r
+ template <typename Distance>\r
+ static inline return_type apply(Point const& point,\r
+ Range const& range,\r
+ Strategy const& strategy,\r
+ Distance& dist_min)\r
+ {\r
+ return apply(point,\r
+ boost::begin(range),\r
+ boost::end(range),\r
+ strategy,\r
+ dist_min);\r
+ }\r
+\r
+ static inline return_type apply(Point const& point,\r
+ Range const& range,\r
+ Strategy const& strategy)\r
+ {\r
+ return apply(point, boost::begin(range), boost::end(range), strategy);\r
+ }\r
+};\r
+\r
+\r
+\r
+// specialization for open ranges\r
+template <typename Point, typename Range, typename Strategy>\r
+class point_to_point_range<Point, Range, open, Strategy>\r
+ : point_to_point_range<Point, Range, closed, Strategy>\r
+{\r
+private:\r
+ typedef point_to_point_range<Point, Range, closed, Strategy> base_type;\r
+ typedef typename base_type::iterator_type iterator_type;\r
+\r
+ template <typename Distance>\r
+ static inline void apply(Point const& point,\r
+ iterator_type first,\r
+ iterator_type last,\r
+ Strategy const& strategy,\r
+ iterator_type& it_min1,\r
+ iterator_type& it_min2,\r
+ Distance& dist_min)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ base_type::apply(point, first, last, strategy,\r
+ it_min1, it_min2, dist_min);\r
+\r
+ iterator_type it_back = --last;\r
+ Distance const zero = Distance(0);\r
+ Distance dist = strategy.apply(point, *it_back, *first);\r
+\r
+ if (geometry::math::equals(dist, zero))\r
+ {\r
+ dist_min = zero;\r
+ it_min1 = it_back;\r
+ it_min2 = first;\r
+ }\r
+ else if (dist < dist_min)\r
+ {\r
+ dist_min = dist;\r
+ it_min1 = it_back;\r
+ it_min2 = first;\r
+ }\r
+ } \r
+\r
+public:\r
+ typedef typename std::pair<iterator_type, iterator_type> return_type;\r
+\r
+ template <typename Distance>\r
+ static inline return_type apply(Point const& point,\r
+ iterator_type first,\r
+ iterator_type last,\r
+ Strategy const& strategy,\r
+ Distance& dist_min)\r
+ {\r
+ iterator_type it_min1, it_min2;\r
+\r
+ apply(point, first, last, strategy, it_min1, it_min2, dist_min);\r
+\r
+ return std::make_pair(it_min1, it_min2);\r
+ }\r
+\r
+ static inline return_type apply(Point const& point,\r
+ iterator_type first,\r
+ iterator_type last,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ typename boost::range_value<Range>::type\r
+ >::type distance_return_type;\r
+\r
+ distance_return_type dist_min;\r
+\r
+ return apply(point, first, last, strategy, dist_min);\r
+ }\r
+\r
+ template <typename Distance>\r
+ static inline return_type apply(Point const& point,\r
+ Range const& range,\r
+ Strategy const& strategy,\r
+ Distance& dist_min)\r
+ {\r
+ return apply(point,\r
+ boost::begin(range),\r
+ boost::end(range),\r
+ strategy,\r
+ dist_min);\r
+ }\r
+\r
+ static inline return_type apply(Point const& point,\r
+ Range const& range,\r
+ Strategy const& strategy)\r
+ {\r
+ return apply(point, boost::begin(range), boost::end(range), strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::closest_feature\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <iterator>\r
+#include <utility>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+#include <boost/geometry/index/rtree.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace closest_feature\r
+{\r
+\r
+\r
+// returns a pair of a objects where the first is an object of the\r
+// r-tree range and the second an object of the query range that\r
+// realizes the closest feature of the two ranges\r
+class range_to_range_rtree\r
+{\r
+private:\r
+ template\r
+ <\r
+ typename RTreeRangeIterator,\r
+ typename QueryRangeIterator,\r
+ typename Strategy,\r
+ typename RTreeValueType,\r
+ typename Distance\r
+ >\r
+ static inline void apply(RTreeRangeIterator rtree_first,\r
+ RTreeRangeIterator rtree_last,\r
+ QueryRangeIterator queries_first,\r
+ QueryRangeIterator queries_last,\r
+ Strategy const& strategy,\r
+ RTreeValueType& rtree_min,\r
+ QueryRangeIterator& qit_min,\r
+ Distance& dist_min)\r
+ {\r
+ typedef index::rtree<RTreeValueType, index::linear<8> > rtree_type;\r
+\r
+ BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last );\r
+ BOOST_GEOMETRY_ASSERT( queries_first != queries_last );\r
+\r
+ Distance const zero = Distance(0);\r
+ dist_min = zero;\r
+\r
+ // create -- packing algorithm\r
+ rtree_type rt(rtree_first, rtree_last);\r
+\r
+ RTreeValueType t_v;\r
+ bool first = true;\r
+\r
+ for (QueryRangeIterator qit = queries_first;\r
+ qit != queries_last; ++qit, first = false)\r
+ {\r
+ std::size_t n = rt.query(index::nearest(*qit, 1), &t_v);\r
+\r
+ BOOST_GEOMETRY_ASSERT( n > 0 );\r
+ // n above is unused outside BOOST_GEOMETRY_ASSERT,\r
+ // hence the call to boost::ignore_unused below\r
+ //\r
+ // however, t_v (initialized by the call to rt.query(...))\r
+ // is used below, which is why we cannot put the call to\r
+ // rt.query(...) inside BOOST_GEOMETRY_ASSERT\r
+ boost::ignore_unused(n);\r
+\r
+ Distance dist = dispatch::distance\r
+ <\r
+ RTreeValueType,\r
+ typename std::iterator_traits\r
+ <\r
+ QueryRangeIterator\r
+ >::value_type,\r
+ Strategy\r
+ >::apply(t_v, *qit, strategy);\r
+\r
+ if (first || dist < dist_min)\r
+ {\r
+ dist_min = dist;\r
+ rtree_min = t_v;\r
+ qit_min = qit;\r
+ if ( math::equals(dist_min, zero) )\r
+ {\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+public:\r
+ template <typename RTreeRangeIterator, typename QueryRangeIterator>\r
+ struct return_type\r
+ {\r
+ typedef std::pair\r
+ <\r
+ typename std::iterator_traits<RTreeRangeIterator>::value_type,\r
+ QueryRangeIterator\r
+ > type;\r
+ };\r
+\r
+\r
+ template\r
+ <\r
+ typename RTreeRangeIterator,\r
+ typename QueryRangeIterator,\r
+ typename Strategy,\r
+ typename Distance\r
+ >\r
+ static inline typename return_type\r
+ <\r
+ RTreeRangeIterator, QueryRangeIterator\r
+ >::type apply(RTreeRangeIterator rtree_first,\r
+ RTreeRangeIterator rtree_last,\r
+ QueryRangeIterator queries_first,\r
+ QueryRangeIterator queries_last,\r
+ Strategy const& strategy,\r
+ Distance& dist_min)\r
+ {\r
+ typedef typename std::iterator_traits\r
+ <\r
+ RTreeRangeIterator\r
+ >::value_type rtree_value_type;\r
+\r
+ rtree_value_type rtree_min;\r
+ QueryRangeIterator qit_min;\r
+\r
+ apply(rtree_first, rtree_last, queries_first, queries_last,\r
+ strategy, rtree_min, qit_min, dist_min);\r
+\r
+ return std::make_pair(rtree_min, qit_min); \r
+ }\r
+\r
+\r
+ template\r
+ <\r
+ typename RTreeRangeIterator,\r
+ typename QueryRangeIterator,\r
+ typename Strategy\r
+ >\r
+ static inline typename return_type\r
+ <\r
+ RTreeRangeIterator, QueryRangeIterator\r
+ >::type apply(RTreeRangeIterator rtree_first,\r
+ RTreeRangeIterator rtree_last,\r
+ QueryRangeIterator queries_first,\r
+ QueryRangeIterator queries_last,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename std::iterator_traits\r
+ <\r
+ RTreeRangeIterator\r
+ >::value_type rtree_value_type;\r
+\r
+ typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<rtree_value_type>::type,\r
+ typename point_type\r
+ <\r
+ typename std::iterator_traits\r
+ <\r
+ QueryRangeIterator\r
+ >::value_type\r
+ >::type\r
+ >::type dist_min;\r
+\r
+ return apply(rtree_first, rtree_last, queries_first, queries_last,\r
+ strategy, dist_min);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::closest_feature\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/distance/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/strategies/comparable_distance_result.hpp>\r
+#include <boost/geometry/strategies/default_comparable_distance_result.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/interface.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+struct comparable_distance\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline\r
+ typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type\r
+ apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type comparable_strategy_type;\r
+\r
+ return dispatch::distance\r
+ <\r
+ Geometry1, Geometry2, comparable_strategy_type\r
+ >::apply(geometry1,\r
+ geometry2,\r
+ strategy::distance::services::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy));\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline typename comparable_distance_result\r
+ <\r
+ Geometry1, Geometry2, default_strategy\r
+ >::type\r
+ apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ default_strategy)\r
+ {\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ typename detail::distance::default_strategy\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ >::type comparable_strategy_type;\r
+\r
+ return dispatch::distance\r
+ <\r
+ Geometry1, Geometry2, comparable_strategy_type\r
+ >::apply(geometry1, geometry2, comparable_strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct comparable_distance\r
+{\r
+ template <typename Strategy>\r
+ static inline\r
+ typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type\r
+ apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return resolve_strategy::comparable_distance::apply(geometry1,\r
+ geometry2,\r
+ strategy);\r
+ }\r
+};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct comparable_distance\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2\r
+ >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor\r
+ <\r
+ typename comparable_distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2,\r
+ Strategy\r
+ >::type\r
+ >\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ : m_geometry2(geometry2),\r
+ m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry1>\r
+ typename comparable_distance_result\r
+ <\r
+ Geometry1, Geometry2, Strategy\r
+ >::type\r
+ operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return comparable_distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ Strategy\r
+ >(geometry1, m_geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename comparable_distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2,\r
+ Strategy\r
+ >::type\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct comparable_distance\r
+ <\r
+ Geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>\r
+ >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor\r
+ <\r
+ typename comparable_distance_result\r
+ <\r
+ Geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Strategy\r
+ >::type\r
+ >\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry1 const& geometry1,\r
+ Strategy const& strategy)\r
+ : m_geometry1(geometry1),\r
+ m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry2>\r
+ typename comparable_distance_result\r
+ <\r
+ Geometry1, Geometry2, Strategy\r
+ >::type\r
+ operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return comparable_distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ Strategy\r
+ >(m_geometry1, geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename comparable_distance_result\r
+ <\r
+ Geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Strategy\r
+ >::type\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct comparable_distance\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+ >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor\r
+ <\r
+ typename comparable_distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,\r
+ Strategy\r
+ >::type\r
+ >\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy)\r
+ : m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ typename comparable_distance_result\r
+ <\r
+ Geometry1, Geometry2, Strategy\r
+ >::type\r
+ operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const\r
+ {\r
+ return comparable_distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ Strategy\r
+ >(geometry1, geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename comparable_distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,\r
+ Strategy\r
+ >::type\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{comparable distance measurement} \brief_strategy\r
+\ingroup distance\r
+\details The free function comparable_distance does not necessarily calculate the distance,\r
+ but it calculates a distance measure such that two distances are comparable to each other.\r
+ For example: for the Cartesian coordinate system, Pythagoras is used but the square root\r
+ is not taken, which makes it faster and the results of two point pairs can still be\r
+ compared to each other.\r
+\tparam Geometry1 first geometry type\r
+\tparam Geometry2 second geometry type\r
+\tparam Strategy \tparam_strategy{Distance}\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param strategy \param_strategy{distance}\r
+\return \return_calc{comparable distance}\r
+\r
+\qbk{distinguish,with strategy}\r
+ */\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+inline typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type\r
+comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return resolve_variant::comparable_distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{comparable distance measurement}\r
+\ingroup distance\r
+\details The free function comparable_distance does not necessarily calculate the distance,\r
+ but it calculates a distance measure such that two distances are comparable to each other.\r
+ For example: for the Cartesian coordinate system, Pythagoras is used but the square root\r
+ is not taken, which makes it faster and the results of two point pairs can still be\r
+ compared to each other.\r
+\tparam Geometry1 first geometry type\r
+\tparam Geometry2 second geometry type\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_calc{comparable distance}\r
+\r
+\qbk{[include reference/algorithms/comparable_distance.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline typename default_comparable_distance_result<Geometry1, Geometry2>::type\r
+comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return geometry::comparable_distance(geometry1, geometry2, default_strategy());\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace conversion\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Source,\r
+ typename Destination,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct indexed_to_indexed\r
+{\r
+ static inline void apply(Source const& source, Destination& destination)\r
+ {\r
+ typedef typename coordinate_type<Destination>::type coordinate_type;\r
+\r
+ geometry::set<min_corner, Dimension>(destination,\r
+ boost::numeric_cast<coordinate_type>(\r
+ geometry::get<min_corner, Dimension>(source)));\r
+ geometry::set<max_corner, Dimension>(destination,\r
+ boost::numeric_cast<coordinate_type>(\r
+ geometry::get<max_corner, Dimension>(source)));\r
+\r
+ indexed_to_indexed\r
+ <\r
+ Source, Destination,\r
+ Dimension + 1, DimensionCount\r
+ >::apply(source, destination);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Source,\r
+ typename Destination,\r
+ std::size_t DimensionCount\r
+>\r
+struct indexed_to_indexed<Source, Destination, DimensionCount, DimensionCount>\r
+{\r
+ static inline void apply(Source const& , Destination& )\r
+ {}\r
+};\r
+\r
+\r
+}} // namespace detail::conversion\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP\r
+\r
+// Note: extracted from "convert.hpp" to avoid circular references convert/append\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace conversion\r
+{\r
+\r
+\r
+template <typename Source, typename Destination, std::size_t Dimension, std::size_t DimensionCount>\r
+struct point_to_point\r
+{\r
+ static inline void apply(Source const& source, Destination& destination)\r
+ {\r
+ typedef typename coordinate_type<Destination>::type coordinate_type;\r
+\r
+ set<Dimension>(destination, boost::numeric_cast<coordinate_type>(get<Dimension>(source)));\r
+ point_to_point<Source, Destination, Dimension + 1, DimensionCount>::apply(source, destination);\r
+ }\r
+};\r
+\r
+template <typename Source, typename Destination, std::size_t DimensionCount>\r
+struct point_to_point<Source, Destination, DimensionCount, DimensionCount>\r
+{\r
+ static inline void apply(Source const& , Destination& )\r
+ {}\r
+};\r
+\r
+\r
+template <typename Source, typename Destination>\r
+inline void convert_point_to_point(Source const& source, Destination& destination)\r
+{\r
+ point_to_point<Source, Destination, 0, dimension<Destination>::value>::apply(source, destination);\r
+}\r
+\r
+\r
+\r
+}} // namespace detail::conversion\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace counting\r
+{\r
+\r
+\r
+template <std::size_t D>\r
+struct other_count\r
+{\r
+ template <typename Geometry>\r
+ static inline std::size_t apply(Geometry const&)\r
+ {\r
+ return D;\r
+ }\r
+\r
+ template <typename Geometry>\r
+ static inline std::size_t apply(Geometry const&, bool)\r
+ {\r
+ return D;\r
+ }\r
+};\r
+\r
+\r
+template <typename RangeCount>\r
+struct polygon_count\r
+{\r
+ template <typename Polygon>\r
+ static inline std::size_t apply(Polygon const& poly)\r
+ {\r
+ std::size_t n = RangeCount::apply(exterior_ring(poly));\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(poly);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ n += RangeCount::apply(*it);\r
+ }\r
+\r
+ return n;\r
+ }\r
+};\r
+\r
+\r
+template <typename SingleCount>\r
+struct multi_count\r
+{\r
+ template <typename MultiGeometry>\r
+ static inline std::size_t apply(MultiGeometry const& geometry)\r
+ {\r
+ std::size_t n = 0;\r
+ for (typename boost::range_iterator<MultiGeometry const>::type\r
+ it = boost::begin(geometry);\r
+ it != boost::end(geometry);\r
+ ++it)\r
+ {\r
+ n += SingleCount::apply(*it);\r
+ }\r
+ return n;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::counting\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/azimuth.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+/// Calculate course (bearing) between two points.\r
+///\r
+/// NOTE: left for convenience and temporary backward compatibility\r
+template <typename ReturnType, typename Point1, typename Point2>\r
+inline ReturnType course(Point1 const& p1, Point2 const& p2)\r
+{\r
+ return azimuth<ReturnType>(p1, p2);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <std::size_t Index, typename Point1, typename Point2>\r
+inline int sign_of_difference(Point1 const& point1, Point2 const& point2)\r
+{\r
+ return\r
+ math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))\r
+ ?\r
+ 0\r
+ :\r
+ (geometry::get<Index>(point1) > geometry::get<Index>(point2) ? 1 : -1);\r
+}\r
+\r
+\r
+// Gives sense of direction for point p, collinear w.r.t. segment (a,b)\r
+// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a\r
+// Returns 1 if p goes forward, so extends (a,b)\r
+// Returns 0 if p is equal with b, or if (a,b) is degenerate\r
+// Note that it does not do any collinearity test, that should be done before\r
+template <typename Point1, typename Point2>\r
+inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,\r
+ const Point2& p)\r
+{\r
+ // Suppose segment = (4 3,4 4) and p =(4 2)\r
+ // Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1\r
+\r
+ int const sign_a0 = sign_of_difference<0>(segment_b, segment_a);\r
+ int const sign_a1 = sign_of_difference<1>(segment_b, segment_a);\r
+\r
+ if (sign_a0 == 0 && sign_a1 == 0)\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ int const sign_p0 = sign_of_difference<0>(segment_b, p);\r
+ int const sign_p1 = sign_of_difference<1>(segment_b, p);\r
+\r
+ if (sign_p0 == 0 && sign_p1 == 0)\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1;\r
+}\r
+\r
+\r
+} // namespace detail\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+template<typename Geometry>\r
+struct check_each_ring_for_within\r
+{\r
+ bool not_disjoint;\r
+ Geometry const& m_geometry;\r
+\r
+ inline check_each_ring_for_within(Geometry const& g)\r
+ : not_disjoint(false)\r
+ , m_geometry(g)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline void apply(Range const& range)\r
+ {\r
+ typename point_type<Range>::type pt;\r
+ not_disjoint = not_disjoint\r
+ || ( geometry::point_on_border(pt, range)\r
+ && geometry::covered_by(pt, m_geometry) );\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename FirstGeometry, typename SecondGeometry>\r
+inline bool rings_containing(FirstGeometry const& geometry1,\r
+ SecondGeometry const& geometry2)\r
+{\r
+ check_each_ring_for_within<FirstGeometry> checker(geometry1);\r
+ geometry::detail::for_each_range(geometry2, checker);\r
+ return checker.not_disjoint;\r
+}\r
+\r
+\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct general_areal\r
+{\r
+ static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // If there is no intersection of segments, they might located\r
+ // inside each other\r
+\r
+ // We check that using a point on the border (external boundary),\r
+ // and see if that is contained in the other geometry. And vice versa.\r
+\r
+ if ( rings_containing(geometry1, geometry2)\r
+ || rings_containing(geometry2, geometry1) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Areal1, typename Areal2>\r
+struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false>\r
+ : detail::disjoint::general_areal<Areal1, Areal2>\r
+{};\r
+\r
+\r
+template <typename Areal, typename Box>\r
+struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>\r
+ : detail::disjoint::general_areal<Areal, Box>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2016.\r
+// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+template\r
+<\r
+ typename Box1, typename Box2,\r
+ std::size_t Dimension = 0,\r
+ std::size_t DimensionCount = dimension<Box1>::value,\r
+ typename CSTag = typename tag_cast\r
+ <\r
+ typename cs_tag<Box1>::type,\r
+ spherical_tag\r
+ >::type\r
+>\r
+struct box_box\r
+{\r
+ static inline bool apply(Box1 const& box1, Box2 const& box2)\r
+ {\r
+ if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))\r
+ {\r
+ return true;\r
+ }\r
+ if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))\r
+ {\r
+ return true;\r
+ }\r
+ return box_box\r
+ <\r
+ Box1, Box2,\r
+ Dimension + 1, DimensionCount\r
+ >::apply(box1, box2);\r
+ }\r
+};\r
+\r
+\r
+template <typename Box1, typename Box2, std::size_t DimensionCount, typename CSTag>\r
+struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>\r
+{\r
+ static inline bool apply(Box1 const& , Box2 const& )\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+template <typename Box1, typename Box2, std::size_t DimensionCount>\r
+struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>\r
+{\r
+ static inline bool apply(Box1 const& box1, Box2 const& box2)\r
+ {\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ typename coordinate_type<Box1>::type,\r
+ typename coordinate_type<Box2>::type\r
+ >::type calc_t;\r
+ typedef typename coordinate_system<Box1>::type::units units_t;\r
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;\r
+\r
+ calc_t const b1_min = get<min_corner, 0>(box1);\r
+ calc_t const b1_max = get<max_corner, 0>(box1);\r
+ calc_t const b2_min = get<min_corner, 0>(box2);\r
+ calc_t const b2_max = get<max_corner, 0>(box2);\r
+\r
+ // min <= max <=> diff >= 0\r
+ calc_t const diff1 = b1_max - b1_min;\r
+ calc_t const diff2 = b2_max - b2_min;\r
+\r
+ // check the intersection if neither box cover the whole globe\r
+ if (diff1 < constants::period() && diff2 < constants::period())\r
+ {\r
+ // calculate positive longitude translation with b1_min as origin\r
+ calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);\r
+ calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min\r
+\r
+ if (b2_min_transl > b1_max // b2_min right of b1_max\r
+ && b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return box_box\r
+ <\r
+ Box1, Box2,\r
+ 1, DimensionCount\r
+ >::apply(box1, box2);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Internal utility function to detect if boxes are disjoint\r
+ \note Is used from other algorithms, declared separately\r
+ to avoid circular references\r
+ */\r
+template <typename Box1, typename Box2>\r
+inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)\r
+{\r
+ return box_box<Box1, Box2>::apply(box1, box2);\r
+}\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Box1, typename Box2, std::size_t DimensionCount>\r
+struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>\r
+ : detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/areal_areal.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_areal.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// If reversal is needed, perform it\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ std::size_t DimensionCount,\r
+ typename Tag1, typename Tag2\r
+>\r
+struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ return disjoint\r
+ <\r
+ Geometry2, Geometry1,\r
+ DimensionCount,\r
+ Tag2, Tag1\r
+ >::apply(g2, g1);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct disjoint\r
+{\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ concepts::check_concepts_and_equal_dimensions\r
+ <\r
+ Geometry1 const,\r
+ Geometry2 const\r
+ >();\r
+\r
+ return dispatch::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct disjoint<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+\r
+ visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {}\r
+\r
+ template <typename Geometry1>\r
+ bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry2), geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct disjoint<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+\r
+ visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {}\r
+\r
+ template <typename Geometry2>\r
+ bool operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry1), geometry2);\r
+ }\r
+};\r
+\r
+template <\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct disjoint<\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+>\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ template <typename Geometry1, typename Geometry2>\r
+ bool operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_check2{are disjoint}\r
+\ingroup disjoint\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_check2{are disjoint}\r
+\r
+\qbk{[include reference/algorithms/disjoint.qbk]}\r
+*/\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool disjoint(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2015.\r
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>\r
+struct disjoint_no_intersections_policy\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ typedef typename point_type<Geometry1>::type point1_type;\r
+ point1_type p;\r
+ geometry::point_on_border(p, g1);\r
+ return !geometry::covered_by(p, g2);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Tag1>\r
+struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ // TODO: use partition or rtree on g2\r
+ typedef typename boost::range_iterator<Geometry1 const>::type iterator;\r
+ for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )\r
+ {\r
+ typedef typename boost::range_value<Geometry1 const>::type value_type;\r
+ if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>\r
+ ::apply(*it, g2) )\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template<typename Geometry1, typename Geometry2,\r
+ typename NoIntersectionsPolicy\r
+ = disjoint_no_intersections_policy<Geometry1, Geometry2> >\r
+struct disjoint_linear_areal\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ // if there are intersections - return false\r
+ if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return NoIntersectionsPolicy::apply(g1, g2);\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename Areal,\r
+ typename Tag = typename tag<Areal>::type\r
+>\r
+struct disjoint_segment_areal\r
+ : not_implemented<Segment, Areal>\r
+{};\r
+\r
+\r
+template <typename Segment, typename Polygon>\r
+class disjoint_segment_areal<Segment, Polygon, polygon_tag>\r
+{\r
+private:\r
+ template <typename InteriorRings>\r
+ static inline\r
+ bool check_interior_rings(InteriorRings const& interior_rings,\r
+ Segment const& segment)\r
+ {\r
+ typedef typename boost::range_value<InteriorRings>::type ring_type;\r
+\r
+ typedef unary_disjoint_geometry_to_query_geometry\r
+ <\r
+ Segment,\r
+ disjoint_range_segment_or_box\r
+ <\r
+ ring_type, closure<ring_type>::value, Segment\r
+ >\r
+ > unary_predicate_type;\r
+ \r
+ return check_iterator_range\r
+ <\r
+ unary_predicate_type\r
+ >::apply(boost::begin(interior_rings),\r
+ boost::end(interior_rings),\r
+ unary_predicate_type(segment));\r
+ }\r
+\r
+\r
+public:\r
+ static inline bool apply(Segment const& segment, Polygon const& polygon)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring;\r
+\r
+ if ( !disjoint_range_segment_or_box\r
+ <\r
+ ring, closure<Polygon>::value, Segment\r
+ >::apply(geometry::exterior_ring(polygon), segment) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( !check_interior_rings(geometry::interior_rings(polygon), segment) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ typename point_type<Segment>::type p;\r
+ detail::assign_point_from_index<0>(segment, p);\r
+\r
+ return !geometry::covered_by(p, polygon);\r
+ }\r
+};\r
+\r
+\r
+template <typename Segment, typename MultiPolygon>\r
+struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>\r
+{\r
+ static inline\r
+ bool apply(Segment const& segment, MultiPolygon const& multipolygon)\r
+ {\r
+ return multirange_constant_size_geometry\r
+ <\r
+ MultiPolygon, Segment\r
+ >::apply(multipolygon, segment);\r
+ }\r
+};\r
+\r
+\r
+template <typename Segment, typename Ring>\r
+struct disjoint_segment_areal<Segment, Ring, ring_tag>\r
+{\r
+ static inline bool apply(Segment const& segment, Ring const& ring)\r
+ {\r
+ if ( !disjoint_range_segment_or_box\r
+ <\r
+ Ring, closure<Ring>::value, Segment\r
+ >::apply(ring, segment) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ typename point_type<Segment>::type p;\r
+ detail::assign_point_from_index<0>(segment, p);\r
+ \r
+ return !geometry::covered_by(p, ring); \r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Linear, typename Areal>\r
+struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>\r
+ : public detail::disjoint::disjoint_linear_areal<Linear, Areal>\r
+{};\r
+\r
+\r
+template <typename Areal, typename Linear>\r
+struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>\r
+{ \r
+ static inline\r
+ bool apply(Areal const& areal, Linear const& linear)\r
+ {\r
+ return detail::disjoint::disjoint_linear_areal\r
+ <\r
+ Linear, Areal\r
+ >::apply(linear, areal);\r
+ }\r
+};\r
+\r
+\r
+template <typename Areal, typename Segment>\r
+struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>\r
+{\r
+ static inline bool apply(Areal const& g1, Segment const& g2)\r
+ {\r
+ return detail::disjoint::disjoint_segment_areal\r
+ <\r
+ Segment, Areal\r
+ >::apply(g2, g1);\r
+ }\r
+};\r
+\r
+\r
+template <typename Segment, typename Areal>\r
+struct disjoint<Segment, Areal, 2, segment_tag, areal_tag, false>\r
+ : detail::disjoint::disjoint_segment_areal<Segment, Areal>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP\r
+\r
+#include <cstddef>\r
+#include <deque>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>\r
+\r
+#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+template <typename Segment1, typename Segment2>\r
+struct disjoint_segment\r
+{\r
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)\r
+ {\r
+ typedef typename point_type<Segment1>::type point_type;\r
+\r
+ // We don't need to rescale to detect disjointness\r
+ typedef no_rescale_policy rescale_policy_type;\r
+ rescale_policy_type robust_policy;\r
+\r
+ typedef segment_intersection_points\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type\r
+ <\r
+ point_type,\r
+ rescale_policy_type\r
+ >::type\r
+ > intersection_return_type;\r
+\r
+ intersection_return_type is\r
+ = strategy::intersection::relate_cartesian_segments\r
+ <\r
+ policies::relate::segments_intersection_points\r
+ <\r
+ intersection_return_type\r
+ >\r
+ >::apply(segment1, segment2, robust_policy);\r
+\r
+ return is.count == 0;\r
+ }\r
+};\r
+\r
+\r
+struct assign_disjoint_policy\r
+{\r
+ // We want to include all points:\r
+ static bool const include_no_turn = true;\r
+ static bool const include_degenerate = true;\r
+ static bool const include_opposite = true;\r
+\r
+ // We don't assign extra info:\r
+ template\r
+ <\r
+ typename Info,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline void apply(Info& , Point1 const& , Point2 const&,\r
+ IntersectionInfo const&)\r
+ {}\r
+};\r
+\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct disjoint_linear\r
+{\r
+ static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ typedef typename geometry::point_type<Geometry1>::type point_type;\r
+ typedef detail::no_rescale_policy rescale_policy_type;\r
+ typedef typename geometry::segment_ratio_type\r
+ <\r
+ point_type, rescale_policy_type\r
+ >::type segment_ratio_type;\r
+ typedef overlay::turn_info\r
+ <\r
+ point_type,\r
+ segment_ratio_type,\r
+ typename detail::get_turns::turn_operation_type\r
+ <\r
+ Geometry1, Geometry2, segment_ratio_type\r
+ >::type\r
+ > turn_info_type;\r
+\r
+ std::deque<turn_info_type> turns;\r
+\r
+ // Specify two policies:\r
+ // 1) Stop at any intersection\r
+ // 2) In assignment, include also degenerate points (which are normally skipped)\r
+ disjoint_interrupt_policy interrupt_policy;\r
+ dispatch::get_turns\r
+ <\r
+ typename geometry::tag<Geometry1>::type,\r
+ typename geometry::tag<Geometry2>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, // should be false\r
+ overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, // should be false\r
+ detail::get_turns::get_turn_info_type\r
+ <\r
+ Geometry1, Geometry2, assign_disjoint_policy\r
+ >\r
+ >::apply(0, geometry1, 1, geometry2,\r
+ rescale_policy_type(), turns, interrupt_policy);\r
+\r
+ return !interrupt_policy.has_intersections;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Linear1, typename Linear2>\r
+struct disjoint<Linear1, Linear2, 2, linear_tag, linear_tag, false>\r
+ : detail::disjoint::disjoint_linear<Linear1, Linear2>\r
+{};\r
+\r
+\r
+template <typename Segment1, typename Segment2>\r
+struct disjoint<Segment1, Segment2, 2, segment_tag, segment_tag, false>\r
+ : detail::disjoint::disjoint_segment<Segment1, Segment2>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Range,\r
+ closure_selector Closure,\r
+ typename SegmentOrBox\r
+>\r
+struct disjoint_range_segment_or_box\r
+{\r
+ static inline\r
+ bool apply(Range const& range, SegmentOrBox const& segment_or_box)\r
+ {\r
+ typedef typename closeable_view<Range const, Closure>::type view_type;\r
+\r
+ typedef typename ::boost::range_value<view_type>::type point_type;\r
+ typedef typename ::boost::range_iterator\r
+ <\r
+ view_type const\r
+ >::type const_iterator;\r
+\r
+ typedef typename ::boost::range_size<view_type>::type size_type;\r
+\r
+ typedef typename geometry::model::referring_segment\r
+ <\r
+ point_type const\r
+ > range_segment;\r
+\r
+ view_type view(range);\r
+\r
+ const size_type count = ::boost::size(view);\r
+\r
+ if ( count == 0 )\r
+ {\r
+ return false;\r
+ }\r
+ else if ( count == 1 )\r
+ {\r
+ return dispatch::disjoint\r
+ <\r
+ point_type, SegmentOrBox\r
+ >::apply(geometry::range::front<view_type const>(view),\r
+ segment_or_box);\r
+ }\r
+ else\r
+ {\r
+ const_iterator it0 = ::boost::begin(view);\r
+ const_iterator it1 = ::boost::begin(view) + 1;\r
+ const_iterator last = ::boost::end(view);\r
+\r
+ for ( ; it1 != last ; ++it0, ++it1 )\r
+ {\r
+ range_segment rng_segment(*it0, *it1);\r
+ if ( !dispatch::disjoint\r
+ <\r
+ range_segment, SegmentOrBox\r
+ >::apply(rng_segment, segment_or_box) )\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Linear,\r
+ typename SegmentOrBox,\r
+ typename Tag = typename tag<Linear>::type\r
+>\r
+struct disjoint_linear_segment_or_box\r
+ : not_implemented<Linear, SegmentOrBox>\r
+{};\r
+\r
+\r
+template <typename Linestring, typename SegmentOrBox>\r
+struct disjoint_linear_segment_or_box<Linestring, SegmentOrBox, linestring_tag>\r
+ : disjoint_range_segment_or_box<Linestring, closed, SegmentOrBox>\r
+{};\r
+\r
+\r
+template <typename MultiLinestring, typename SegmentOrBox>\r
+struct disjoint_linear_segment_or_box\r
+ <\r
+ MultiLinestring, SegmentOrBox, multi_linestring_tag\r
+ > : multirange_constant_size_geometry<MultiLinestring, SegmentOrBox>\r
+{};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Linear, typename Segment>\r
+struct disjoint<Linear, Segment, 2, linear_tag, segment_tag, false>\r
+ : detail::disjoint::disjoint_linear_segment_or_box<Linear, Segment>\r
+{};\r
+\r
+\r
+template <typename Linear, typename Box, std::size_t DimensionCount>\r
+struct disjoint<Linear, Box, DimensionCount, linear_tag, box_tag, false>\r
+ : detail::disjoint::disjoint_linear_segment_or_box<Linear, Box>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/iterators/segment_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/less.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+template <typename MultiPoint1, typename MultiPoint2>\r
+class multipoint_multipoint\r
+{\r
+private:\r
+ template <typename Iterator>\r
+ class unary_disjoint_predicate\r
+ : detail::relate::less\r
+ {\r
+ private:\r
+ typedef detail::relate::less base_type;\r
+\r
+ public:\r
+ unary_disjoint_predicate(Iterator first, Iterator last)\r
+ : base_type(), m_first(first), m_last(last)\r
+ {}\r
+\r
+ template <typename Point>\r
+ inline bool apply(Point const& point) const\r
+ {\r
+ return !std::binary_search(m_first,\r
+ m_last,\r
+ point,\r
+ static_cast<base_type const&>(*this));\r
+ }\r
+\r
+ private:\r
+ Iterator m_first, m_last;\r
+ };\r
+\r
+public:\r
+ static inline bool apply(MultiPoint1 const& multipoint1,\r
+ MultiPoint2 const& multipoint2)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );\r
+\r
+ typedef typename boost::range_value<MultiPoint1>::type point1_type;\r
+\r
+ std::vector<point1_type> points1(boost::begin(multipoint1),\r
+ boost::end(multipoint1));\r
+\r
+ std::sort(points1.begin(), points1.end(), detail::relate::less());\r
+\r
+ typedef unary_disjoint_predicate\r
+ <\r
+ typename std::vector<point1_type>::const_iterator\r
+ > predicate_type;\r
+\r
+ return check_iterator_range\r
+ <\r
+ predicate_type\r
+ >::apply(boost::begin(multipoint2),\r
+ boost::end(multipoint2),\r
+ predicate_type(points1.begin(), points1.end()));\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPoint, typename Linear>\r
+class multipoint_linear\r
+{\r
+private:\r
+ // structs for partition -- start\r
+ struct expand_box\r
+ {\r
+ template <typename Box, typename Geometry>\r
+ static inline void apply(Box& total, Geometry const& geometry)\r
+ {\r
+ geometry::expand(total, geometry::return_envelope<Box>(geometry));\r
+ }\r
+\r
+ };\r
+\r
+ struct overlaps_box\r
+ {\r
+ template <typename Box, typename Geometry>\r
+ static inline bool apply(Box const& box, Geometry const& geometry)\r
+ {\r
+ return ! dispatch::disjoint<Geometry, Box>::apply(geometry, box);\r
+ }\r
+ };\r
+\r
+ class item_visitor_type\r
+ {\r
+ public:\r
+ item_visitor_type() : m_intersection_found(false) {}\r
+\r
+ template <typename Item1, typename Item2>\r
+ inline void apply(Item1 const& item1, Item2 const& item2)\r
+ {\r
+ if (! m_intersection_found\r
+ && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2))\r
+ {\r
+ m_intersection_found = true;\r
+ }\r
+ }\r
+\r
+ inline bool intersection_found() const { return m_intersection_found; }\r
+\r
+ private:\r
+ bool m_intersection_found;\r
+ };\r
+ // structs for partition -- end\r
+\r
+ class segment_range\r
+ {\r
+ public:\r
+ typedef geometry::segment_iterator<Linear const> const_iterator;\r
+ typedef const_iterator iterator;\r
+\r
+ segment_range(Linear const& linear)\r
+ : m_linear(linear)\r
+ {}\r
+\r
+ const_iterator begin() const\r
+ {\r
+ return geometry::segments_begin(m_linear);\r
+ }\r
+\r
+ const_iterator end() const\r
+ {\r
+ return geometry::segments_end(m_linear);\r
+ }\r
+\r
+ private:\r
+ Linear const& m_linear;\r
+ };\r
+\r
+public:\r
+ static inline bool apply(MultiPoint const& multipoint, Linear const& linear)\r
+ {\r
+ item_visitor_type visitor;\r
+\r
+ geometry::partition\r
+ <\r
+ geometry::model::box<typename point_type<MultiPoint>::type>,\r
+ expand_box,\r
+ overlaps_box\r
+ >::apply(multipoint, segment_range(linear), visitor);\r
+\r
+ return ! visitor.intersection_found();\r
+ }\r
+\r
+ static inline bool apply(Linear const& linear, MultiPoint const& multipoint)\r
+ {\r
+ return apply(multipoint, linear);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Point, typename MultiPoint, std::size_t DimensionCount>\r
+struct disjoint\r
+ <\r
+ Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false\r
+ > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Point>\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Segment, std::size_t DimensionCount>\r
+struct disjoint\r
+ <\r
+ MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false\r
+ > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Segment>\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Box, std::size_t DimensionCount>\r
+struct disjoint\r
+ <\r
+ MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false\r
+ > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Box>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint1,\r
+ typename MultiPoint2,\r
+ std::size_t DimensionCount\r
+>\r
+struct disjoint\r
+ <\r
+ MultiPoint1, MultiPoint2, DimensionCount,\r
+ multi_point_tag, multi_point_tag, false\r
+ >\r
+{\r
+ static inline bool apply(MultiPoint1 const& multipoint1,\r
+ MultiPoint2 const& multipoint2)\r
+ {\r
+ if ( boost::size(multipoint2) < boost::size(multipoint1) )\r
+ {\r
+ return detail::disjoint::multipoint_multipoint\r
+ <\r
+ MultiPoint2, MultiPoint1\r
+ >::apply(multipoint2, multipoint1);\r
+ } \r
+\r
+ return detail::disjoint::multipoint_multipoint\r
+ <\r
+ MultiPoint1, MultiPoint2\r
+ >::apply(multipoint1, multipoint2);\r
+ }\r
+};\r
+\r
+\r
+template <typename Linear, typename MultiPoint, std::size_t DimensionCount>\r
+struct disjoint\r
+ <\r
+ Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false\r
+ > : detail::disjoint::multipoint_linear<MultiPoint, Linear>\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Linear, std::size_t DimensionCount>\r
+struct disjoint\r
+ <\r
+ MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false\r
+ > : detail::disjoint::multipoint_linear<MultiPoint, Linear>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+template <typename Geometry, typename BinaryPredicate>\r
+class unary_disjoint_geometry_to_query_geometry\r
+{\r
+public:\r
+ unary_disjoint_geometry_to_query_geometry(Geometry const& geometry)\r
+ : m_geometry(geometry)\r
+ {}\r
+\r
+ template <typename QueryGeometry>\r
+ inline bool apply(QueryGeometry const& query_geometry) const\r
+ {\r
+ return BinaryPredicate::apply(query_geometry, m_geometry);\r
+ }\r
+\r
+private:\r
+ Geometry const& m_geometry;\r
+};\r
+\r
+\r
+template<typename MultiRange, typename ConstantSizeGeometry>\r
+struct multirange_constant_size_geometry\r
+{\r
+ static inline bool apply(MultiRange const& multirange,\r
+ ConstantSizeGeometry const& constant_size_geometry)\r
+ {\r
+ typedef unary_disjoint_geometry_to_query_geometry\r
+ <\r
+ ConstantSizeGeometry,\r
+ dispatch::disjoint\r
+ <\r
+ typename boost::range_value<MultiRange>::type,\r
+ ConstantSizeGeometry\r
+ >\r
+ > unary_predicate_type;\r
+\r
+ return detail::check_iterator_range\r
+ <\r
+ unary_predicate_type\r
+ >::apply(boost::begin(multirange), boost::end(multirange),\r
+ unary_predicate_type(constant_size_geometry));\r
+ }\r
+\r
+ static inline bool apply(ConstantSizeGeometry const& constant_size_geometry,\r
+ MultiRange const& multirange)\r
+ {\r
+ return apply(multirange, constant_size_geometry);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland\r
+\r
+// This file was modified by Oracle on 2013-2016.\r
+// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+/*!\r
+ \brief Internal utility function to detect if point/box are disjoint\r
+ */\r
+template <typename Point, typename Box>\r
+inline bool disjoint_point_box(Point const& point, Box const& box)\r
+{\r
+ // ! covered_by(point, box)\r
+ return ! strategy::within::relate_point_box_loop\r
+ <\r
+ strategy::within::covered_by_range,\r
+ Point, Box,\r
+ 0, dimension<Point>::type::value\r
+ >::apply(point, box);\r
+}\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Point, typename Box, std::size_t DimensionCount>\r
+struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>\r
+{\r
+ static inline bool apply(Point const& point, Box const& box)\r
+ {\r
+ // ! covered_by(point, box)\r
+ return ! strategy::within::relate_point_box_loop\r
+ <\r
+ strategy::within::covered_by_range,\r
+ Point, Box,\r
+ 0, DimensionCount\r
+ >::apply(point, box);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+struct reverse_covered_by\r
+{\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ return ! geometry::covered_by(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template<typename Point, typename Linear, std::size_t DimensionCount>\r
+struct disjoint<Point, Linear, DimensionCount, point_tag, linear_tag, false>\r
+ : detail::disjoint::reverse_covered_by\r
+{};\r
+\r
+\r
+template <typename Point, typename Areal, std::size_t DimensionCount>\r
+struct disjoint<Point, Areal, DimensionCount, point_tag, areal_tag, false>\r
+ : detail::disjoint::reverse_covered_by\r
+{};\r
+\r
+\r
+template<typename Point, typename Segment, std::size_t DimensionCount>\r
+struct disjoint<Point, Segment, DimensionCount, point_tag, segment_tag, false>\r
+ : detail::disjoint::reverse_covered_by\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/strategies/strategy_transform.hpp>\r
+\r
+#include <boost/geometry/geometries/helper_geometry.hpp>\r
+\r
+#include <boost/geometry/algorithms/transform.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct point_point_generic\r
+{\r
+ template <typename Point1, typename Point2>\r
+ static inline bool apply(Point1 const& p1, Point2 const& p2)\r
+ {\r
+ if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))\r
+ {\r
+ return true;\r
+ }\r
+ return\r
+ point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct point_point_generic<DimensionCount, DimensionCount>\r
+{\r
+ template <typename Point1, typename Point2>\r
+ static inline bool apply(Point1 const&, Point2 const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+class point_point_on_spheroid\r
+{\r
+private:\r
+ template <typename Point1, typename Point2, bool SameUnits>\r
+ struct are_same_points\r
+ {\r
+ static inline bool apply(Point1 const& point1, Point2 const& point2)\r
+ {\r
+ typedef typename helper_geometry<Point1>::type helper_point_type1;\r
+ typedef typename helper_geometry<Point2>::type helper_point_type2;\r
+\r
+ helper_point_type1 point1_normalized\r
+ = return_normalized<helper_point_type1>(point1);\r
+ helper_point_type2 point2_normalized\r
+ = return_normalized<helper_point_type2>(point2);\r
+\r
+ return point_point_generic\r
+ <\r
+ 0, dimension<Point1>::value\r
+ >::apply(point1_normalized, point2_normalized);\r
+ }\r
+ };\r
+\r
+ template <typename Point1, typename Point2>\r
+ struct are_same_points<Point1, Point2, false> // points have different units\r
+ {\r
+ static inline bool apply(Point1 const& point1, Point2 const& point2)\r
+ {\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ typename fp_coordinate_type<Point1>::type,\r
+ typename fp_coordinate_type<Point2>::type\r
+ >::type calculation_type;\r
+\r
+ typename helper_geometry\r
+ <\r
+ Point1, calculation_type, radian\r
+ >::type helper_point1, helper_point2;\r
+\r
+ Point1 point1_normalized = return_normalized<Point1>(point1);\r
+ Point2 point2_normalized = return_normalized<Point2>(point2);\r
+\r
+ geometry::transform(point1_normalized, helper_point1);\r
+ geometry::transform(point2_normalized, helper_point2);\r
+\r
+ return point_point_generic\r
+ <\r
+ 0, dimension<Point1>::value\r
+ >::apply(helper_point1, helper_point2);\r
+ }\r
+ };\r
+\r
+public:\r
+ template <typename Point1, typename Point2>\r
+ static inline bool apply(Point1 const& point1, Point2 const& point2)\r
+ {\r
+ return are_same_points\r
+ <\r
+ Point1,\r
+ Point2,\r
+ boost::is_same\r
+ <\r
+ typename coordinate_system<Point1>::type::units,\r
+ typename coordinate_system<Point2>::type::units\r
+ >::value\r
+ >::apply(point1, point2);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point1, typename Point2,\r
+ std::size_t Dimension, std::size_t DimensionCount,\r
+ typename CSTag1 = typename cs_tag<Point1>::type,\r
+ typename CSTag2 = CSTag1\r
+>\r
+struct point_point\r
+ : point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>\r
+{};\r
+\r
+template\r
+<\r
+ typename Point1, typename Point2,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct point_point\r
+ <\r
+ Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag\r
+ > : point_point_on_spheroid\r
+{};\r
+\r
+template\r
+<\r
+ typename Point1, typename Point2,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct point_point\r
+ <\r
+ Point1, Point2, Dimension, DimensionCount, geographic_tag\r
+ > : point_point_on_spheroid\r
+{};\r
+\r
+template\r
+<\r
+ typename Point1, typename Point2,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>\r
+ : point_point_generic<Dimension, DimensionCount>\r
+{};\r
+\r
+\r
+/*!\r
+ \brief Internal utility function to detect of points are disjoint\r
+ \note To avoid circular references\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)\r
+{\r
+ return point_point\r
+ <\r
+ Point1, Point2,\r
+ 0, dimension<Point1>::type::value\r
+ >::apply(point1, point2);\r
+}\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Point1, typename Point2, std::size_t DimensionCount>\r
+struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>\r
+ : detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP\r
+\r
+#include <cstddef>\r
+#include <utility>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/calculation_type.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/disjoint.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+template <std::size_t I>\r
+struct compute_tmin_tmax_per_dim\r
+{\r
+ template <typename SegmentPoint, typename Box, typename RelativeDistance>\r
+ static inline void apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ Box const& box,\r
+ RelativeDistance& ti_min,\r
+ RelativeDistance& ti_max,\r
+ RelativeDistance& diff)\r
+ {\r
+ typedef typename coordinate_type<Box>::type box_coordinate_type;\r
+ typedef typename coordinate_type\r
+ <\r
+ SegmentPoint\r
+ >::type point_coordinate_type;\r
+\r
+ RelativeDistance c_p0 = boost::numeric_cast\r
+ <\r
+ point_coordinate_type\r
+ >( geometry::get<I>(p0) );\r
+\r
+ RelativeDistance c_p1 = boost::numeric_cast\r
+ <\r
+ point_coordinate_type\r
+ >( geometry::get<I>(p1) );\r
+\r
+ RelativeDistance c_b_min = boost::numeric_cast\r
+ <\r
+ box_coordinate_type\r
+ >( geometry::get<geometry::min_corner, I>(box) );\r
+\r
+ RelativeDistance c_b_max = boost::numeric_cast\r
+ <\r
+ box_coordinate_type\r
+ >( geometry::get<geometry::max_corner, I>(box) );\r
+\r
+ if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )\r
+ {\r
+ diff = c_p1 - c_p0;\r
+ ti_min = c_b_min - c_p0;\r
+ ti_max = c_b_max - c_p0;\r
+ }\r
+ else\r
+ {\r
+ diff = c_p0 - c_p1;\r
+ ti_min = c_p0 - c_b_max;\r
+ ti_max = c_p0 - c_b_min;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename RelativeDistance,\r
+ typename SegmentPoint,\r
+ typename Box,\r
+ std::size_t I,\r
+ std::size_t Dimension\r
+>\r
+struct disjoint_segment_box_impl\r
+{\r
+ template <typename RelativeDistancePair>\r
+ static inline bool apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ Box const& box,\r
+ RelativeDistancePair& t_min,\r
+ RelativeDistancePair& t_max)\r
+ {\r
+ RelativeDistance ti_min, ti_max, diff;\r
+\r
+ compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);\r
+\r
+ if ( geometry::math::equals(diff, 0) )\r
+ {\r
+ if ( (geometry::math::equals(t_min.second, 0)\r
+ && t_min.first > ti_max)\r
+ ||\r
+ (geometry::math::equals(t_max.second, 0)\r
+ && t_max.first < ti_min)\r
+ ||\r
+ (math::sign(ti_min) * math::sign(ti_max) > 0) )\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ RelativeDistance t_min_x_diff = t_min.first * diff;\r
+ RelativeDistance t_max_x_diff = t_max.first * diff;\r
+\r
+ if ( t_min_x_diff > ti_max * t_min.second\r
+ || t_max_x_diff < ti_min * t_max.second )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if ( ti_min * t_min.second > t_min_x_diff )\r
+ {\r
+ t_min.first = ti_min;\r
+ t_min.second = diff;\r
+ }\r
+ if ( ti_max * t_max.second < t_max_x_diff )\r
+ {\r
+ t_max.first = ti_max;\r
+ t_max.second = diff;\r
+ }\r
+\r
+ if ( t_min.first > t_min.second || t_max.first < 0 )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ return disjoint_segment_box_impl\r
+ <\r
+ RelativeDistance,\r
+ SegmentPoint,\r
+ Box, \r
+ I + 1,\r
+ Dimension\r
+ >::apply(p0, p1, box, t_min, t_max);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename RelativeDistance,\r
+ typename SegmentPoint,\r
+ typename Box,\r
+ std::size_t Dimension\r
+>\r
+struct disjoint_segment_box_impl\r
+ <\r
+ RelativeDistance, SegmentPoint, Box, 0, Dimension\r
+ >\r
+{\r
+ static inline bool apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ Box const& box)\r
+ {\r
+ std::pair<RelativeDistance, RelativeDistance> t_min, t_max;\r
+ RelativeDistance diff;\r
+\r
+ compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,\r
+ t_min.first, t_max.first, diff);\r
+\r
+ if ( geometry::math::equals(diff, 0) )\r
+ {\r
+ if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }\r
+ if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }\r
+\r
+ if (math::sign(t_min.first) * math::sign(t_max.first) > 0)\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ if ( t_min.first > diff || t_max.first < 0 )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ t_min.second = t_max.second = diff;\r
+\r
+ return disjoint_segment_box_impl\r
+ <\r
+ RelativeDistance, SegmentPoint, Box, 1, Dimension\r
+ >::apply(p0, p1, box, t_min, t_max);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename RelativeDistance,\r
+ typename SegmentPoint,\r
+ typename Box,\r
+ std::size_t Dimension\r
+>\r
+struct disjoint_segment_box_impl\r
+ <\r
+ RelativeDistance, SegmentPoint, Box, Dimension, Dimension\r
+ >\r
+{\r
+ template <typename RelativeDistancePair>\r
+ static inline bool apply(SegmentPoint const&, SegmentPoint const&,\r
+ Box const&,\r
+ RelativeDistancePair&, RelativeDistancePair&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+//=========================================================================\r
+\r
+\r
+template <typename Segment, typename Box>\r
+struct disjoint_segment_box\r
+{ \r
+ static inline bool apply(Segment const& segment, Box const& box)\r
+ {\r
+ assert_dimension_equal<Segment, Box>();\r
+\r
+ typedef typename util::calculation_type::geometric::binary\r
+ <\r
+ Segment, Box, void\r
+ >::type relative_distance_type;\r
+\r
+ typedef typename point_type<Segment>::type segment_point_type;\r
+ segment_point_type p0, p1;\r
+ geometry::detail::assign_point_from_index<0>(segment, p0);\r
+ geometry::detail::assign_point_from_index<1>(segment, p1);\r
+\r
+ return disjoint_segment_box_impl\r
+ <\r
+ relative_distance_type, segment_point_type, Box,\r
+ 0, dimension<Box>::value\r
+ >::apply(p0, p1, box);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Segment, typename Box, std::size_t DimensionCount>\r
+struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>\r
+ : detail::disjoint::disjoint_segment_box<Segment, Box>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template<typename Point, typename Segment, typename Strategy>\r
+struct point_to_segment\r
+{\r
+ static inline typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ typename point_type<Segment>::type\r
+ >::type\r
+ apply(Point const& point, Segment const& segment, Strategy const& )\r
+ {\r
+ typename detail::distance::default_ps_strategy\r
+ <\r
+ Point,\r
+ typename point_type<Segment>::type,\r
+ Strategy\r
+ >::type segment_strategy;\r
+\r
+ typename point_type<Segment>::type p[2];\r
+ geometry::detail::assign_point_from_index<0>(segment, p[0]);\r
+ geometry::detail::assign_point_from_index<1>(segment, p[1]);\r
+ return segment_strategy.apply(point, p[0], p[1]);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// Point-segment version 1, with point-point strategy\r
+template <typename Point, typename Segment, typename Strategy>\r
+struct distance\r
+<\r
+ Point, Segment, Strategy,\r
+ point_tag, segment_tag, strategy_tag_distance_point_point,\r
+ false\r
+> : detail::distance::point_to_segment<Point, Segment, Strategy>\r
+{};\r
+\r
+\r
+// Point-line version 1, where point-point strategy is specified\r
+template <typename Point, typename Linestring, typename Strategy>\r
+struct distance\r
+<\r
+ Point, Linestring, Strategy,\r
+ point_tag, linestring_tag, strategy_tag_distance_point_point,\r
+ false\r
+>\r
+{\r
+\r
+ static inline typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Linestring>::type\r
+ >::type\r
+ apply(Point const& point,\r
+ Linestring const& linestring,\r
+ Strategy const&)\r
+ {\r
+ typedef typename detail::distance::default_ps_strategy\r
+ <\r
+ Point,\r
+ typename point_type<Linestring>::type,\r
+ Strategy\r
+ >::type ps_strategy_type;\r
+\r
+ return detail::distance::point_to_range\r
+ <\r
+ Point, Linestring, closed, ps_strategy_type\r
+ >::apply(point, linestring, ps_strategy_type());\r
+ }\r
+};\r
+\r
+\r
+// Point-ring , where point-point strategy is specified\r
+template <typename Point, typename Ring, typename Strategy>\r
+struct distance\r
+<\r
+ Point, Ring, Strategy,\r
+ point_tag, ring_tag, strategy_tag_distance_point_point,\r
+ false\r
+>\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Ring>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point,\r
+ Ring const& ring,\r
+ Strategy const&)\r
+ {\r
+ typedef typename detail::distance::default_ps_strategy\r
+ <\r
+ Point,\r
+ typename point_type<Ring>::type,\r
+ Strategy\r
+ >::type ps_strategy_type;\r
+\r
+ return detail::distance::point_to_ring\r
+ <\r
+ Point, Ring,\r
+ geometry::closure<Ring>::value,\r
+ ps_strategy_type\r
+ >::apply(point, ring, ps_strategy_type());\r
+ }\r
+};\r
+\r
+\r
+// Point-polygon , where point-point strategy is specified\r
+template <typename Point, typename Polygon, typename Strategy>\r
+struct distance\r
+<\r
+ Point, Polygon, Strategy,\r
+ point_tag, polygon_tag, strategy_tag_distance_point_point,\r
+ false\r
+>\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Polygon>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point,\r
+ Polygon const& polygon,\r
+ Strategy const&)\r
+ {\r
+ typedef typename detail::distance::default_ps_strategy\r
+ <\r
+ Point,\r
+ typename point_type<Polygon>::type,\r
+ Strategy\r
+ >::type ps_strategy_type;\r
+\r
+ return detail::distance::point_to_polygon\r
+ <\r
+ Point,\r
+ Polygon,\r
+ geometry::closure<Polygon>::value,\r
+ ps_strategy_type\r
+ >::apply(point, polygon, ps_strategy_type());\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename MultiGeometry,\r
+ typename MultiGeometryTag,\r
+ typename Strategy\r
+>\r
+struct distance\r
+ <\r
+ Point, MultiGeometry, Strategy,\r
+ point_tag, MultiGeometryTag,\r
+ strategy_tag_distance_point_point, false\r
+ >\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<MultiGeometry>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point,\r
+ MultiGeometry const& multigeometry,\r
+ Strategy const&)\r
+ {\r
+ typedef typename detail::distance::default_ps_strategy\r
+ <\r
+ Point,\r
+ typename point_type<MultiGeometry>::type,\r
+ Strategy\r
+ >::type ps_strategy_type;\r
+ \r
+ return distance\r
+ <\r
+ Point, MultiGeometry, ps_strategy_type,\r
+ point_tag, MultiGeometryTag,\r
+ strategy_tag_distance_point_segment, false\r
+ >::apply(point, multigeometry, ps_strategy_type());\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename MultiPoint,\r
+ typename GeometryTag,\r
+ typename Strategy\r
+>\r
+struct distance\r
+ <\r
+ Geometry, MultiPoint, Strategy,\r
+ GeometryTag, multi_point_tag,\r
+ strategy_tag_distance_point_point, false\r
+ >\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<MultiPoint>::type,\r
+ typename point_type<Geometry>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Geometry const& geometry,\r
+ MultiPoint const& multipoint,\r
+ Strategy const&)\r
+ {\r
+ typedef typename detail::distance::default_ps_strategy\r
+ <\r
+ typename point_type<MultiPoint>::type,\r
+ typename point_type<Geometry>::type,\r
+ Strategy\r
+ >::type ps_strategy_type;\r
+ \r
+ return distance\r
+ <\r
+ Geometry, MultiPoint, ps_strategy_type,\r
+ GeometryTag, multi_point_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ >::apply(geometry, multipoint, ps_strategy_type());\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename MultiGeometry,\r
+ typename MultiGeometryTag,\r
+ typename Strategy\r
+>\r
+struct distance\r
+ <\r
+ MultiPoint, MultiGeometry, Strategy,\r
+ multi_point_tag, MultiGeometryTag,\r
+ strategy_tag_distance_point_point, false\r
+ >\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<MultiPoint>::type, \r
+ typename point_type<MultiGeometry>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPoint const& multipoint,\r
+ MultiGeometry const& multigeometry,\r
+ Strategy const&)\r
+ {\r
+ typedef typename detail::distance::default_ps_strategy\r
+ <\r
+ typename point_type<MultiPoint>::type,\r
+ typename point_type<MultiGeometry>::type,\r
+ Strategy\r
+ >::type ps_strategy_type;\r
+ \r
+ return distance\r
+ <\r
+ MultiPoint, MultiGeometry, ps_strategy_type,\r
+ multi_point_tag, MultiGeometryTag,\r
+ strategy_tag_distance_point_segment, false\r
+ >::apply(multipoint, multigeometry, ps_strategy_type());\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Box1, typename Box2, typename Strategy>\r
+struct distance\r
+ <\r
+ Box1, Box2, Strategy, box_tag, box_tag,\r
+ strategy_tag_distance_box_box, false\r
+ >\r
+{\r
+ static inline typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Box1>::type,\r
+ typename point_type<Box2>::type\r
+ >::type\r
+ apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ return strategy.apply(box1, box2);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+\r
+// Helper metafunction for default strategy retrieval\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2 = Geometry1,\r
+ typename Tag1 = typename tag_cast\r
+ <\r
+ typename tag<Geometry1>::type, pointlike_tag\r
+ >::type,\r
+ typename Tag2 = typename tag_cast\r
+ <\r
+ typename tag<Geometry2>::type, pointlike_tag\r
+ >::type,\r
+ bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct default_strategy\r
+ : strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, segment_tag,\r
+ typename point_type<Geometry1>::type,\r
+ typename point_type<Geometry2>::type\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1,\r
+ typename Tag2\r
+>\r
+struct default_strategy<Geometry1, Geometry2, Tag1, Tag2, true>\r
+ : default_strategy<Geometry2, Geometry1, Tag2, Tag1, false>\r
+{};\r
+\r
+\r
+template <typename Pointlike1, typename Pointlike2>\r
+struct default_strategy\r
+ <\r
+ Pointlike1, Pointlike2,\r
+ pointlike_tag, pointlike_tag, false\r
+ > : strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, point_tag,\r
+ typename point_type<Pointlike1>::type,\r
+ typename point_type<Pointlike2>::type\r
+ >\r
+{};\r
+\r
+\r
+template <typename Pointlike, typename Box>\r
+struct default_strategy<Pointlike, Box, pointlike_tag, box_tag, false>\r
+ : strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, box_tag,\r
+ typename point_type<Pointlike>::type,\r
+ typename point_type<Box>::type\r
+ >\r
+{};\r
+\r
+\r
+template <typename Box1, typename Box2>\r
+struct default_strategy<Box1, Box2, box_tag, box_tag, false>\r
+ : strategy::distance::services::default_strategy\r
+ <\r
+ box_tag, box_tag,\r
+ typename point_type<Box1>::type,\r
+ typename point_type<Box2>::type\r
+ >\r
+{};\r
+\r
+\r
+\r
+// Helper metafunction for default point-segment strategy retrieval\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+struct default_ps_strategy\r
+ : strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, segment_tag,\r
+ typename point_type<Geometry1>::type,\r
+ typename point_type<Geometry2>::type,\r
+ typename cs_tag<typename point_type<Geometry1>::type>::type,\r
+ typename cs_tag<typename point_type<Geometry2>::type>::type,\r
+ Strategy\r
+ >\r
+{};\r
+\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+#include <boost/geometry/iterators/segment_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>\r
+#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+// closure of segment or box point range\r
+template\r
+<\r
+ typename SegmentOrBox,\r
+ typename Tag = typename tag<SegmentOrBox>::type\r
+>\r
+struct segment_or_box_point_range_closure\r
+ : not_implemented<SegmentOrBox>\r
+{}; \r
+\r
+template <typename Segment>\r
+struct segment_or_box_point_range_closure<Segment, segment_tag>\r
+{\r
+ static const closure_selector value = closed;\r
+};\r
+\r
+template <typename Box>\r
+struct segment_or_box_point_range_closure<Box, box_tag>\r
+{\r
+ static const closure_selector value = open;\r
+};\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename SegmentOrBox,\r
+ typename Strategy,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+class geometry_to_segment_or_box\r
+{\r
+private:\r
+ typedef typename point_type<SegmentOrBox>::type segment_or_box_point;\r
+\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type comparable_strategy;\r
+\r
+ typedef detail::closest_feature::point_to_point_range\r
+ <\r
+ typename point_type<Geometry>::type,\r
+ std::vector<segment_or_box_point>,\r
+ segment_or_box_point_range_closure<SegmentOrBox>::value,\r
+ comparable_strategy\r
+ > point_to_point_range;\r
+\r
+ typedef detail::closest_feature::geometry_to_range geometry_to_range;\r
+\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ comparable_strategy,\r
+ typename point_type<Geometry>::type,\r
+ segment_or_box_point\r
+ >::type comparable_return_type;\r
+\r
+\r
+ // assign the new minimum value for an iterator of the point range\r
+ // of a segment or a box\r
+ template\r
+ <\r
+ typename SegOrBox,\r
+ typename SegOrBoxTag = typename tag<SegOrBox>::type\r
+ >\r
+ struct assign_new_min_iterator\r
+ : not_implemented<SegOrBox>\r
+ {};\r
+\r
+ template <typename Segment>\r
+ struct assign_new_min_iterator<Segment, segment_tag>\r
+ {\r
+ template <typename Iterator>\r
+ static inline void apply(Iterator&, Iterator)\r
+ {\r
+ }\r
+ };\r
+\r
+ template <typename Box>\r
+ struct assign_new_min_iterator<Box, box_tag>\r
+ {\r
+ template <typename Iterator>\r
+ static inline void apply(Iterator& it_min, Iterator it)\r
+ {\r
+ it_min = it;\r
+ }\r
+ };\r
+\r
+\r
+ // assign the points of a segment or a box to a range\r
+ template\r
+ <\r
+ typename SegOrBox,\r
+ typename PointRange,\r
+ typename SegOrBoxTag = typename tag<SegOrBox>::type\r
+ >\r
+ struct assign_segment_or_box_points\r
+ {};\r
+\r
+ template <typename Segment, typename PointRange>\r
+ struct assign_segment_or_box_points<Segment, PointRange, segment_tag>\r
+ {\r
+ static inline void apply(Segment const& segment, PointRange& range)\r
+ {\r
+ detail::assign_point_from_index<0>(segment, range[0]);\r
+ detail::assign_point_from_index<1>(segment, range[1]);\r
+ }\r
+ };\r
+\r
+ template <typename Box, typename PointRange>\r
+ struct assign_segment_or_box_points<Box, PointRange, box_tag>\r
+ {\r
+ static inline void apply(Box const& box, PointRange& range)\r
+ {\r
+ detail::assign_box_corners_oriented<true>(box, range);\r
+ }\r
+ };\r
+\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Geometry>::type,\r
+ segment_or_box_point\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Geometry const& geometry,\r
+ SegmentOrBox const& segment_or_box,\r
+ Strategy const& strategy,\r
+ bool check_intersection = true)\r
+ {\r
+ typedef geometry::point_iterator<Geometry const> point_iterator_type;\r
+ typedef geometry::segment_iterator\r
+ <\r
+ Geometry const\r
+ > segment_iterator_type;\r
+\r
+ typedef typename boost::range_const_iterator\r
+ <\r
+ std::vector<segment_or_box_point>\r
+ >::type seg_or_box_const_iterator;\r
+\r
+ typedef assign_new_min_iterator<SegmentOrBox> assign_new_value;\r
+\r
+\r
+ if (check_intersection\r
+ && geometry::intersects(geometry, segment_or_box))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ comparable_strategy cstrategy =\r
+ strategy::distance::services::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy);\r
+\r
+ // get all points of the segment or the box\r
+ std::vector<segment_or_box_point>\r
+ seg_or_box_points(geometry::num_points(segment_or_box));\r
+\r
+ assign_segment_or_box_points\r
+ <\r
+ SegmentOrBox, \r
+ std::vector<segment_or_box_point>\r
+ >::apply(segment_or_box, seg_or_box_points);\r
+\r
+ // consider all distances of the points in the geometry to the\r
+ // segment or box\r
+ comparable_return_type cd_min1(0);\r
+ point_iterator_type pit_min;\r
+ seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points);\r
+ seg_or_box_const_iterator it_min2 = it_min1;\r
+ ++it_min2;\r
+ bool first = true;\r
+\r
+ for (point_iterator_type pit = points_begin(geometry);\r
+ pit != points_end(geometry); ++pit, first = false)\r
+ {\r
+ comparable_return_type cd;\r
+ std::pair\r
+ <\r
+ seg_or_box_const_iterator, seg_or_box_const_iterator\r
+ > it_pair\r
+ = point_to_point_range::apply(*pit,\r
+ boost::const_begin(seg_or_box_points),\r
+ boost::const_end(seg_or_box_points),\r
+ cstrategy,\r
+ cd);\r
+\r
+ if (first || cd < cd_min1)\r
+ {\r
+ cd_min1 = cd;\r
+ pit_min = pit;\r
+ assign_new_value::apply(it_min1, it_pair.first);\r
+ assign_new_value::apply(it_min2, it_pair.second);\r
+ }\r
+ }\r
+\r
+ // consider all distances of the points in the segment or box to the\r
+ // segments of the geometry\r
+ comparable_return_type cd_min2(0);\r
+ segment_iterator_type sit_min;\r
+ seg_or_box_const_iterator it_min;\r
+\r
+ first = true;\r
+ for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points);\r
+ it != boost::const_end(seg_or_box_points); ++it, first = false)\r
+ {\r
+ comparable_return_type cd;\r
+ segment_iterator_type sit\r
+ = geometry_to_range::apply(*it,\r
+ segments_begin(geometry),\r
+ segments_end(geometry),\r
+ cstrategy,\r
+ cd);\r
+\r
+ if (first || cd < cd_min2)\r
+ {\r
+ cd_min2 = cd;\r
+ it_min = it;\r
+ sit_min = sit;\r
+ }\r
+ }\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))\r
+ {\r
+ return (std::min)(cd_min1, cd_min2);\r
+ }\r
+\r
+ if (cd_min1 < cd_min2)\r
+ {\r
+ return strategy.apply(*pit_min, *it_min1, *it_min2);\r
+ }\r
+ else\r
+ {\r
+ return dispatch::distance\r
+ <\r
+ segment_or_box_point,\r
+ typename std::iterator_traits\r
+ <\r
+ segment_iterator_type\r
+ >::value_type,\r
+ Strategy\r
+ >::apply(*it_min, *sit_min, strategy);\r
+ }\r
+ }\r
+\r
+\r
+ static inline return_type\r
+ apply(SegmentOrBox const& segment_or_box, Geometry const& geometry, \r
+ Strategy const& strategy, bool check_intersection = true)\r
+ {\r
+ return apply(geometry, segment_or_box, strategy, check_intersection);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename MultiPoint, typename SegmentOrBox, typename Strategy>\r
+class geometry_to_segment_or_box\r
+ <\r
+ MultiPoint, SegmentOrBox, Strategy, multi_point_tag\r
+ >\r
+{\r
+private:\r
+ typedef detail::closest_feature::geometry_to_range base_type;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiPoint const\r
+ >::type iterator_type;\r
+\r
+ typedef detail::closest_feature::geometry_to_range geometry_to_range;\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<SegmentOrBox>::type,\r
+ typename point_type<MultiPoint>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPoint const& multipoint,\r
+ SegmentOrBox const& segment_or_box,\r
+ Strategy const& strategy)\r
+ {\r
+ namespace sds = strategy::distance::services;\r
+\r
+ typename sds::return_type\r
+ <\r
+ typename sds::comparable_type<Strategy>::type,\r
+ typename point_type<SegmentOrBox>::type,\r
+ typename point_type<MultiPoint>::type\r
+ >::type cd_min;\r
+\r
+ iterator_type it_min\r
+ = geometry_to_range::apply(segment_or_box,\r
+ boost::begin(multipoint),\r
+ boost::end(multipoint),\r
+ sds::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy),\r
+ cd_min);\r
+\r
+ return\r
+ is_comparable<Strategy>::value\r
+ ?\r
+ cd_min\r
+ :\r
+ dispatch::distance\r
+ <\r
+ typename point_type<MultiPoint>::type,\r
+ SegmentOrBox,\r
+ Strategy\r
+ >::apply(*it_min, segment_or_box, strategy);\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Linear, typename Segment, typename Strategy>\r
+struct distance\r
+ <\r
+ Linear, Segment, Strategy, linear_tag, segment_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::geometry_to_segment_or_box<Linear, Segment, Strategy>\r
+{};\r
+\r
+\r
+template <typename Areal, typename Segment, typename Strategy>\r
+struct distance\r
+ <\r
+ Areal, Segment, Strategy, areal_tag, segment_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>\r
+{};\r
+\r
+\r
+template <typename Segment, typename Areal, typename Strategy>\r
+struct distance\r
+ <\r
+ Segment, Areal, Strategy, segment_tag, areal_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>\r
+{};\r
+\r
+\r
+template <typename Linear, typename Box, typename Strategy>\r
+struct distance\r
+ <\r
+ Linear, Box, Strategy, linear_tag, box_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::geometry_to_segment_or_box\r
+ <\r
+ Linear, Box, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <typename Areal, typename Box, typename Strategy>\r
+struct distance\r
+ <\r
+ Areal, Box, Strategy, areal_tag, box_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::geometry_to_segment_or_box<Areal, Box, Strategy>\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Segment, typename Strategy>\r
+struct distance\r
+ <\r
+ MultiPoint, Segment, Strategy,\r
+ multi_point_tag, segment_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::geometry_to_segment_or_box\r
+ <\r
+ MultiPoint, Segment, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Box, typename Strategy>\r
+struct distance\r
+ <\r
+ MultiPoint, Box, Strategy,\r
+ multi_point_tag, box_tag,\r
+ strategy_tag_distance_point_box, false\r
+ > : detail::distance::geometry_to_segment_or_box\r
+ <\r
+ MultiPoint, Box, Strategy\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP\r
+\r
+// the implementation details\r
+#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/box_to_box.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/backward_compatibility.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+// Copyright (c) 2014 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+#include <boost/mpl/always.hpp>\r
+#include <boost/mpl/bool.hpp>\r
+#include <boost/mpl/vector.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/default_distance_result.hpp>\r
+#include <boost/geometry/strategies/distance_result.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// If reversal is needed, perform it\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename Strategy,\r
+ typename Tag1, typename Tag2, typename StrategyTag\r
+>\r
+struct distance\r
+<\r
+ Geometry1, Geometry2, Strategy,\r
+ Tag1, Tag2, StrategyTag,\r
+ true\r
+>\r
+ : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Geometry2>::type,\r
+ typename point_type<Geometry1>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(\r
+ Geometry1 const& g1,\r
+ Geometry2 const& g2,\r
+ Strategy const& strategy)\r
+ {\r
+ return distance\r
+ <\r
+ Geometry2, Geometry1, Strategy,\r
+ Tag2, Tag1, StrategyTag,\r
+ false\r
+ >::apply(g2, g1, strategy);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+struct distance\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline typename distance_result<Geometry1, Geometry2, Strategy>::type\r
+ apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return dispatch::distance\r
+ <\r
+ Geometry1, Geometry2, Strategy\r
+ >::apply(geometry1, geometry2, strategy);\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline\r
+ typename distance_result<Geometry1, Geometry2, default_strategy>::type\r
+ apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ default_strategy)\r
+ {\r
+ typedef typename detail::distance::default_strategy\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type strategy_type;\r
+\r
+ return dispatch::distance\r
+ <\r
+ Geometry1, Geometry2, strategy_type\r
+ >::apply(geometry1, geometry2, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct distance\r
+{\r
+ template <typename Strategy>\r
+ static inline typename distance_result<Geometry1, Geometry2, Strategy>::type\r
+ apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return\r
+ resolve_strategy::distance::apply(geometry1, geometry2, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor\r
+ <\r
+ typename distance_result\r
+ <\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2,\r
+ Strategy\r
+ >::type\r
+ >\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ : m_geometry2(geometry2),\r
+ m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry1>\r
+ typename distance_result<Geometry1, Geometry2, Strategy>::type\r
+ operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ Strategy\r
+ >(geometry1, m_geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename distance_result\r
+ <\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2,\r
+ Strategy\r
+ >::type\r
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor\r
+ <\r
+ typename distance_result\r
+ <\r
+ Geometry1,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Strategy\r
+ >::type\r
+ >\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry1 const& geometry1,\r
+ Strategy const& strategy)\r
+ : m_geometry1(geometry1),\r
+ m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry2>\r
+ typename distance_result<Geometry1, Geometry2, Strategy>::type\r
+ operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ Strategy\r
+ >(m_geometry1, geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename distance_result\r
+ <\r
+ Geometry1,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Strategy\r
+ >::type\r
+ apply(\r
+ Geometry1 const& geometry1,\r
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct distance\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+ >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor\r
+ <\r
+ typename distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,\r
+ Strategy\r
+ >::type\r
+ >\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy)\r
+ : m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ typename distance_result<Geometry1, Geometry2, Strategy>::type\r
+ operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const\r
+ {\r
+ return distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ Strategy\r
+ >(geometry1, geometry2, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline typename distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,\r
+ Strategy\r
+ >::type\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{distance} \brief_strategy\r
+\ingroup distance\r
+\details\r
+\details \details_calc{area}. \brief_strategy. \details_strategy_reasons\r
+\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Strategy \tparam_strategy{Distance}\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param strategy \param_strategy{distance}\r
+\return \return_calc{distance}\r
+\note The strategy can be a point-point strategy. In case of distance point-line/point-polygon\r
+ it may also be a point-segment strategy.\r
+\r
+\qbk{distinguish,with strategy}\r
+\r
+\qbk{\r
+[heading Available Strategies]\r
+\* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]\r
+\* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]\r
+\* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]\r
+\* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]\r
+\* more (currently extensions): Vincenty\, Andoyer (geographic)\r
+}\r
+ */\r
+\r
+/*\r
+Note, in case of a Compilation Error:\r
+if you get:\r
+ - "Failed to specialize function template ..."\r
+ - "error: no matching function for call to ..."\r
+for distance, it is probably so that there is no specialization\r
+for return_type<...> for your strategy.\r
+*/\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+inline typename distance_result<Geometry1, Geometry2, Strategy>::type\r
+distance(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ detail::throw_on_empty_input(geometry1);\r
+ detail::throw_on_empty_input(geometry2);\r
+\r
+ return resolve_variant::distance\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{distance}\r
+\ingroup distance\r
+\details The default strategy is used, corresponding to the coordinate system of the geometries\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_calc{distance}\r
+\r
+\qbk{[include reference/algorithms/distance.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline typename default_distance_result<Geometry1, Geometry2>::type\r
+distance(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return geometry::distance(geometry1, geometry2, default_strategy());\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP\r
+\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+// metafunction to determine is a strategy is comparable or not\r
+template <typename Strategy>\r
+struct is_comparable\r
+ : boost::is_same\r
+ <\r
+ Strategy,\r
+ typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+#include <boost/geometry/iterators/segment_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+// class to choose between point_iterator and segment_iterator\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct iterator_selector\r
+{\r
+ typedef geometry::segment_iterator<Geometry> iterator_type;\r
+\r
+ static inline iterator_type begin(Geometry& geometry)\r
+ {\r
+ return segments_begin(geometry);\r
+ }\r
+\r
+ static inline iterator_type end(Geometry& geometry)\r
+ {\r
+ return segments_end(geometry);\r
+ }\r
+};\r
+\r
+template <typename MultiPoint>\r
+struct iterator_selector<MultiPoint, multi_point_tag>\r
+{\r
+ typedef geometry::point_iterator<MultiPoint> iterator_type;\r
+\r
+ static inline iterator_type begin(MultiPoint& multipoint)\r
+ {\r
+ return points_begin(multipoint);\r
+ }\r
+\r
+ static inline iterator_type end(MultiPoint& multipoint)\r
+ {\r
+ return points_end(multipoint);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template <typename Linear, typename Areal, typename Strategy>\r
+struct linear_to_areal\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Linear>::type,\r
+ typename point_type<Areal>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Linear const& linear,\r
+ Areal const& areal,\r
+ Strategy const& strategy)\r
+ {\r
+ if ( geometry::intersects(linear, areal) )\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ return linear_to_linear\r
+ <\r
+ Linear, Areal, Strategy\r
+ >::apply(linear, areal, strategy, false);\r
+ }\r
+\r
+\r
+ static inline return_type apply(Areal const& areal,\r
+ Linear const& linear,\r
+ Strategy const& strategy)\r
+ {\r
+ return apply(linear, areal, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename Areal1, typename Areal2, typename Strategy>\r
+struct areal_to_areal\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Areal1>::type,\r
+ typename point_type<Areal2>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Areal1 const& areal1,\r
+ Areal2 const& areal2,\r
+ Strategy const& strategy)\r
+ {\r
+ if ( geometry::intersects(areal1, areal2) )\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ return linear_to_linear\r
+ <\r
+ Areal1, Areal2, Strategy\r
+ >::apply(areal1, areal2, strategy, false);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Linear, typename Areal, typename Strategy>\r
+struct distance\r
+ <\r
+ Linear, Areal, Strategy,\r
+ linear_tag, areal_tag, \r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+ : detail::distance::linear_to_areal\r
+ <\r
+ Linear, Areal, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <typename Areal, typename Linear, typename Strategy>\r
+struct distance\r
+ <\r
+ Areal, Linear, Strategy,\r
+ areal_tag, linear_tag, \r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+ : detail::distance::linear_to_areal\r
+ <\r
+ Linear, Areal, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <typename Areal1, typename Areal2, typename Strategy>\r
+struct distance\r
+ <\r
+ Areal1, Areal2, Strategy,\r
+ areal_tag, areal_tag, \r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+ : detail::distance::areal_to_areal\r
+ <\r
+ Areal1, Areal2, Strategy\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+#include <boost/geometry/iterators/segment_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+#include <boost/geometry/algorithms/num_segments.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template <typename Linear1, typename Linear2, typename Strategy>\r
+struct linear_to_linear\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Linear1>::type,\r
+ typename point_type<Linear2>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Linear1 const& linear1,\r
+ Linear2 const& linear2,\r
+ Strategy const& strategy,\r
+ bool = false)\r
+ {\r
+ if (geometry::num_points(linear1) == 1)\r
+ {\r
+ return dispatch::distance\r
+ <\r
+ typename point_type<Linear1>::type,\r
+ Linear2,\r
+ Strategy\r
+ >::apply(*points_begin(linear1), linear2, strategy);\r
+ }\r
+\r
+ if (geometry::num_points(linear2) == 1)\r
+ {\r
+ return dispatch::distance\r
+ <\r
+ typename point_type<Linear2>::type,\r
+ Linear1,\r
+ Strategy\r
+ >::apply(*points_begin(linear2), linear1, strategy);\r
+ }\r
+\r
+ if (geometry::num_segments(linear2) < geometry::num_segments(linear1))\r
+ {\r
+ return point_or_segment_range_to_geometry_rtree\r
+ <\r
+ geometry::segment_iterator<Linear2 const>,\r
+ Linear1,\r
+ Strategy\r
+ >::apply(geometry::segments_begin(linear2),\r
+ geometry::segments_end(linear2),\r
+ linear1,\r
+ strategy);\r
+\r
+ }\r
+\r
+ return point_or_segment_range_to_geometry_rtree\r
+ <\r
+ geometry::segment_iterator<Linear1 const>,\r
+ Linear2,\r
+ Strategy\r
+ >::apply(geometry::segments_begin(linear1),\r
+ geometry::segments_end(linear1),\r
+ linear2,\r
+ strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Linear1, typename Linear2, typename Strategy>\r
+struct distance\r
+ <\r
+ Linear1, Linear2, Strategy,\r
+ linear_tag, linear_tag, \r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::linear_to_linear\r
+ <\r
+ Linear1, Linear2, Strategy\r
+ >\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template <typename MultiPoint1, typename MultiPoint2, typename Strategy>\r
+struct multipoint_to_multipoint\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<MultiPoint1>::type,\r
+ typename point_type<MultiPoint2>::type\r
+ >::type return_type; \r
+\r
+ static inline return_type apply(MultiPoint1 const& multipoint1,\r
+ MultiPoint2 const& multipoint2,\r
+ Strategy const& strategy)\r
+ {\r
+ if (boost::size(multipoint2) < boost::size(multipoint1))\r
+\r
+ {\r
+ return point_or_segment_range_to_geometry_rtree\r
+ <\r
+ typename boost::range_iterator<MultiPoint2 const>::type,\r
+ MultiPoint1,\r
+ Strategy\r
+ >::apply(boost::begin(multipoint2),\r
+ boost::end(multipoint2),\r
+ multipoint1,\r
+ strategy);\r
+ }\r
+\r
+ return point_or_segment_range_to_geometry_rtree\r
+ <\r
+ typename boost::range_iterator<MultiPoint1 const>::type,\r
+ MultiPoint2,\r
+ Strategy\r
+ >::apply(boost::begin(multipoint1),\r
+ boost::end(multipoint1),\r
+ multipoint2,\r
+ strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPoint, typename Linear, typename Strategy>\r
+struct multipoint_to_linear\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<MultiPoint>::type,\r
+ typename point_type<Linear>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPoint const& multipoint,\r
+ Linear const& linear,\r
+ Strategy const& strategy)\r
+ {\r
+ return detail::distance::point_or_segment_range_to_geometry_rtree\r
+ <\r
+ typename boost::range_iterator<MultiPoint const>::type,\r
+ Linear,\r
+ Strategy\r
+ >::apply(boost::begin(multipoint),\r
+ boost::end(multipoint),\r
+ linear,\r
+ strategy);\r
+ }\r
+\r
+ static inline return_type apply(Linear const& linear,\r
+ MultiPoint const& multipoint,\r
+ Strategy const& strategy)\r
+ {\r
+ return apply(multipoint, linear, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPoint, typename Areal, typename Strategy>\r
+class multipoint_to_areal\r
+{\r
+private:\r
+ struct not_covered_by_areal\r
+ {\r
+ not_covered_by_areal(Areal const& areal)\r
+ : m_areal(areal)\r
+ {}\r
+\r
+ template <typename Point>\r
+ inline bool apply(Point const& point) const\r
+ {\r
+ return !geometry::covered_by(point, m_areal);\r
+ }\r
+\r
+ Areal const& m_areal;\r
+ };\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<MultiPoint>::type,\r
+ typename point_type<Areal>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPoint const& multipoint,\r
+ Areal const& areal,\r
+ Strategy const& strategy)\r
+ {\r
+ not_covered_by_areal predicate(areal);\r
+\r
+ if (check_iterator_range\r
+ <\r
+ not_covered_by_areal, false\r
+ >::apply(boost::begin(multipoint),\r
+ boost::end(multipoint),\r
+ predicate))\r
+ {\r
+ return detail::distance::point_or_segment_range_to_geometry_rtree\r
+ <\r
+ typename boost::range_iterator<MultiPoint const>::type,\r
+ Areal,\r
+ Strategy\r
+ >::apply(boost::begin(multipoint),\r
+ boost::end(multipoint),\r
+ areal,\r
+ strategy);\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ static inline return_type apply(Areal const& areal,\r
+ MultiPoint const& multipoint,\r
+ Strategy const& strategy)\r
+ {\r
+ return apply(multipoint, areal, strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename MultiPoint1, typename MultiPoint2, typename Strategy>\r
+struct distance\r
+ <\r
+ MultiPoint1, MultiPoint2, Strategy,\r
+ multi_point_tag, multi_point_tag,\r
+ strategy_tag_distance_point_point, false\r
+ > : detail::distance::multipoint_to_multipoint\r
+ <\r
+ MultiPoint1, MultiPoint2, Strategy\r
+ >\r
+{};\r
+\r
+template <typename MultiPoint, typename Linear, typename Strategy>\r
+struct distance\r
+ <\r
+ MultiPoint, Linear, Strategy, multi_point_tag, linear_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>\r
+{};\r
+\r
+\r
+template <typename Linear, typename MultiPoint, typename Strategy>\r
+struct distance\r
+ <\r
+ Linear, MultiPoint, Strategy, linear_tag, multi_point_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Areal, typename Strategy>\r
+struct distance\r
+ <\r
+ MultiPoint, Areal, Strategy, multi_point_tag, areal_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>\r
+{};\r
+\r
+\r
+template <typename Areal, typename MultiPoint, typename Strategy>\r
+struct distance\r
+ <\r
+ Areal, MultiPoint, Strategy, areal_tag, multi_point_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>\r
+#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template <typename P1, typename P2, typename Strategy>\r
+struct point_to_point\r
+{\r
+ static inline\r
+ typename strategy::distance::services::return_type<Strategy, P1, P2>::type\r
+ apply(P1 const& p1, P2 const& p2, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ return strategy.apply(p1, p2);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Range,\r
+ closure_selector Closure,\r
+ typename Strategy\r
+>\r
+class point_to_range\r
+{\r
+private:\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type comparable_strategy;\r
+\r
+ typedef detail::closest_feature::point_to_point_range\r
+ <\r
+ Point, Range, Closure, comparable_strategy\r
+ > point_to_point_range;\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ typename boost::range_value<Range>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point, Range const& range,\r
+ Strategy const& strategy)\r
+ {\r
+ return_type const zero = return_type(0);\r
+\r
+ if (boost::size(range) == 0)\r
+ {\r
+ return zero;\r
+ }\r
+\r
+ namespace sds = strategy::distance::services;\r
+\r
+ typename sds::return_type\r
+ <\r
+ comparable_strategy,\r
+ Point,\r
+ typename point_type<Range>::type\r
+ >::type cd_min;\r
+\r
+ std::pair\r
+ <\r
+ typename boost::range_iterator<Range const>::type,\r
+ typename boost::range_iterator<Range const>::type\r
+ > it_pair\r
+ = point_to_point_range::apply(point,\r
+ boost::begin(range),\r
+ boost::end(range),\r
+ sds::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy),\r
+ cd_min);\r
+\r
+ return\r
+ is_comparable<Strategy>::value\r
+ ?\r
+ cd_min\r
+ :\r
+ strategy.apply(point, *it_pair.first, *it_pair.second);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Ring,\r
+ closure_selector Closure,\r
+ typename Strategy\r
+>\r
+struct point_to_ring\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Ring>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point,\r
+ Ring const& ring,\r
+ Strategy const& strategy)\r
+ {\r
+ if (geometry::within(point, ring))\r
+ {\r
+ return return_type(0);\r
+ }\r
+\r
+ return point_to_range\r
+ <\r
+ Point, Ring, closure<Ring>::value, Strategy\r
+ >::apply(point, ring, strategy);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Polygon,\r
+ closure_selector Closure,\r
+ typename Strategy\r
+>\r
+class point_to_polygon\r
+{\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Polygon>::type\r
+ >::type return_type;\r
+\r
+private:\r
+ typedef point_to_range\r
+ <\r
+ Point, typename ring_type<Polygon>::type, Closure, Strategy\r
+ > per_ring;\r
+\r
+ struct distance_to_interior_rings\r
+ {\r
+ template <typename InteriorRingIterator>\r
+ static inline return_type apply(Point const& point,\r
+ InteriorRingIterator first,\r
+ InteriorRingIterator last,\r
+ Strategy const& strategy)\r
+ {\r
+ for (InteriorRingIterator it = first; it != last; ++it)\r
+ {\r
+ if (geometry::within(point, *it))\r
+ {\r
+ // the point is inside a polygon hole, so its distance\r
+ // to the polygon its distance to the polygon's\r
+ // hole boundary\r
+ return per_ring::apply(point, *it, strategy);\r
+ }\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ template <typename InteriorRings>\r
+ static inline return_type apply(Point const& point,\r
+ InteriorRings const& interior_rings,\r
+ Strategy const& strategy)\r
+ {\r
+ return apply(point,\r
+ boost::begin(interior_rings),\r
+ boost::end(interior_rings),\r
+ strategy);\r
+ }\r
+ };\r
+\r
+\r
+public:\r
+ static inline return_type apply(Point const& point,\r
+ Polygon const& polygon,\r
+ Strategy const& strategy)\r
+ {\r
+ if (!geometry::covered_by(point, exterior_ring(polygon)))\r
+ {\r
+ // the point is outside the exterior ring, so its distance\r
+ // to the polygon is its distance to the polygon's exterior ring\r
+ return per_ring::apply(point, exterior_ring(polygon), strategy);\r
+ }\r
+\r
+ // Check interior rings\r
+ return distance_to_interior_rings::apply(point,\r
+ interior_rings(polygon),\r
+ strategy);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename MultiGeometry,\r
+ typename Strategy,\r
+ bool CheckCoveredBy = boost::is_same\r
+ <\r
+ typename tag<MultiGeometry>::type, multi_polygon_tag\r
+ >::value\r
+>\r
+class point_to_multigeometry\r
+{\r
+private:\r
+ typedef detail::closest_feature::geometry_to_range geometry_to_range;\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ typename point_type<MultiGeometry>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point,\r
+ MultiGeometry const& multigeometry,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef iterator_selector<MultiGeometry const> selector_type;\r
+\r
+ namespace sds = strategy::distance::services;\r
+\r
+ typename sds::return_type\r
+ <\r
+ typename sds::comparable_type<Strategy>::type,\r
+ Point,\r
+ typename point_type<MultiGeometry>::type\r
+ >::type cd;\r
+\r
+ typename selector_type::iterator_type it_min\r
+ = geometry_to_range::apply(point,\r
+ selector_type::begin(multigeometry),\r
+ selector_type::end(multigeometry),\r
+ sds::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy),\r
+ cd);\r
+\r
+ return\r
+ is_comparable<Strategy>::value\r
+ ?\r
+ cd\r
+ :\r
+ dispatch::distance\r
+ <\r
+ Point,\r
+ typename std::iterator_traits\r
+ <\r
+ typename selector_type::iterator_type\r
+ >::value_type,\r
+ Strategy\r
+ >::apply(point, *it_min, strategy);\r
+ }\r
+};\r
+\r
+\r
+// this is called only for multipolygons, hence the change in the\r
+// template parameter name MultiGeometry to MultiPolygon\r
+template <typename Point, typename MultiPolygon, typename Strategy>\r
+struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ typename point_type<MultiPolygon>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Point const& point,\r
+ MultiPolygon const& multipolygon,\r
+ Strategy const& strategy)\r
+ {\r
+ if (geometry::covered_by(point, multipolygon))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ return point_to_multigeometry\r
+ <\r
+ Point, MultiPolygon, Strategy, false\r
+ >::apply(point, multipolygon, strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// Point-point\r
+template <typename P1, typename P2, typename Strategy>\r
+struct distance\r
+ <\r
+ P1, P2, Strategy, point_tag, point_tag,\r
+ strategy_tag_distance_point_point, false\r
+ > : detail::distance::point_to_point<P1, P2, Strategy>\r
+{};\r
+\r
+\r
+// Point-line version 2, where point-segment strategy is specified\r
+template <typename Point, typename Linestring, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Linestring, Strategy, point_tag, linestring_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::point_to_range<Point, Linestring, closed, Strategy>\r
+{};\r
+\r
+\r
+// Point-ring , where point-segment strategy is specified\r
+template <typename Point, typename Ring, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Ring, Strategy, point_tag, ring_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::point_to_ring\r
+ <\r
+ Point, Ring, closure<Ring>::value, Strategy\r
+ >\r
+{};\r
+\r
+\r
+// Point-polygon , where point-segment strategy is specified\r
+template <typename Point, typename Polygon, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Polygon, Strategy, point_tag, polygon_tag, \r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::point_to_polygon\r
+ <\r
+ Point, Polygon, closure<Polygon>::value, Strategy\r
+ >\r
+{};\r
+\r
+\r
+// Point-segment version 2, with point-segment strategy\r
+template <typename Point, typename Segment, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Segment, Strategy, point_tag, segment_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+{\r
+ static inline typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Segment>::type\r
+ >::type apply(Point const& point,\r
+ Segment const& segment,\r
+ Strategy const& strategy)\r
+ {\r
+ typename point_type<Segment>::type p[2];\r
+ geometry::detail::assign_point_from_index<0>(segment, p[0]);\r
+ geometry::detail::assign_point_from_index<1>(segment, p[1]);\r
+\r
+ boost::ignore_unused(strategy);\r
+ return strategy.apply(point, p[0], p[1]);\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, typename Box, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Box, Strategy, point_tag, box_tag,\r
+ strategy_tag_distance_point_box, false\r
+ >\r
+{\r
+ static inline typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, Point, typename point_type<Box>::type\r
+ >::type\r
+ apply(Point const& point, Box const& box, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ return strategy.apply(point, box);\r
+ }\r
+};\r
+\r
+\r
+template<typename Point, typename MultiPoint, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, MultiPoint, Strategy, point_tag, multi_point_tag,\r
+ strategy_tag_distance_point_point, false\r
+ > : detail::distance::point_to_multigeometry\r
+ <\r
+ Point, MultiPoint, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template<typename Point, typename MultiLinestring, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::point_to_multigeometry\r
+ <\r
+ Point, MultiLinestring, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template<typename Point, typename MultiPolygon, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : detail::distance::point_to_multigeometry\r
+ <\r
+ Point, MultiPolygon, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <typename Point, typename Linear, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Linear, Strategy, point_tag, linear_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : distance\r
+ <\r
+ Point, Linear, Strategy,\r
+ point_tag, typename tag<Linear>::type,\r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+{};\r
+\r
+\r
+template <typename Point, typename Areal, typename Strategy>\r
+struct distance\r
+ <\r
+ Point, Areal, Strategy, point_tag, areal_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ > : distance\r
+ <\r
+ Point, Areal, Strategy,\r
+ point_tag, typename tag<Areal>::type,\r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP\r
+\r
+#include <iterator>\r
+#include <utility>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/iterators/has_one_element.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename PointOrSegmentIterator,\r
+ typename Geometry,\r
+ typename Strategy\r
+>\r
+class point_or_segment_range_to_geometry_rtree\r
+{\r
+private:\r
+ typedef typename std::iterator_traits\r
+ <\r
+ PointOrSegmentIterator\r
+ >::value_type point_or_segment_type;\r
+\r
+ typedef iterator_selector<Geometry const> selector_type;\r
+\r
+ typedef detail::closest_feature::range_to_range_rtree range_to_range;\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<point_or_segment_type>::type,\r
+ typename point_type<Geometry>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(PointOrSegmentIterator first,\r
+ PointOrSegmentIterator last,\r
+ Geometry const& geometry,\r
+ Strategy const& strategy)\r
+ {\r
+ namespace sds = strategy::distance::services;\r
+\r
+ BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ if ( geometry::has_one_element(first, last) )\r
+ {\r
+ return dispatch::distance\r
+ <\r
+ point_or_segment_type, Geometry, Strategy\r
+ >::apply(*first, geometry, strategy);\r
+ }\r
+\r
+ typename sds::return_type\r
+ <\r
+ typename sds::comparable_type<Strategy>::type,\r
+ typename point_type<point_or_segment_type>::type,\r
+ typename point_type<Geometry>::type\r
+ >::type cd_min;\r
+\r
+ std::pair\r
+ <\r
+ point_or_segment_type,\r
+ typename selector_type::iterator_type\r
+ > closest_features\r
+ = range_to_range::apply(first,\r
+ last,\r
+ selector_type::begin(geometry),\r
+ selector_type::end(geometry),\r
+ sds::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy),\r
+ cd_min);\r
+\r
+ return\r
+ is_comparable<Strategy>::value\r
+ ?\r
+ cd_min\r
+ :\r
+ dispatch::distance\r
+ <\r
+ point_or_segment_type, \r
+ typename std::iterator_traits\r
+ <\r
+ typename selector_type::iterator_type\r
+ >::value_type,\r
+ Strategy\r
+ >::apply(closest_features.first,\r
+ *closest_features.second,\r
+ strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <functional>\r
+#include <vector>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/calculation_type.hpp>\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename Box,\r
+ typename Strategy,\r
+ bool UsePointBoxStrategy = false\r
+>\r
+class segment_to_box_2D_generic\r
+{\r
+private:\r
+ typedef typename point_type<Segment>::type segment_point;\r
+ typedef typename point_type<Box>::type box_point;\r
+\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type comparable_strategy;\r
+\r
+ typedef detail::closest_feature::point_to_point_range\r
+ <\r
+ segment_point,\r
+ std::vector<box_point>,\r
+ open,\r
+ comparable_strategy\r
+ > point_to_point_range;\r
+\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ comparable_strategy, segment_point, box_point\r
+ >::type comparable_return_type;\r
+ \r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, segment_point, box_point\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Segment const& segment,\r
+ Box const& box,\r
+ Strategy const& strategy,\r
+ bool check_intersection = true)\r
+ {\r
+ if (check_intersection && geometry::intersects(segment, box))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ comparable_strategy cstrategy =\r
+ strategy::distance::services::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy);\r
+\r
+ // get segment points\r
+ segment_point p[2];\r
+ detail::assign_point_from_index<0>(segment, p[0]);\r
+ detail::assign_point_from_index<1>(segment, p[1]);\r
+\r
+ // get box points\r
+ std::vector<box_point> box_points(4);\r
+ detail::assign_box_corners_oriented<true>(box, box_points);\r
+ \r
+ comparable_return_type cd[6];\r
+ for (unsigned int i = 0; i < 4; ++i)\r
+ {\r
+ cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);\r
+ }\r
+\r
+ std::pair\r
+ <\r
+ typename std::vector<box_point>::const_iterator,\r
+ typename std::vector<box_point>::const_iterator\r
+ > bit_min[2];\r
+\r
+ bit_min[0] = point_to_point_range::apply(p[0],\r
+ box_points.begin(),\r
+ box_points.end(),\r
+ cstrategy,\r
+ cd[4]);\r
+ bit_min[1] = point_to_point_range::apply(p[1],\r
+ box_points.begin(),\r
+ box_points.end(),\r
+ cstrategy,\r
+ cd[5]);\r
+\r
+ unsigned int imin = 0;\r
+ for (unsigned int i = 1; i < 6; ++i)\r
+ {\r
+ if (cd[i] < cd[imin])\r
+ {\r
+ imin = i;\r
+ }\r
+ }\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))\r
+ {\r
+ return cd[imin];\r
+ }\r
+\r
+ if (imin < 4)\r
+ {\r
+ return strategy.apply(box_points[imin], p[0], p[1]);\r
+ }\r
+ else\r
+ {\r
+ unsigned int bimin = imin - 4;\r
+ return strategy.apply(p[bimin],\r
+ *bit_min[bimin].first,\r
+ *bit_min[bimin].second);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename Box,\r
+ typename Strategy\r
+>\r
+class segment_to_box_2D_generic<Segment, Box, Strategy, true>\r
+{\r
+private:\r
+ typedef typename point_type<Segment>::type segment_point;\r
+ typedef typename point_type<Box>::type box_point;\r
+\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type comparable_strategy;\r
+\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ comparable_strategy, segment_point, box_point\r
+ >::type comparable_return_type;\r
+\r
+ typedef typename detail::distance::default_strategy\r
+ <\r
+ segment_point, Box\r
+ >::type point_box_strategy;\r
+\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ point_box_strategy\r
+ >::type point_box_comparable_strategy;\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, segment_point, box_point\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Segment const& segment,\r
+ Box const& box,\r
+ Strategy const& strategy,\r
+ bool check_intersection = true)\r
+ {\r
+ if (check_intersection && geometry::intersects(segment, box))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ comparable_strategy cstrategy =\r
+ strategy::distance::services::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy);\r
+ boost::ignore_unused(cstrategy);\r
+\r
+ // get segment points\r
+ segment_point p[2];\r
+ detail::assign_point_from_index<0>(segment, p[0]);\r
+ detail::assign_point_from_index<1>(segment, p[1]);\r
+\r
+ // get box points\r
+ std::vector<box_point> box_points(4);\r
+ detail::assign_box_corners_oriented<true>(box, box_points);\r
+ \r
+ comparable_return_type cd[6];\r
+ for (unsigned int i = 0; i < 4; ++i)\r
+ {\r
+ cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);\r
+ }\r
+\r
+ point_box_comparable_strategy pb_cstrategy;\r
+ boost::ignore_unused(pb_cstrategy);\r
+ cd[4] = pb_cstrategy.apply(p[0], box);\r
+ cd[5] = pb_cstrategy.apply(p[1], box);\r
+\r
+ unsigned int imin = 0;\r
+ for (unsigned int i = 1; i < 6; ++i)\r
+ {\r
+ if (cd[i] < cd[imin])\r
+ {\r
+ imin = i;\r
+ }\r
+ }\r
+\r
+ if (is_comparable<Strategy>::value)\r
+ {\r
+ return cd[imin];\r
+ }\r
+\r
+ if (imin < 4)\r
+ {\r
+ strategy.apply(box_points[imin], p[0], p[1]);\r
+ }\r
+ else\r
+ {\r
+ return point_box_strategy().apply(p[imin - 4], box);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename ReturnType,\r
+ typename SegmentPoint,\r
+ typename BoxPoint,\r
+ typename PPStrategy,\r
+ typename PSStrategy\r
+>\r
+class segment_to_box_2D\r
+{\r
+private:\r
+ template <typename Result>\r
+ struct cast_to_result\r
+ {\r
+ template <typename T>\r
+ static inline Result apply(T const& t)\r
+ {\r
+ return boost::numeric_cast<Result>(t);\r
+ }\r
+ };\r
+\r
+\r
+ template <typename T, bool IsLess /* true */>\r
+ struct compare_less_equal\r
+ {\r
+ typedef compare_less_equal<T, !IsLess> other;\r
+\r
+ template <typename T1, typename T2>\r
+ inline bool operator()(T1 const& t1, T2 const& t2) const\r
+ {\r
+ return std::less_equal<T>()(cast_to_result<T>::apply(t1),\r
+ cast_to_result<T>::apply(t2));\r
+ }\r
+ };\r
+\r
+ template <typename T>\r
+ struct compare_less_equal<T, false>\r
+ {\r
+ typedef compare_less_equal<T, true> other;\r
+\r
+ template <typename T1, typename T2>\r
+ inline bool operator()(T1 const& t1, T2 const& t2) const\r
+ {\r
+ return std::greater_equal<T>()(cast_to_result<T>::apply(t1),\r
+ cast_to_result<T>::apply(t2));\r
+ }\r
+ };\r
+\r
+\r
+ template <typename LessEqual>\r
+ struct other_compare\r
+ {\r
+ typedef typename LessEqual::other type;\r
+ };\r
+\r
+\r
+ // it is assumed here that p0 lies to the right of the box (so the\r
+ // entire segment lies to the right of the box)\r
+ template <typename LessEqual>\r
+ struct right_of_box\r
+ {\r
+ static inline ReturnType apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& bottom_right,\r
+ BoxPoint const& top_right,\r
+ PPStrategy const& pp_strategy,\r
+ PSStrategy const& ps_strategy)\r
+ {\r
+ boost::ignore_unused(pp_strategy, ps_strategy);\r
+\r
+ // the implementation below is written for non-negative slope\r
+ // segments\r
+ //\r
+ // for negative slope segments swap the roles of bottom_right\r
+ // and top_right and use greater_equal instead of less_equal.\r
+\r
+ typedef cast_to_result<ReturnType> cast;\r
+\r
+ LessEqual less_equal;\r
+\r
+ if (less_equal(geometry::get<1>(top_right), geometry::get<1>(p0)))\r
+ {\r
+ // closest box point is the top-right corner\r
+ return cast::apply(pp_strategy.apply(p0, top_right));\r
+ }\r
+ else if (less_equal(geometry::get<1>(bottom_right),\r
+ geometry::get<1>(p0)))\r
+ {\r
+ // distance is realized between p0 and right-most\r
+ // segment of box\r
+ ReturnType diff = cast::apply(geometry::get<0>(p0))\r
+ - cast::apply(geometry::get<0>(bottom_right));\r
+ return strategy::distance::services::result_from_distance\r
+ <\r
+ PSStrategy, BoxPoint, SegmentPoint\r
+ >::apply(ps_strategy, math::abs(diff));\r
+ }\r
+ else\r
+ {\r
+ // distance is realized between the bottom-right\r
+ // corner of the box and the segment\r
+ return cast::apply(ps_strategy.apply(bottom_right, p0, p1));\r
+ }\r
+ }\r
+ };\r
+\r
+\r
+ // it is assumed here that p0 lies above the box (so the\r
+ // entire segment lies above the box)\r
+ template <typename LessEqual>\r
+ struct above_of_box\r
+ {\r
+ static inline ReturnType apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& top_left,\r
+ PSStrategy const& ps_strategy)\r
+ {\r
+ boost::ignore_unused(ps_strategy);\r
+\r
+ // the segment lies above the box\r
+\r
+ typedef cast_to_result<ReturnType> cast;\r
+\r
+ LessEqual less_equal;\r
+\r
+ // p0 is above the upper segment of the box\r
+ // (and inside its band)\r
+ if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p0)))\r
+ {\r
+ ReturnType diff = cast::apply(geometry::get<1>(p0))\r
+ - cast::apply(geometry::get<1>(top_left));\r
+ return strategy::distance::services::result_from_distance\r
+ <\r
+ PSStrategy, SegmentPoint, BoxPoint\r
+ >::apply(ps_strategy, math::abs(diff));\r
+ }\r
+\r
+ // p0 is to the left of the box, but p1 is above the box\r
+ // in this case the distance is realized between the\r
+ // top-left corner of the box and the segment\r
+ return cast::apply(ps_strategy.apply(top_left, p0, p1));\r
+ }\r
+ };\r
+\r
+\r
+ template <typename LessEqual>\r
+ struct check_right_left_of_box\r
+ {\r
+ static inline bool apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& top_left,\r
+ BoxPoint const& top_right,\r
+ BoxPoint const& bottom_left,\r
+ BoxPoint const& bottom_right,\r
+ PPStrategy const& pp_strategy,\r
+ PSStrategy const& ps_strategy,\r
+ ReturnType& result)\r
+ {\r
+ // p0 lies to the right of the box\r
+ if (geometry::get<0>(p0) >= geometry::get<0>(top_right))\r
+ {\r
+ result = right_of_box\r
+ <\r
+ LessEqual\r
+ >::apply(p0, p1, bottom_right, top_right,\r
+ pp_strategy, ps_strategy);\r
+ return true;\r
+ }\r
+\r
+ // p1 lies to the left of the box\r
+ if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))\r
+ {\r
+ result = right_of_box\r
+ <\r
+ typename other_compare<LessEqual>::type\r
+ >::apply(p1, p0, top_left, bottom_left,\r
+ pp_strategy, ps_strategy);\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+ };\r
+\r
+\r
+ template <typename LessEqual>\r
+ struct check_above_below_of_box\r
+ {\r
+ static inline bool apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& top_left,\r
+ BoxPoint const& top_right,\r
+ BoxPoint const& bottom_left,\r
+ BoxPoint const& bottom_right,\r
+ PSStrategy const& ps_strategy,\r
+ ReturnType& result)\r
+ {\r
+ // the segment lies below the box\r
+ if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))\r
+ {\r
+ result = above_of_box\r
+ <\r
+ typename other_compare<LessEqual>::type\r
+ >::apply(p1, p0, bottom_right, ps_strategy);\r
+ return true;\r
+ }\r
+\r
+ // the segment lies above the box\r
+ if (geometry::get<1>(p0) > geometry::get<1>(top_right))\r
+ {\r
+ result = above_of_box\r
+ <\r
+ LessEqual\r
+ >::apply(p0, p1, top_left, ps_strategy);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ };\r
+\r
+ struct check_generic_position\r
+ {\r
+ static inline bool apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& bottom_left0,\r
+ BoxPoint const& top_right0,\r
+ BoxPoint const& bottom_left1,\r
+ BoxPoint const& top_right1,\r
+ BoxPoint const& corner1,\r
+ BoxPoint const& corner2,\r
+ PSStrategy const& ps_strategy,\r
+ ReturnType& result)\r
+ {\r
+ typedef cast_to_result<ReturnType> cast;\r
+\r
+ ReturnType diff0 = cast::apply(geometry::get<0>(p1))\r
+ - cast::apply(geometry::get<0>(p0));\r
+ ReturnType t_min0 = cast::apply(geometry::get<0>(bottom_left0))\r
+ - cast::apply(geometry::get<0>(p0));\r
+ ReturnType t_max0 = cast::apply(geometry::get<0>(top_right0))\r
+ - cast::apply(geometry::get<0>(p0));\r
+\r
+ ReturnType diff1 = cast::apply(geometry::get<1>(p1))\r
+ - cast::apply(geometry::get<1>(p0));\r
+ ReturnType t_min1 = cast::apply(geometry::get<1>(bottom_left1))\r
+ - cast::apply(geometry::get<1>(p0));\r
+ ReturnType t_max1 = cast::apply(geometry::get<1>(top_right1))\r
+ - cast::apply(geometry::get<1>(p0));\r
+\r
+ if (diff1 < 0)\r
+ {\r
+ diff1 = -diff1;\r
+ t_min1 = -t_min1;\r
+ t_max1 = -t_max1;\r
+ }\r
+\r
+ // t_min0 > t_max1\r
+ if (t_min0 * diff1 > t_max1 * diff0)\r
+ {\r
+ result = cast::apply(ps_strategy.apply(corner1, p0, p1));\r
+ return true;\r
+ }\r
+\r
+ // t_max0 < t_min1\r
+ if (t_max0 * diff1 < t_min1 * diff0)\r
+ {\r
+ result = cast::apply(ps_strategy.apply(corner2, p0, p1));\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ };\r
+\r
+ static inline ReturnType\r
+ non_negative_slope_segment(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& top_left,\r
+ BoxPoint const& top_right,\r
+ BoxPoint const& bottom_left,\r
+ BoxPoint const& bottom_right,\r
+ PPStrategy const& pp_strategy,\r
+ PSStrategy const& ps_strategy)\r
+ {\r
+ typedef compare_less_equal<ReturnType, true> less_equal;\r
+\r
+ // assert that the segment has non-negative slope\r
+ BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))\r
+ && geometry::get<1>(p0) < geometry::get<1>(p1))\r
+ ||\r
+ ( geometry::get<0>(p0) < geometry::get<0>(p1)\r
+ && geometry::get<1>(p0) <= geometry::get<1>(p1) )\r
+ || geometry::has_nan_coordinate(p0)\r
+ || geometry::has_nan_coordinate(p1));\r
+\r
+ ReturnType result(0);\r
+\r
+ if (check_right_left_of_box\r
+ <\r
+ less_equal\r
+ >::apply(p0, p1,\r
+ top_left, top_right, bottom_left, bottom_right,\r
+ pp_strategy, ps_strategy, result))\r
+ {\r
+ return result;\r
+ }\r
+\r
+ if (check_above_below_of_box\r
+ <\r
+ less_equal\r
+ >::apply(p0, p1,\r
+ top_left, top_right, bottom_left, bottom_right,\r
+ ps_strategy, result))\r
+ {\r
+ return result;\r
+ }\r
+\r
+ if (check_generic_position::apply(p0, p1,\r
+ bottom_left, top_right,\r
+ bottom_left, top_right,\r
+ top_left, bottom_right,\r
+ ps_strategy, result))\r
+ {\r
+ return result;\r
+ }\r
+\r
+ // in all other cases the box and segment intersect, so return 0\r
+ return result;\r
+ }\r
+\r
+\r
+ static inline ReturnType\r
+ negative_slope_segment(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& top_left,\r
+ BoxPoint const& top_right,\r
+ BoxPoint const& bottom_left,\r
+ BoxPoint const& bottom_right,\r
+ PPStrategy const& pp_strategy,\r
+ PSStrategy const& ps_strategy)\r
+ {\r
+ typedef compare_less_equal<ReturnType, false> greater_equal;\r
+\r
+ // assert that the segment has negative slope\r
+ BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1)\r
+ && geometry::get<1>(p0) > geometry::get<1>(p1) )\r
+ || geometry::has_nan_coordinate(p0)\r
+ || geometry::has_nan_coordinate(p1) );\r
+\r
+ ReturnType result(0);\r
+\r
+ if (check_right_left_of_box\r
+ <\r
+ greater_equal\r
+ >::apply(p0, p1,\r
+ bottom_left, bottom_right, top_left, top_right,\r
+ pp_strategy, ps_strategy, result))\r
+ {\r
+ return result;\r
+ }\r
+\r
+ if (check_above_below_of_box\r
+ <\r
+ greater_equal\r
+ >::apply(p1, p0,\r
+ top_right, top_left, bottom_right, bottom_left,\r
+ ps_strategy, result))\r
+ {\r
+ return result;\r
+ }\r
+\r
+ if (check_generic_position::apply(p0, p1,\r
+ bottom_left, top_right,\r
+ top_right, bottom_left,\r
+ bottom_left, top_right,\r
+ ps_strategy, result))\r
+ {\r
+ return result;\r
+ }\r
+\r
+ // in all other cases the box and segment intersect, so return 0\r
+ return result;\r
+ }\r
+\r
+public:\r
+ static inline ReturnType apply(SegmentPoint const& p0,\r
+ SegmentPoint const& p1,\r
+ BoxPoint const& top_left,\r
+ BoxPoint const& top_right,\r
+ BoxPoint const& bottom_left,\r
+ BoxPoint const& bottom_right,\r
+ PPStrategy const& pp_strategy,\r
+ PSStrategy const& ps_strategy)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1)\r
+ || geometry::has_nan_coordinate(p0)\r
+ || geometry::has_nan_coordinate(p1) );\r
+\r
+ if (geometry::get<0>(p0) < geometry::get<0>(p1)\r
+ && geometry::get<1>(p0) > geometry::get<1>(p1))\r
+ {\r
+ return negative_slope_segment(p0, p1,\r
+ top_left, top_right,\r
+ bottom_left, bottom_right,\r
+ pp_strategy, ps_strategy);\r
+ }\r
+\r
+ return non_negative_slope_segment(p0, p1,\r
+ top_left, top_right,\r
+ bottom_left, bottom_right,\r
+ pp_strategy, ps_strategy);\r
+ }\r
+};\r
+\r
+\r
+//=========================================================================\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename Box,\r
+ typename std::size_t Dimension,\r
+ typename PPStrategy,\r
+ typename PSStrategy\r
+>\r
+class segment_to_box\r
+ : not_implemented<Segment, Box>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename Box,\r
+ typename PPStrategy,\r
+ typename PSStrategy\r
+>\r
+class segment_to_box<Segment, Box, 2, PPStrategy, PSStrategy>\r
+{\r
+private:\r
+ typedef typename point_type<Segment>::type segment_point;\r
+ typedef typename point_type<Box>::type box_point;\r
+\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ PPStrategy\r
+ >::type pp_comparable_strategy;\r
+\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ PSStrategy\r
+ >::type ps_comparable_strategy;\r
+\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ ps_comparable_strategy, segment_point, box_point\r
+ >::type comparable_return_type;\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ PSStrategy, segment_point, box_point\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Segment const& segment,\r
+ Box const& box,\r
+ PPStrategy const& pp_strategy,\r
+ PSStrategy const& ps_strategy)\r
+ {\r
+ segment_point p[2];\r
+ detail::assign_point_from_index<0>(segment, p[0]);\r
+ detail::assign_point_from_index<1>(segment, p[1]);\r
+\r
+ if (geometry::equals(p[0], p[1]))\r
+ {\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_same\r
+ <\r
+ ps_comparable_strategy,\r
+ PSStrategy\r
+ >,\r
+ typename strategy::distance::services::comparable_type\r
+ <\r
+ typename detail::distance::default_strategy\r
+ <\r
+ segment_point, Box\r
+ >::type\r
+ >::type,\r
+ typename detail::distance::default_strategy\r
+ <\r
+ segment_point, Box\r
+ >::type\r
+ >::type point_box_strategy_type;\r
+\r
+ return dispatch::distance\r
+ <\r
+ segment_point,\r
+ Box,\r
+ point_box_strategy_type\r
+ >::apply(p[0], box, point_box_strategy_type());\r
+ }\r
+\r
+ box_point top_left, top_right, bottom_left, bottom_right;\r
+ detail::assign_box_corners(box, bottom_left, bottom_right,\r
+ top_left, top_right);\r
+\r
+ if (geometry::less<segment_point>()(p[0], p[1]))\r
+ {\r
+ return segment_to_box_2D\r
+ <\r
+ return_type,\r
+ segment_point,\r
+ box_point,\r
+ PPStrategy,\r
+ PSStrategy\r
+ >::apply(p[0], p[1],\r
+ top_left, top_right, bottom_left, bottom_right,\r
+ pp_strategy,\r
+ ps_strategy);\r
+ }\r
+ else\r
+ {\r
+ return segment_to_box_2D\r
+ <\r
+ return_type,\r
+ segment_point,\r
+ box_point,\r
+ PPStrategy,\r
+ PSStrategy\r
+ >::apply(p[1], p[0],\r
+ top_left, top_right, bottom_left, bottom_right,\r
+ pp_strategy,\r
+ ps_strategy);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Segment, typename Box, typename Strategy>\r
+struct distance\r
+ <\r
+ Segment, Box, Strategy, segment_tag, box_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+{\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Segment>::type,\r
+ typename point_type<Box>::type\r
+ >::type return_type;\r
+\r
+\r
+ static inline return_type apply(Segment const& segment,\r
+ Box const& box,\r
+ Strategy const& strategy)\r
+ {\r
+ assert_dimension_equal<Segment, Box>();\r
+\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_same\r
+ <\r
+ typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type,\r
+ Strategy\r
+ >,\r
+ typename strategy::distance::services::comparable_type\r
+ <\r
+ typename detail::distance::default_strategy\r
+ <\r
+ typename point_type<Segment>::type,\r
+ typename point_type<Box>::type\r
+ >::type\r
+ >::type,\r
+ typename detail::distance::default_strategy\r
+ <\r
+ typename point_type<Segment>::type,\r
+ typename point_type<Box>::type\r
+ >::type\r
+ >::type pp_strategy_type;\r
+\r
+\r
+ return detail::distance::segment_to_box\r
+ <\r
+ Segment,\r
+ Box,\r
+ dimension<Segment>::value,\r
+ pp_strategy_type,\r
+ Strategy\r
+ >::apply(segment, box, pp_strategy_type(), strategy);\r
+ }\r
+};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP\r
+\r
+#include <algorithm>\r
+#include <iterator>\r
+\r
+#include <boost/core/addressof.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/distance.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace distance\r
+{\r
+\r
+\r
+\r
+// compute segment-segment distance\r
+template<typename Segment1, typename Segment2, typename Strategy>\r
+class segment_to_segment\r
+{\r
+private:\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type comparable_strategy;\r
+\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ comparable_strategy,\r
+ typename point_type<Segment1>::type,\r
+ typename point_type<Segment2>::type\r
+ >::type comparable_return_type;\r
+\r
+public:\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Segment1>::type,\r
+ typename point_type<Segment2>::type\r
+ >::type return_type;\r
+\r
+ static inline return_type\r
+ apply(Segment1 const& segment1, Segment2 const& segment2,\r
+ Strategy const& strategy)\r
+ {\r
+ if (geometry::intersects(segment1, segment2))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ typename point_type<Segment1>::type p[2];\r
+ detail::assign_point_from_index<0>(segment1, p[0]);\r
+ detail::assign_point_from_index<1>(segment1, p[1]);\r
+\r
+ typename point_type<Segment2>::type q[2];\r
+ detail::assign_point_from_index<0>(segment2, q[0]);\r
+ detail::assign_point_from_index<1>(segment2, q[1]);\r
+\r
+ comparable_strategy cstrategy =\r
+ strategy::distance::services::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(strategy);\r
+\r
+ comparable_return_type d[4];\r
+ d[0] = cstrategy.apply(q[0], p[0], p[1]);\r
+ d[1] = cstrategy.apply(q[1], p[0], p[1]);\r
+ d[2] = cstrategy.apply(p[0], q[0], q[1]);\r
+ d[3] = cstrategy.apply(p[1], q[0], q[1]);\r
+\r
+ std::size_t imin = std::distance(boost::addressof(d[0]),\r
+ std::min_element(d, d + 4));\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))\r
+ {\r
+ return d[imin];\r
+ }\r
+\r
+ switch (imin)\r
+ {\r
+ case 0:\r
+ return strategy.apply(q[0], p[0], p[1]);\r
+ case 1:\r
+ return strategy.apply(q[1], p[0], p[1]);\r
+ case 2:\r
+ return strategy.apply(p[0], q[0], q[1]);\r
+ default:\r
+ return strategy.apply(p[1], q[0], q[1]);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+}} // namespace detail::distance\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+\r
+// segment-segment\r
+template <typename Segment1, typename Segment2, typename Strategy>\r
+struct distance\r
+ <\r
+ Segment1, Segment2, Strategy, segment_tag, segment_tag,\r
+ strategy_tag_distance_point_segment, false\r
+ >\r
+ : detail::distance::segment_to_segment<Segment1, Segment2, Strategy>\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+template\r
+<\r
+ std::size_t Index,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct envelope_indexed_box\r
+{\r
+ template <typename BoxIn, typename BoxOut>\r
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)\r
+ {\r
+ detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);\r
+ detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);\r
+\r
+ detail::conversion::point_to_point\r
+ <\r
+ detail::indexed_point_view<BoxIn const, Index>,\r
+ detail::indexed_point_view<BoxOut, Index>,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(box_in_corner, mbr_corner);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ std::size_t Index,\r
+ std::size_t DimensionCount\r
+>\r
+struct envelope_indexed_box_on_spheroid\r
+{\r
+ template <typename BoxIn, typename BoxOut>\r
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)\r
+ {\r
+ // transform() does not work with boxes of dimension higher\r
+ // than 2; to account for such boxes we transform the min/max\r
+ // points of the boxes using the indexed_point_view\r
+ detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);\r
+ detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);\r
+\r
+ // first transform the units\r
+ transform_units(box_in_corner, mbr_corner);\r
+\r
+ // now transform the remaining coordinates\r
+ detail::conversion::point_to_point\r
+ <\r
+ detail::indexed_point_view<BoxIn const, Index>,\r
+ detail::indexed_point_view<BoxOut, Index>,\r
+ 2,\r
+ DimensionCount\r
+ >::apply(box_in_corner, mbr_corner);\r
+ }\r
+};\r
+\r
+\r
+struct envelope_box\r
+{\r
+ template<typename BoxIn, typename BoxOut>\r
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)\r
+ {\r
+ envelope_indexed_box\r
+ <\r
+ min_corner, 0, dimension<BoxIn>::value\r
+ >::apply(box_in, mbr);\r
+\r
+ envelope_indexed_box\r
+ <\r
+ max_corner, 0, dimension<BoxIn>::value\r
+ >::apply(box_in, mbr);\r
+ }\r
+};\r
+\r
+\r
+struct envelope_box_on_spheroid\r
+{\r
+ template <typename BoxIn, typename BoxOut>\r
+ static inline void apply(BoxIn const& box_in, BoxOut& mbr)\r
+ {\r
+ BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);\r
+\r
+ envelope_indexed_box_on_spheroid\r
+ <\r
+ min_corner, dimension<BoxIn>::value\r
+ >::apply(box_in_normalized, mbr);\r
+\r
+ envelope_indexed_box_on_spheroid\r
+ <\r
+ max_corner, dimension<BoxIn>::value\r
+ >::apply(box_in_normalized, mbr);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Box, typename CS_Tag>\r
+struct envelope<Box, box_tag, CS_Tag>\r
+ : detail::envelope::envelope_box\r
+{};\r
+\r
+\r
+template <typename Box>\r
+struct envelope<Box, box_tag, spherical_equatorial_tag>\r
+ : detail::envelope::envelope_box_on_spheroid\r
+{};\r
+\r
+\r
+template <typename Box>\r
+struct envelope<Box, box_tag, geographic_tag>\r
+ : detail::envelope::envelope_box_on_spheroid\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/linear.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/point.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/range.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+struct envelope_polygon\r
+{\r
+ template <typename Polygon, typename Box>\r
+ static inline void apply(Polygon const& polygon, Box& mbr)\r
+ {\r
+ typename ring_return_type<Polygon const>::type ext_ring\r
+ = exterior_ring(polygon);\r
+\r
+ if (geometry::is_empty(ext_ring))\r
+ {\r
+ // if the exterior ring is empty, consider the interior rings\r
+ envelope_multi_range\r
+ <\r
+ envelope_range\r
+ >::apply(interior_rings(polygon), mbr);\r
+ }\r
+ else\r
+ {\r
+ // otherwise, consider only the exterior ring\r
+ envelope_range::apply(ext_ring, mbr);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Ring>\r
+struct envelope<Ring, ring_tag>\r
+ : detail::envelope::envelope_range\r
+{};\r
+\r
+\r
+template <typename Polygon>\r
+struct envelope<Polygon, polygon_tag>\r
+ : detail::envelope::envelope_polygon\r
+{};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct envelope<MultiPolygon, multi_polygon_tag>\r
+ : detail::envelope::envelope_multi_range\r
+ <\r
+ detail::envelope::envelope_polygon\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/bounds.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct initialize_loop\r
+{\r
+ template <typename Box, typename CoordinateType>\r
+ static inline void apply(Box& box,\r
+ CoordinateType min_value,\r
+ CoordinateType max_value)\r
+ {\r
+ geometry::set<min_corner, Dimension>(box, min_value);\r
+ geometry::set<max_corner, Dimension>(box, max_value);\r
+\r
+ initialize_loop\r
+ <\r
+ Dimension + 1, DimensionCount\r
+ >::apply(box, min_value, max_value);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct initialize_loop<DimensionCount, DimensionCount>\r
+{\r
+ template <typename Box, typename CoordinateType>\r
+ static inline void apply(Box&, CoordinateType, CoordinateType)\r
+ {\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Box,\r
+ std::size_t Dimension = 0,\r
+ std::size_t DimensionCount = dimension<Box>::value\r
+>\r
+struct initialize\r
+{\r
+ typedef typename coordinate_type<Box>::type coordinate_type;\r
+\r
+ static inline void apply(Box& box,\r
+ coordinate_type min_value\r
+ = boost::numeric::bounds<coordinate_type>::highest(),\r
+ coordinate_type max_value\r
+ = boost::numeric::bounds<coordinate_type>::lowest())\r
+ {\r
+ initialize_loop\r
+ <\r
+ Dimension, DimensionCount\r
+ >::apply(box, min_value, max_value);\r
+ }\r
+};\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct envelope\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Geometry const& geometry, Box& box)\r
+ {\r
+ concepts::check<Geometry const>();\r
+ concepts::check<Box>();\r
+\r
+ dispatch::envelope<Geometry>::apply(geometry, box);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Box>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ Box& m_box;\r
+\r
+ visitor(Box& box): m_box(box) {}\r
+\r
+ template <typename Geometry>\r
+ void operator()(Geometry const& geometry) const\r
+ {\r
+ envelope<Geometry>::apply(geometry, m_box);\r
+ }\r
+ };\r
+\r
+ template <typename Box>\r
+ static inline void\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ Box& box)\r
+ {\r
+ boost::apply_visitor(visitor<Box>(box), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{envelope}\r
+\ingroup envelope\r
+\details \details_calc{envelope,\det_envelope}.\r
+\tparam Geometry \tparam_geometry\r
+\tparam Box \tparam_box\r
+\param geometry \param_geometry\r
+\param mbr \param_box \param_set{envelope}\r
+\r
+\qbk{[include reference/algorithms/envelope.qbk]}\r
+\qbk{\r
+[heading Example]\r
+[envelope] [envelope_output]\r
+}\r
+*/\r
+template<typename Geometry, typename Box>\r
+inline void envelope(Geometry const& geometry, Box& mbr)\r
+{\r
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc{envelope}\r
+\ingroup envelope\r
+\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}\r
+\tparam Box \tparam_box\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{envelope}\r
+\r
+\qbk{[include reference/algorithms/envelope.qbk]}\r
+\qbk{\r
+[heading Example]\r
+[return_envelope] [return_envelope_output]\r
+}\r
+*/\r
+template<typename Box, typename Geometry>\r
+inline Box return_envelope(Geometry const& geometry)\r
+{\r
+ Box mbr;\r
+ resolve_variant::envelope<Geometry>::apply(geometry, mbr);\r
+ return mbr;\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+\r
+\r
+namespace boost { namespace geometry \r
+{\r
+\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+struct intersects_antimeridian\r
+{\r
+ template <typename Units, typename CoordinateType>\r
+ static inline bool apply(CoordinateType const& lon1,\r
+ CoordinateType const& lat1,\r
+ CoordinateType const& lon2,\r
+ CoordinateType const& lat2)\r
+ {\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ CoordinateType, Units\r
+ > constants;\r
+ \r
+ return\r
+ math::equals(math::abs(lat1), constants::max_latitude())\r
+ ||\r
+ math::equals(math::abs(lat2), constants::max_latitude())\r
+ ||\r
+ math::larger(math::abs(lon1 - lon2), constants::half_period());\r
+ }\r
+\r
+ template <typename Segment>\r
+ static inline bool apply(Segment const& segment)\r
+ {\r
+ return apply(detail::indexed_point_view<Segment, 0>(segment),\r
+ detail::indexed_point_view<Segment, 1>(segment));\r
+ }\r
+\r
+ template <typename Point>\r
+ static inline bool apply(Point const& p1, Point const& p2)\r
+ {\r
+ Point p1_normalized = detail::return_normalized<Point>(p1);\r
+ Point p2_normalized = detail::return_normalized<Point>(p2);\r
+\r
+ return apply\r
+ <\r
+ typename coordinate_system<Point>::type::units\r
+ >(geometry::get<0>(p1_normalized),\r
+ geometry::get<1>(p1_normalized),\r
+ geometry::get<0>(p2_normalized),\r
+ geometry::get<1>(p2_normalized));\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/iterators/segment_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+struct envelope_linestring_on_spheroid\r
+{\r
+ template <typename Linestring, typename Box>\r
+ static inline void apply(Linestring const& linestring, Box& mbr)\r
+ {\r
+ envelope_range::apply(geometry::segments_begin(linestring),\r
+ geometry::segments_end(linestring),\r
+ mbr);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Linestring, typename CS_Tag>\r
+struct envelope<Linestring, linestring_tag, CS_Tag>\r
+ : detail::envelope::envelope_range\r
+{};\r
+\r
+template <typename Linestring>\r
+struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>\r
+ : detail::envelope::envelope_linestring_on_spheroid\r
+{};\r
+\r
+\r
+template <typename MultiLinestring, typename CS_Tag>\r
+struct envelope\r
+ <\r
+ MultiLinestring, multi_linestring_tag, CS_Tag\r
+ > : detail::envelope::envelope_multi_range\r
+ <\r
+ detail::envelope::envelope_range\r
+ >\r
+{};\r
+\r
+template <typename MultiLinestring>\r
+struct envelope\r
+ <\r
+ MultiLinestring, multi_linestring_tag, spherical_equatorial_tag\r
+ > : detail::envelope::envelope_multi_range_on_spheroid\r
+ <\r
+ detail::envelope::envelope_linestring_on_spheroid\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <utility>\r
+#include <vector>\r
+\r
+#include <boost/algorithm/minmax_element.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/geometries/helper_geometry.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/range.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/point.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+class envelope_multipoint_on_spheroid\r
+{\r
+private:\r
+ template <std::size_t Dim>\r
+ struct coordinate_less\r
+ {\r
+ template <typename Point>\r
+ inline bool operator()(Point const& point1, Point const& point2) const\r
+ {\r
+ return math::smaller(geometry::get<Dim>(point1),\r
+ geometry::get<Dim>(point2));\r
+ }\r
+ };\r
+\r
+ template <typename Constants, typename MultiPoint, typename OutputIterator>\r
+ static inline void analyze_point_coordinates(MultiPoint const& multipoint,\r
+ bool& has_south_pole,\r
+ bool& has_north_pole,\r
+ OutputIterator oit)\r
+ {\r
+ typedef typename boost::range_value<MultiPoint>::type point_type;\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiPoint const\r
+ >::type iterator_type;\r
+\r
+ // analyze point coordinates:\r
+ // (1) normalize point coordinates\r
+ // (2) check if any point is the north or the south pole\r
+ // (3) put all non-pole points in a container\r
+ //\r
+ // notice that at this point in the algorithm, we have at\r
+ // least two points on the spheroid\r
+ has_south_pole = false;\r
+ has_north_pole = false;\r
+\r
+ for (iterator_type it = boost::begin(multipoint);\r
+ it != boost::end(multipoint);\r
+ ++it)\r
+ {\r
+ point_type point = detail::return_normalized<point_type>(*it);\r
+\r
+ if (math::equals(geometry::get<1>(point),\r
+ Constants::min_latitude()))\r
+ {\r
+ has_south_pole = true;\r
+ }\r
+ else if (math::equals(geometry::get<1>(point),\r
+ Constants::max_latitude()))\r
+ {\r
+ has_north_pole = true;\r
+ }\r
+ else\r
+ {\r
+ *oit++ = point;\r
+ }\r
+ }\r
+ }\r
+\r
+ template <typename SortedRange, typename Value>\r
+ static inline Value maximum_gap(SortedRange const& sorted_range,\r
+ Value& max_gap_left,\r
+ Value& max_gap_right)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ SortedRange const\r
+ >::type iterator_type;\r
+\r
+ iterator_type it1 = boost::begin(sorted_range), it2 = it1;\r
+ ++it2;\r
+ max_gap_left = geometry::get<0>(*it1);\r
+ max_gap_right = geometry::get<0>(*it2);\r
+\r
+ Value max_gap = max_gap_right - max_gap_left;\r
+ for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)\r
+ {\r
+ Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);\r
+ if (math::larger(gap, max_gap))\r
+ {\r
+ max_gap_left = geometry::get<0>(*it1);\r
+ max_gap_right = geometry::get<0>(*it2);\r
+ max_gap = gap;\r
+ }\r
+ }\r
+\r
+ return max_gap;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Constants,\r
+ typename PointRange,\r
+ typename LongitudeLess,\r
+ typename CoordinateType\r
+ >\r
+ static inline void get_min_max_longitudes(PointRange& range,\r
+ LongitudeLess const& lon_less,\r
+ CoordinateType& lon_min,\r
+ CoordinateType& lon_max)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ PointRange const\r
+ >::type iterator_type;\r
+\r
+ // compute min and max longitude values\r
+ std::pair<iterator_type, iterator_type> min_max_longitudes\r
+ = boost::minmax_element(boost::begin(range),\r
+ boost::end(range),\r
+ lon_less);\r
+\r
+ lon_min = geometry::get<0>(*min_max_longitudes.first);\r
+ lon_max = geometry::get<0>(*min_max_longitudes.second);\r
+\r
+ // if the longitude span is "large" compute the true maximum gap\r
+ if (math::larger(lon_max - lon_min, Constants::half_period()))\r
+ {\r
+ std::sort(boost::begin(range), boost::end(range), lon_less);\r
+\r
+ CoordinateType max_gap_left = 0, max_gap_right = 0;\r
+ CoordinateType max_gap\r
+ = maximum_gap(range, max_gap_left, max_gap_right);\r
+\r
+ CoordinateType complement_gap\r
+ = Constants::period() + lon_min - lon_max;\r
+\r
+ if (math::larger(max_gap, complement_gap))\r
+ {\r
+ lon_min = max_gap_right;\r
+ lon_max = max_gap_left + Constants::period();\r
+ }\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Constants,\r
+ typename Iterator,\r
+ typename LatitudeLess,\r
+ typename CoordinateType\r
+ >\r
+ static inline void get_min_max_latitudes(Iterator const first,\r
+ Iterator const last,\r
+ LatitudeLess const& lat_less,\r
+ bool has_south_pole,\r
+ bool has_north_pole,\r
+ CoordinateType& lat_min,\r
+ CoordinateType& lat_max)\r
+ {\r
+ if (has_south_pole && has_north_pole)\r
+ {\r
+ lat_min = Constants::min_latitude();\r
+ lat_max = Constants::max_latitude();\r
+ }\r
+ else if (has_south_pole)\r
+ {\r
+ lat_min = Constants::min_latitude();\r
+ lat_max\r
+ = geometry::get<1>(*std::max_element(first, last, lat_less));\r
+ }\r
+ else if (has_north_pole)\r
+ {\r
+ lat_min\r
+ = geometry::get<1>(*std::min_element(first, last, lat_less));\r
+ lat_max = Constants::max_latitude();\r
+ }\r
+ else\r
+ {\r
+ std::pair<Iterator, Iterator> min_max_latitudes\r
+ = boost::minmax_element(first, last, lat_less);\r
+\r
+ lat_min = geometry::get<1>(*min_max_latitudes.first);\r
+ lat_max = geometry::get<1>(*min_max_latitudes.second);\r
+ }\r
+ }\r
+\r
+public:\r
+ template <typename MultiPoint, typename Box>\r
+ static inline void apply(MultiPoint const& multipoint, Box& mbr)\r
+ {\r
+ typedef typename point_type<MultiPoint>::type point_type;\r
+ typedef typename coordinate_type<MultiPoint>::type coordinate_type;\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiPoint const\r
+ >::type iterator_type;\r
+\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ coordinate_type,\r
+ typename coordinate_system<MultiPoint>::type::units\r
+ > constants;\r
+\r
+ if (boost::empty(multipoint))\r
+ {\r
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);\r
+ return;\r
+ }\r
+\r
+ initialize<Box, 0, 2>::apply(mbr);\r
+\r
+ if (boost::size(multipoint) == 1)\r
+ {\r
+ return dispatch::envelope\r
+ <\r
+ typename boost::range_value<MultiPoint>::type\r
+ >::apply(range::front(multipoint), mbr);\r
+ }\r
+\r
+ // analyze the points and put the non-pole ones in the\r
+ // points vector\r
+ std::vector<point_type> points;\r
+ bool has_north_pole = false, has_south_pole = false;\r
+\r
+ analyze_point_coordinates<constants>(multipoint,\r
+ has_south_pole, has_north_pole,\r
+ std::back_inserter(points));\r
+\r
+ coordinate_type lon_min, lat_min, lon_max, lat_max;\r
+ if (points.size() == 1)\r
+ {\r
+ // we have one non-pole point and at least one pole point\r
+ lon_min = geometry::get<0>(range::front(points));\r
+ lon_max = geometry::get<0>(range::front(points));\r
+ lat_min = has_south_pole\r
+ ? constants::min_latitude()\r
+ : constants::max_latitude();\r
+ lat_max = has_north_pole\r
+ ? constants::max_latitude()\r
+ : constants::min_latitude();\r
+ }\r
+ else if (points.empty())\r
+ {\r
+ // all points are pole points\r
+ BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);\r
+ lon_min = coordinate_type(0);\r
+ lon_max = coordinate_type(0);\r
+ lat_min = has_south_pole\r
+ ? constants::min_latitude()\r
+ : constants::max_latitude();\r
+ lat_max = (has_north_pole)\r
+ ? constants::max_latitude()\r
+ : constants::min_latitude();\r
+ }\r
+ else\r
+ {\r
+ get_min_max_longitudes<constants>(points,\r
+ coordinate_less<0>(),\r
+ lon_min,\r
+ lon_max);\r
+\r
+ get_min_max_latitudes<constants>(points.begin(),\r
+ points.end(),\r
+ coordinate_less<1>(),\r
+ has_south_pole,\r
+ has_north_pole,\r
+ lat_min,\r
+ lat_max);\r
+ }\r
+\r
+ typedef typename helper_geometry\r
+ <\r
+ Box,\r
+ coordinate_type,\r
+ typename coordinate_system<MultiPoint>::type::units\r
+ >::type helper_box_type;\r
+\r
+ helper_box_type helper_mbr;\r
+\r
+ geometry::set<min_corner, 0>(helper_mbr, lon_min);\r
+ geometry::set<min_corner, 1>(helper_mbr, lat_min);\r
+ geometry::set<max_corner, 0>(helper_mbr, lon_max);\r
+ geometry::set<max_corner, 1>(helper_mbr, lat_max);\r
+\r
+ // now transform to output MBR (per index)\r
+ envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);\r
+ envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);\r
+\r
+ // compute envelope for higher coordinates\r
+ iterator_type it = boost::begin(multipoint);\r
+ envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);\r
+\r
+ for (++it; it != boost::end(multipoint); ++it)\r
+ {\r
+ detail::expand::point_loop\r
+ <\r
+ strategy::compare::default_strategy,\r
+ strategy::compare::default_strategy,\r
+ 2, dimension<Box>::value\r
+ >::apply(mbr, *it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename MultiPoint, typename CSTag>\r
+struct envelope<MultiPoint, multi_point_tag, CSTag>\r
+ : detail::envelope::envelope_range\r
+{};\r
+\r
+template <typename MultiPoint>\r
+struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag>\r
+ : detail::envelope::envelope_multipoint_on_spheroid\r
+{};\r
+\r
+template <typename MultiPoint>\r
+struct envelope<MultiPoint, multi_point_tag, geographic_tag>\r
+ : detail::envelope::envelope_multipoint_on_spheroid\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct envelope_one_point\r
+{\r
+ template <std::size_t Index, typename Point, typename Box>\r
+ static inline void apply(Point const& point, Box& mbr)\r
+ {\r
+ detail::indexed_point_view<Box, Index> box_corner(mbr);\r
+ detail::conversion::point_to_point\r
+ <\r
+ Point,\r
+ detail::indexed_point_view<Box, Index>,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(point, box_corner);\r
+ }\r
+\r
+ template <typename Point, typename Box>\r
+ static inline void apply(Point const& point, Box& mbr)\r
+ {\r
+ apply<min_corner>(point, mbr);\r
+ apply<max_corner>(point, mbr);\r
+ }\r
+};\r
+\r
+\r
+struct envelope_point_on_spheroid\r
+{\r
+ template<typename Point, typename Box>\r
+ static inline void apply(Point const& point, Box& mbr)\r
+ {\r
+ Point normalized_point = detail::return_normalized<Point>(point);\r
+\r
+ typename point_type<Box>::type box_point;\r
+\r
+ // transform units of input point to units of a box point\r
+ transform_units(normalized_point, box_point);\r
+\r
+ geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));\r
+ geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));\r
+\r
+ geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));\r
+ geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));\r
+\r
+ envelope_one_point\r
+ <\r
+ 2, dimension<Point>::value\r
+ >::apply(normalized_point, mbr);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Point, typename CS_Tag>\r
+struct envelope<Point, point_tag, CS_Tag>\r
+ : detail::envelope::envelope_one_point<0, dimension<Point>::value>\r
+{};\r
+\r
+\r
+template <typename Point>\r
+struct envelope<Point, point_tag, spherical_equatorial_tag>\r
+ : detail::envelope::envelope_point_on_spheroid\r
+{};\r
+\r
+\r
+template <typename Point>\r
+struct envelope<Point, point_tag, geographic_tag>\r
+ : detail::envelope::envelope_point_on_spheroid\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP\r
+\r
+#include <iterator>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand/box.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/point.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/segment.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+// implementation for simple ranges\r
+struct envelope_range\r
+{\r
+ template <typename Iterator, typename Box>\r
+ static inline void apply(Iterator first, Iterator last, Box& mbr)\r
+ {\r
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;\r
+\r
+ // initialize MBR\r
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);\r
+\r
+ Iterator it = first;\r
+ if (it != last)\r
+ {\r
+ // initialize box with first element in range\r
+ dispatch::envelope<value_type>::apply(*it, mbr);\r
+\r
+ // consider now the remaining elements in the range (if any)\r
+ for (++it; it != last; ++it)\r
+ {\r
+ dispatch::expand<Box, value_type>::apply(mbr, *it);\r
+ }\r
+ }\r
+ }\r
+\r
+ template <typename Range, typename Box>\r
+ static inline void apply(Range const& range, Box& mbr)\r
+ {\r
+ return apply(boost::begin(range), boost::end(range), mbr);\r
+ }\r
+};\r
+\r
+\r
+// implementation for multi-ranges\r
+template <typename EnvelopePolicy>\r
+struct envelope_multi_range\r
+{\r
+ template <typename MultiRange, typename Box>\r
+ static inline void apply(MultiRange const& multirange, Box& mbr)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiRange const\r
+ >::type iterator_type;\r
+\r
+ bool initialized = false;\r
+ for (iterator_type it = boost::begin(multirange);\r
+ it != boost::end(multirange);\r
+ ++it)\r
+ {\r
+ if (! geometry::is_empty(*it))\r
+ {\r
+ if (initialized)\r
+ {\r
+ Box helper_mbr;\r
+ EnvelopePolicy::apply(*it, helper_mbr);\r
+\r
+ dispatch::expand<Box, Box>::apply(mbr, helper_mbr);\r
+ }\r
+ else\r
+ {\r
+ // compute the initial envelope\r
+ EnvelopePolicy::apply(*it, mbr);\r
+ initialized = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (! initialized)\r
+ {\r
+ // if not already initialized, initialize MBR\r
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+// implementation for multi-range on a spheroid (longitude is periodic)\r
+template <typename EnvelopePolicy>\r
+struct envelope_multi_range_on_spheroid\r
+{\r
+ template <typename MultiRange, typename Box>\r
+ static inline void apply(MultiRange const& multirange, Box& mbr)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiRange const\r
+ >::type iterator_type;\r
+\r
+ // due to the periodicity of longitudes we need to compute the boxes\r
+ // of all the single geometries and keep them in a container\r
+ std::vector<Box> boxes;\r
+ for (iterator_type it = boost::begin(multirange);\r
+ it != boost::end(multirange);\r
+ ++it)\r
+ {\r
+ if (! geometry::is_empty(*it))\r
+ {\r
+ Box helper_box;\r
+ EnvelopePolicy::apply(*it, helper_box);\r
+ boxes.push_back(helper_box);\r
+ }\r
+ }\r
+\r
+ // now we need to compute the envelope of the range of boxes\r
+ // (cannot be done in an incremental fashion as in the\r
+ // Cartesian coordinate system)\r
+ // if all single geometries are empty no boxes have been found\r
+ // and the MBR is simply initialized\r
+ if (! boxes.empty())\r
+ {\r
+ envelope_range_of_boxes::apply(boxes, mbr);\r
+ }\r
+ else\r
+ {\r
+ initialize<Box, 0, dimension<Box>::value>::apply(mbr);\r
+ }\r
+\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>\r
+#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/indexed.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+template <typename T>\r
+class longitude_interval\r
+{\r
+ typedef T const& reference_type;\r
+\r
+public:\r
+ typedef T value_type;\r
+ typedef T difference_type;\r
+\r
+ longitude_interval(T const& left, T const& right)\r
+ {\r
+ m_end[0] = left;\r
+ m_end[1] = right; \r
+ }\r
+\r
+ template <std::size_t Index>\r
+ reference_type get() const\r
+ {\r
+ return m_end[Index];\r
+ }\r
+\r
+ difference_type length() const\r
+ {\r
+ return get<1>() - get<0>();\r
+ }\r
+\r
+private:\r
+ T m_end[2];\r
+};\r
+\r
+\r
+template <typename Units>\r
+struct envelope_range_of_longitudes\r
+{\r
+ template <std::size_t Index>\r
+ struct longitude_less\r
+ {\r
+ template <typename Interval>\r
+ inline bool operator()(Interval const& i1, Interval const& i2) const\r
+ {\r
+ return math::smaller(i1.template get<Index>(),\r
+ i2.template get<Index>());\r
+ }\r
+ };\r
+\r
+ template <typename RangeOfLongitudeIntervals, typename Longitude>\r
+ static inline void apply(RangeOfLongitudeIntervals const& range,\r
+ Longitude& lon_min, Longitude& lon_max)\r
+ {\r
+ typedef typename math::detail::constants_on_spheroid\r
+ <\r
+ Longitude, Units\r
+ > constants;\r
+\r
+ Longitude const zero = 0;\r
+ Longitude const period = constants::period();\r
+\r
+ lon_min = lon_max = zero;\r
+\r
+ // the range of longitude intervals can be empty if all input boxes\r
+ // degenerate to the north or south pole (or combination of the two)\r
+ // in this case the initialization values for lon_min and\r
+ // lon_max are valid choices\r
+ if (! boost::empty(range))\r
+ {\r
+ lon_min = std::min_element(boost::begin(range),\r
+ boost::end(range),\r
+ longitude_less<0>())->template get<0>();\r
+ lon_max = std::max_element(boost::begin(range),\r
+ boost::end(range),\r
+ longitude_less<1>())->template get<1>();\r
+\r
+ if (math::larger(lon_max - lon_min, constants::half_period()))\r
+ {\r
+ Longitude max_gap_left, max_gap_right;\r
+ Longitude max_gap = geometry::maximum_gap(range,\r
+ max_gap_left,\r
+ max_gap_right);\r
+\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max));\r
+ BOOST_GEOMETRY_ASSERT\r
+ (! math::larger(lon_max, constants::max_longitude()));\r
+ BOOST_GEOMETRY_ASSERT\r
+ (! math::smaller(lon_min, constants::min_longitude()));\r
+\r
+ BOOST_GEOMETRY_ASSERT\r
+ (! math::larger(max_gap_left, max_gap_right));\r
+ BOOST_GEOMETRY_ASSERT\r
+ (! math::larger(max_gap_right, constants::max_longitude()));\r
+ BOOST_GEOMETRY_ASSERT\r
+ (! math::smaller(max_gap_left, constants::min_longitude()));\r
+\r
+ if (math::larger(max_gap, zero))\r
+ {\r
+ Longitude wrapped_gap = period + lon_min - lon_max;\r
+ if (math::larger(max_gap, wrapped_gap))\r
+ {\r
+ lon_min = max_gap_right;\r
+ lon_max = max_gap_left + period;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct envelope_range_of_boxes_by_expansion\r
+{\r
+ template <typename RangeOfBoxes, typename Box>\r
+ static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)\r
+ {\r
+ typedef typename boost::range_value<RangeOfBoxes>::type box_type;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ RangeOfBoxes const\r
+ >::type iterator_type;\r
+\r
+ // first initialize MBR\r
+ detail::indexed_point_view<Box, min_corner> mbr_min(mbr);\r
+ detail::indexed_point_view<Box, max_corner> mbr_max(mbr);\r
+\r
+ detail::indexed_point_view<box_type const, min_corner>\r
+ first_box_min(range::front(range_of_boxes));\r
+\r
+ detail::indexed_point_view<box_type const, max_corner>\r
+ first_box_max(range::front(range_of_boxes));\r
+\r
+ detail::conversion::point_to_point\r
+ <\r
+ detail::indexed_point_view<box_type const, min_corner>,\r
+ detail::indexed_point_view<Box, min_corner>,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(first_box_min, mbr_min);\r
+\r
+ detail::conversion::point_to_point\r
+ <\r
+ detail::indexed_point_view<box_type const, max_corner>,\r
+ detail::indexed_point_view<Box, max_corner>,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(first_box_max, mbr_max);\r
+\r
+ // now expand using the remaining boxes\r
+ iterator_type it = boost::begin(range_of_boxes);\r
+ for (++it; it != boost::end(range_of_boxes); ++it)\r
+ {\r
+ detail::expand::indexed_loop\r
+ <\r
+ strategy::compare::default_strategy,\r
+ strategy::compare::default_strategy,\r
+ min_corner,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(mbr, *it);\r
+\r
+ detail::expand::indexed_loop\r
+ <\r
+ strategy::compare::default_strategy,\r
+ strategy::compare::default_strategy,\r
+ max_corner,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(mbr, *it);\r
+ }\r
+ }\r
+\r
+};\r
+\r
+\r
+struct envelope_range_of_boxes\r
+{\r
+ template <std::size_t Index>\r
+ struct latitude_less\r
+ {\r
+ template <typename Box>\r
+ inline bool operator()(Box const& box1, Box const& box2) const\r
+ {\r
+ return math::smaller(geometry::get<Index, 1>(box1),\r
+ geometry::get<Index, 1>(box2));\r
+ }\r
+ };\r
+\r
+ template <typename RangeOfBoxes, typename Box>\r
+ static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)\r
+ {\r
+ // boxes in the range are assumed to be normalized already\r
+\r
+ typedef typename boost::range_value<RangeOfBoxes>::type box_type;\r
+ typedef typename coordinate_type<box_type>::type coordinate_type;\r
+ typedef typename coordinate_system<box_type>::type::units units_type;\r
+ typedef typename boost::range_iterator\r
+ <\r
+ RangeOfBoxes const\r
+ >::type iterator_type;\r
+\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ coordinate_type, units_type\r
+ > constants;\r
+\r
+ typedef longitude_interval<coordinate_type> interval_type;\r
+ typedef std::vector<interval_type> interval_range_type;\r
+\r
+ BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes));\r
+\r
+ iterator_type it_min = std::min_element(boost::begin(range_of_boxes),\r
+ boost::end(range_of_boxes),\r
+ latitude_less<min_corner>());\r
+ iterator_type it_max = std::max_element(boost::begin(range_of_boxes),\r
+ boost::end(range_of_boxes),\r
+ latitude_less<max_corner>());\r
+\r
+ coordinate_type const min_longitude = constants::min_longitude();\r
+ coordinate_type const max_longitude = constants::max_longitude();\r
+ coordinate_type const period = constants::period();\r
+\r
+ interval_range_type intervals;\r
+ for (iterator_type it = boost::begin(range_of_boxes);\r
+ it != boost::end(range_of_boxes);\r
+ ++it)\r
+ {\r
+ coordinate_type lat_min = geometry::get<min_corner, 1>(*it);\r
+ coordinate_type lat_max = geometry::get<max_corner, 1>(*it);\r
+ if (math::equals(lat_min, constants::max_latitude())\r
+ || math::equals(lat_max, constants::min_latitude()))\r
+ {\r
+ // if the box degenerates to the south or north pole\r
+ // just ignore it\r
+ continue;\r
+ } \r
+\r
+ coordinate_type lon_left = geometry::get<min_corner, 0>(*it);\r
+ coordinate_type lon_right = geometry::get<max_corner, 0>(*it);\r
+\r
+ if (math::larger(lon_right, max_longitude))\r
+ {\r
+ intervals.push_back(interval_type(lon_left, max_longitude));\r
+ intervals.push_back\r
+ (interval_type(min_longitude, lon_right - period));\r
+ }\r
+ else\r
+ {\r
+ intervals.push_back(interval_type(lon_left, lon_right));\r
+ }\r
+ }\r
+\r
+ coordinate_type lon_min = 0;\r
+ coordinate_type lon_max = 0;\r
+ envelope_range_of_longitudes\r
+ <\r
+ units_type\r
+ >::apply(intervals, lon_min, lon_max);\r
+\r
+ // do not convert units; conversion will be performed at a\r
+ // higher level\r
+\r
+ // assign now the min/max longitude/latitude values\r
+ detail::indexed_point_view<Box, min_corner> mbr_min(mbr);\r
+ detail::indexed_point_view<Box, max_corner> mbr_max(mbr);\r
+\r
+ geometry::set<0>(mbr_min, lon_min);\r
+ geometry::set<1>(mbr_min, geometry::get<min_corner, 1>(*it_min));\r
+ geometry::set<0>(mbr_max, lon_max);\r
+ geometry::set<1>(mbr_max, geometry::get<max_corner, 1>(*it_max));\r
+\r
+ // what remains to be done is to compute the envelope range\r
+ // for the remaining dimensions (if any)\r
+ envelope_range_of_boxes_by_expansion\r
+ <\r
+ 2, dimension<Box>::value\r
+ >::apply(range_of_boxes, mbr);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015, 2016.\r
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP\r
+\r
+#include <cstddef>\r
+#include <utility>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/geometries/helper_geometry.hpp>\r
+\r
+#include <boost/geometry/strategies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/point.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand/point.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct envelope_one_segment\r
+{\r
+ template<typename Point, typename Box>\r
+ static inline void apply(Point const& p1, Point const& p2, Box& mbr)\r
+ {\r
+ envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr);\r
+ detail::expand::point_loop\r
+ <\r
+ strategy::compare::default_strategy,\r
+ strategy::compare::default_strategy,\r
+ Dimension,\r
+ DimensionCount\r
+ >::apply(mbr, p2);\r
+ }\r
+};\r
+\r
+\r
+// Computes the MBR of a segment given by (lon1, lat1) and (lon2,\r
+// lat2), and with azimuths a1 and a2 at the two endpoints of the\r
+// segment.\r
+// It is assumed that the spherical coordinates of the segment are\r
+// normalized and in radians.\r
+// The longitudes and latitudes of the endpoints are overridden by\r
+// those of the box.\r
+class compute_mbr_of_segment\r
+{\r
+private:\r
+ // computes the azimuths of the segment with endpoints (lon1, lat1)\r
+ // and (lon2, lat2)\r
+ // radians\r
+ template <typename CalculationType>\r
+ static inline void azimuths(CalculationType const& lon1,\r
+ CalculationType const& lat1,\r
+ CalculationType const& lon2,\r
+ CalculationType const& lat2,\r
+ CalculationType& a1,\r
+ CalculationType& a2)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(lon1 <= lon2);\r
+\r
+ CalculationType dlon = lon2 - lon1;\r
+ CalculationType sin_dlon = sin(dlon);\r
+ CalculationType cos_dlon = cos(dlon);\r
+ CalculationType cos_lat1 = cos(lat1);\r
+ CalculationType cos_lat2 = cos(lat2);\r
+ CalculationType sin_lat1 = sin(lat1);\r
+ CalculationType sin_lat2 = sin(lat2);\r
+ \r
+ a1 = atan2(sin_dlon * cos_lat2,\r
+ cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon);\r
+\r
+ a2 = atan2(-sin_dlon * cos_lat1,\r
+ cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon);\r
+ a2 += math::pi<CalculationType>();\r
+ }\r
+\r
+ // degrees or radians\r
+ template <typename CalculationType>\r
+ static inline void swap(CalculationType& lon1,\r
+ CalculationType& lat1,\r
+ CalculationType& lon2,\r
+ CalculationType& lat2)\r
+ {\r
+ std::swap(lon1, lon2);\r
+ std::swap(lat1, lat2);\r
+ }\r
+\r
+ // radians\r
+ template <typename CalculationType>\r
+ static inline bool contains_pi_half(CalculationType const& a1,\r
+ CalculationType const& a2)\r
+ {\r
+ // azimuths a1 and a2 are assumed to be in radians\r
+ BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));\r
+\r
+ static CalculationType const pi_half = math::half_pi<CalculationType>();\r
+\r
+ return (a1 < a2)\r
+ ? (a1 < pi_half && pi_half < a2)\r
+ : (a1 > pi_half && pi_half > a2);\r
+ }\r
+\r
+ // radians or degrees\r
+ template <typename Units, typename CoordinateType>\r
+ static inline bool crosses_antimeridian(CoordinateType const& lon1,\r
+ CoordinateType const& lon2)\r
+ {\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ CoordinateType, Units\r
+ > constants;\r
+\r
+ return math::abs(lon1 - lon2) > constants::half_period(); // > pi\r
+ }\r
+\r
+ // radians\r
+ template <typename CalculationType>\r
+ static inline CalculationType max_latitude(CalculationType const& azimuth,\r
+ CalculationType const& latitude)\r
+ {\r
+ // azimuth and latitude are assumed to be in radians\r
+ return acos( math::abs(cos(latitude) * sin(azimuth)) );\r
+ }\r
+\r
+ // degrees or radians\r
+ template <typename Units, typename CalculationType>\r
+ static inline void compute_box_corners(CalculationType& lon1,\r
+ CalculationType& lat1,\r
+ CalculationType& lon2,\r
+ CalculationType& lat2)\r
+ {\r
+ // coordinates are assumed to be in radians\r
+ BOOST_GEOMETRY_ASSERT(lon1 <= lon2);\r
+\r
+ CalculationType lon1_rad = math::as_radian<Units>(lon1);\r
+ CalculationType lat1_rad = math::as_radian<Units>(lat1);\r
+ CalculationType lon2_rad = math::as_radian<Units>(lon2);\r
+ CalculationType lat2_rad = math::as_radian<Units>(lat2);\r
+\r
+ CalculationType a1 = 0, a2 = 0;\r
+ azimuths(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);\r
+\r
+ if (lat1 > lat2)\r
+ {\r
+ std::swap(lat1, lat2);\r
+ std::swap(lat1_rad, lat2_rad);\r
+ }\r
+\r
+ if (math::equals(a1, a2))\r
+ {\r
+ // the segment must lie on the equator or is very short\r
+ return;\r
+ }\r
+\r
+ if (contains_pi_half(a1, a2))\r
+ {\r
+ CalculationType const mid_lat = lat1 + lat2;\r
+ if (mid_lat < 0)\r
+ {\r
+ // update using min latitude\r
+ CalculationType const lat_min_rad = -max_latitude(a1, lat1_rad);\r
+ CalculationType const lat_min = math::from_radian<Units>(lat_min_rad);\r
+\r
+ if (lat1 > lat_min)\r
+ {\r
+ lat1 = lat_min;\r
+ }\r
+ }\r
+ else if (mid_lat > 0)\r
+ {\r
+ // update using max latitude\r
+ CalculationType const lat_max_rad = max_latitude(a1, lat1_rad);\r
+ CalculationType const lat_max = math::from_radian<Units>(lat_max_rad);\r
+\r
+ if (lat2 < lat_max)\r
+ {\r
+ lat2 = lat_max;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ template <typename Units, typename CalculationType>\r
+ static inline void apply(CalculationType& lon1,\r
+ CalculationType& lat1,\r
+ CalculationType& lon2,\r
+ CalculationType& lat2)\r
+ {\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ CalculationType, Units\r
+ > constants;\r
+\r
+ bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude());\r
+ bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude());\r
+\r
+ if (is_pole1 && is_pole2)\r
+ {\r
+ // both points are poles; nothing more to do:\r
+ // longitudes are already normalized to 0\r
+ // but just in case\r
+ lon1 = 0;\r
+ lon2 = 0;\r
+ }\r
+ else if (is_pole1 && !is_pole2)\r
+ {\r
+ // first point is a pole, second point is not:\r
+ // make the longitude of the first point the same as that\r
+ // of the second point\r
+ lon1 = lon2;\r
+ }\r
+ else if (!is_pole1 && is_pole2)\r
+ {\r
+ // second point is a pole, first point is not:\r
+ // make the longitude of the second point the same as that\r
+ // of the first point\r
+ lon2 = lon1;\r
+ }\r
+\r
+ if (lon1 == lon2)\r
+ {\r
+ // segment lies on a meridian\r
+ if (lat1 > lat2)\r
+ {\r
+ std::swap(lat1, lat2);\r
+ }\r
+ return;\r
+ }\r
+\r
+ BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);\r
+\r
+ if (lon1 > lon2)\r
+ {\r
+ swap(lon1, lat1, lon2, lat2);\r
+ }\r
+\r
+ if (crosses_antimeridian<Units>(lon1, lon2))\r
+ {\r
+ lon1 += constants::period();\r
+ swap(lon1, lat1, lon2, lat2);\r
+ }\r
+\r
+ compute_box_corners<Units>(lon1, lat1, lon2, lat2);\r
+ }\r
+\r
+public:\r
+ template <typename Units, typename CalculationType, typename Box>\r
+ static inline void apply(CalculationType lon1,\r
+ CalculationType lat1,\r
+ CalculationType lon2,\r
+ CalculationType lat2,\r
+ Box& mbr)\r
+ {\r
+ typedef typename coordinate_type<Box>::type box_coordinate_type;\r
+\r
+ typedef typename helper_geometry\r
+ <\r
+ Box, box_coordinate_type, Units\r
+ >::type helper_box_type;\r
+\r
+ helper_box_type radian_mbr;\r
+\r
+ apply<Units>(lon1, lat1, lon2, lat2);\r
+\r
+ geometry::set\r
+ <\r
+ min_corner, 0\r
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));\r
+\r
+ geometry::set\r
+ <\r
+ min_corner, 1\r
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));\r
+\r
+ geometry::set\r
+ <\r
+ max_corner, 0\r
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));\r
+\r
+ geometry::set\r
+ <\r
+ max_corner, 1\r
+ >(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));\r
+\r
+ transform_units(radian_mbr, mbr);\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t DimensionCount>\r
+struct envelope_segment_on_sphere\r
+{\r
+ template <typename Point, typename Box>\r
+ static inline void apply(Point const& p1, Point const& p2, Box& mbr)\r
+ {\r
+ // first compute the envelope range for the first two coordinates\r
+ Point p1_normalized = detail::return_normalized<Point>(p1);\r
+ Point p2_normalized = detail::return_normalized<Point>(p2);\r
+\r
+ typedef typename coordinate_system<Point>::type::units units_type;\r
+\r
+ compute_mbr_of_segment::template apply<units_type>(\r
+ geometry::get<0>(p1_normalized),\r
+ geometry::get<1>(p1_normalized),\r
+ geometry::get<0>(p2_normalized),\r
+ geometry::get<1>(p2_normalized),\r
+ mbr);\r
+\r
+ // now compute the envelope range for coordinates of\r
+ // dimension 2 and higher\r
+ envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr);\r
+ }\r
+\r
+ template <typename Segment, typename Box>\r
+ static inline void apply(Segment const& segment, Box& mbr)\r
+ {\r
+ typename point_type<Segment>::type p[2];\r
+ detail::assign_point_from_index<0>(segment, p[0]);\r
+ detail::assign_point_from_index<1>(segment, p[1]);\r
+ apply(p[0], p[1], mbr);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <std::size_t DimensionCount, typename CS_Tag>\r
+struct envelope_segment\r
+ : envelope_one_segment<0, DimensionCount>\r
+{};\r
+\r
+\r
+template <std::size_t DimensionCount>\r
+struct envelope_segment<DimensionCount, spherical_equatorial_tag>\r
+ : envelope_segment_on_sphere<DimensionCount>\r
+{};\r
+\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Segment, typename CS_Tag>\r
+struct envelope<Segment, segment_tag, CS_Tag>\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Segment const& segment, Box& mbr)\r
+ {\r
+ typename point_type<Segment>::type p[2];\r
+ detail::assign_point_from_index<0>(segment, p[0]);\r
+ detail::assign_point_from_index<1>(segment, p[1]);\r
+ detail::envelope::envelope_segment\r
+ <\r
+ dimension<Segment>::value, CS_Tag\r
+ >::apply(p[0], p[1], mbr);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/strategy_transform.hpp>\r
+\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+#include <boost/geometry/views/detail/two_dimensional_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/algorithms/transform.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace envelope\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename GeometryIn,\r
+ typename GeometryOut,\r
+ typename TagIn = typename tag<GeometryIn>::type,\r
+ typename TagOut = typename tag<GeometryOut>::type\r
+>\r
+struct transform_units_impl\r
+ : not_implemented<TagIn, TagOut>\r
+{};\r
+\r
+template <typename PointIn, typename PointOut>\r
+struct transform_units_impl<PointIn, PointOut, point_tag, point_tag>\r
+{\r
+ static inline void apply(PointIn const& point_in, PointOut& point_out)\r
+ {\r
+ detail::two_dimensional_view<PointIn const> view_in(point_in);\r
+ detail::two_dimensional_view<PointOut> view_out(point_out);\r
+\r
+ geometry::transform(view_in, view_out);\r
+ }\r
+};\r
+\r
+template <typename BoxIn, typename BoxOut>\r
+struct transform_units_impl<BoxIn, BoxOut, box_tag, box_tag>\r
+{\r
+ template <std::size_t Index>\r
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out)\r
+ {\r
+ typedef detail::indexed_point_view<BoxIn const, Index> view_in_type;\r
+ typedef detail::indexed_point_view<BoxOut, Index> view_out_type;\r
+\r
+ view_in_type view_in(box_in);\r
+ view_out_type view_out(box_out);\r
+\r
+ transform_units_impl\r
+ <\r
+ view_in_type, view_out_type\r
+ >::apply(view_in, view_out);\r
+ }\r
+\r
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out)\r
+ {\r
+ apply<min_corner>(box_in, box_out);\r
+ apply<max_corner>(box_in, box_out);\r
+ }\r
+};\r
+\r
+\r
+// Short utility to transform the units of the first two coordinates of\r
+// geometry_in to the units of geometry_out\r
+template <typename GeometryIn, typename GeometryOut>\r
+inline void transform_units(GeometryIn const& geometry_in,\r
+ GeometryOut& geometry_out)\r
+{\r
+ transform_units_impl\r
+ <\r
+ GeometryIn, GeometryOut\r
+ >::apply(geometry_in, geometry_out);\r
+}\r
+\r
+\r
+}} // namespace detail::envelope\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost:geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP\r
+\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/formulas/spherical.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Since these vectors (though ray would be a better name) are used in the\r
+// implementation of equals() for Areal geometries the internal representation\r
+// should be consistent with the default side strategy for CS because currently\r
+// it's used in other relops.\r
+\r
+template <\r
+ typename T,\r
+ typename Geometry,\r
+ typename CSTag = typename cs_tag<Geometry>::type\r
+>\r
+struct collected_vector\r
+{\r
+ typedef T type;\r
+ \r
+ inline collected_vector()\r
+ {}\r
+\r
+ inline collected_vector(T const& px, T const& py,\r
+ T const& pdx, T const& pdy)\r
+ : x(px)\r
+ , y(py)\r
+ , dx(pdx)\r
+ , dy(pdy)\r
+ //, dx_0(dx)\r
+ //, dy_0(dy)\r
+ {}\r
+\r
+ template <typename Point>\r
+ inline collected_vector(Point const& p1, Point const& p2)\r
+ : x(get<0>(p1))\r
+ , y(get<1>(p1))\r
+ , dx(get<0>(p2) - x)\r
+ , dy(get<1>(p2) - y)\r
+ //, dx_0(dx)\r
+ //, dy_0(dy)\r
+ {}\r
+\r
+ bool normalize()\r
+ {\r
+ T magnitude = math::sqrt(\r
+ boost::numeric_cast<T>(dx * dx + dy * dy));\r
+\r
+ // NOTE: shouldn't here math::equals() be called?\r
+ if (magnitude > 0)\r
+ {\r
+ dx /= magnitude;\r
+ dy /= magnitude;\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ // For sorting\r
+ inline bool operator<(collected_vector const& other) const\r
+ {\r
+ if (math::equals(x, other.x))\r
+ {\r
+ if (math::equals(y, other.y))\r
+ {\r
+ if (math::equals(dx, other.dx))\r
+ {\r
+ return dy < other.dy;\r
+ }\r
+ return dx < other.dx;\r
+ }\r
+ return y < other.y;\r
+ }\r
+ return x < other.x;\r
+ }\r
+\r
+ inline bool next_is_collinear(collected_vector const& other) const\r
+ {\r
+ return same_direction(other);\r
+ }\r
+\r
+ // For std::equals\r
+ inline bool operator==(collected_vector const& other) const\r
+ {\r
+ return math::equals(x, other.x)\r
+ && math::equals(y, other.y)\r
+ && same_direction(other);\r
+ }\r
+\r
+private:\r
+ inline bool same_direction(collected_vector const& other) const\r
+ {\r
+ // For high precision arithmetic, we have to be\r
+ // more relaxed then using ==\r
+ // Because 2/sqrt( (0,0)<->(2,2) ) == 1/sqrt( (0,0)<->(1,1) )\r
+ // is not always true (at least, it is not for ttmath)\r
+ return math::equals_with_epsilon(dx, other.dx)\r
+ && math::equals_with_epsilon(dy, other.dy);\r
+ }\r
+\r
+ T x, y;\r
+ T dx, dy;\r
+ //T dx_0, dy_0;\r
+};\r
+\r
+template <typename T, typename Geometry>\r
+struct collected_vector<T, Geometry, spherical_equatorial_tag>\r
+{\r
+ typedef T type;\r
+ \r
+ typedef typename coordinate_system<Geometry>::type cs_type;\r
+ typedef model::point<T, 2, cs_type> point_type;\r
+ typedef model::point<T, 3, cs::cartesian> vector_type;\r
+\r
+ collected_vector()\r
+ {}\r
+\r
+ template <typename Point>\r
+ collected_vector(Point const& p1, Point const& p2)\r
+ : origin(get<0>(p1), get<1>(p1))\r
+ {\r
+ origin = detail::return_normalized<point_type>(origin);\r
+\r
+ using namespace geometry::formula;\r
+ prev = sph_to_cart3d<vector_type>(p1);\r
+ next = sph_to_cart3d<vector_type>(p2);\r
+ direction = cross_product(prev, next);\r
+ }\r
+\r
+ bool normalize()\r
+ {\r
+ T magnitude_sqr = dot_product(direction, direction);\r
+\r
+ // NOTE: shouldn't here math::equals() be called?\r
+ if (magnitude_sqr > 0)\r
+ {\r
+ divide_value(direction, math::sqrt(magnitude_sqr));\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ bool operator<(collected_vector const& other) const\r
+ {\r
+ if (math::equals(get<0>(origin), get<0>(other.origin)))\r
+ {\r
+ if (math::equals(get<1>(origin), get<1>(other.origin)))\r
+ {\r
+ if (math::equals(get<0>(direction), get<0>(other.direction)))\r
+ {\r
+ if (math::equals(get<1>(direction), get<1>(other.direction)))\r
+ {\r
+ return get<2>(direction) < get<2>(other.direction);\r
+ }\r
+ return get<1>(direction) < get<1>(other.direction);\r
+ }\r
+ return get<0>(direction) < get<0>(other.direction);\r
+ }\r
+ return get<1>(origin) < get<1>(other.origin);\r
+ }\r
+ return get<0>(origin) < get<0>(other.origin);\r
+ }\r
+\r
+ // For consistency with side and intersection strategies used by relops\r
+ // IMPORTANT: this method should be called for previous vector\r
+ // and next vector should be passed as parameter\r
+ bool next_is_collinear(collected_vector const& other) const\r
+ {\r
+ return formula::sph_side_value(direction, other.next) == 0;\r
+ }\r
+\r
+ // For std::equals\r
+ bool operator==(collected_vector const& other) const\r
+ {\r
+ return math::equals(get<0>(origin), get<0>(other.origin))\r
+ && math::equals(get<1>(origin), get<1>(other.origin))\r
+ && is_collinear(other);\r
+ }\r
+\r
+private:\r
+ // For consistency with side and intersection strategies used by relops\r
+ bool is_collinear(collected_vector const& other) const\r
+ {\r
+ return formula::sph_side_value(direction, other.prev) == 0\r
+ && formula::sph_side_value(direction, other.next) == 0;\r
+ }\r
+ \r
+ /*bool same_direction(collected_vector const& other) const\r
+ {\r
+ return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction))\r
+ && math::equals_with_epsilon(get<1>(direction), get<1>(other.direction))\r
+ && math::equals_with_epsilon(get<2>(direction), get<2>(other.direction));\r
+ }*/\r
+\r
+ point_type origin; // used for sorting and equality check\r
+ vector_type direction; // used for sorting, only in operator<\r
+ vector_type prev; // used for collinearity check, only in operator==\r
+ vector_type next; // used for collinearity check\r
+};\r
+\r
+template <typename T, typename Geometry>\r
+struct collected_vector<T, Geometry, spherical_polar_tag>\r
+ : public collected_vector<T, Geometry, spherical_equatorial_tag>\r
+{\r
+ typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type;\r
+\r
+ collected_vector() {}\r
+\r
+ template <typename Point>\r
+ collected_vector(Point const& p1, Point const& p2)\r
+ : base_type(to_equatorial(p1), to_equatorial(p2))\r
+ {}\r
+\r
+private:\r
+ template <typename Point>\r
+ Point polar_to_equatorial(Point const& p)\r
+ {\r
+ typedef typename coordinate_type<Point>::type coord_type;\r
+\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ coord_type,\r
+ typename coordinate_system<Point>::type::units\r
+ > constants;\r
+\r
+ coord_type const pi_2 = constants::half_period() / 2;\r
+\r
+ Point res = p;\r
+ set<1>(res, pi_2 - get<1>(p));\r
+ return res;\r
+ }\r
+};\r
+\r
+// This is consistent with the currently used default geographic side\r
+// and intersection strategies. Spherical strategies are used by default.\r
+// When default strategies are changed in the future this specialization\r
+// should be changed too.\r
+template <typename T, typename Geometry>\r
+struct collected_vector<T, Geometry, geographic_tag>\r
+ : public collected_vector<T, Geometry, spherical_equatorial_tag>\r
+{\r
+ typedef collected_vector<T, Geometry, spherical_equatorial_tag> base_type;\r
+\r
+ collected_vector() {}\r
+\r
+ template <typename Point>\r
+ collected_vector(Point const& p1, Point const& p2)\r
+ : base_type(p1, p2)\r
+ {}\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace collect_vectors\r
+{\r
+\r
+\r
+template <typename Range, typename Collection>\r
+struct range_collect_vectors\r
+{\r
+ typedef typename boost::range_value<Collection>::type item_type;\r
+ typedef typename item_type::type calculation_type;\r
+\r
+ static inline void apply(Collection& collection, Range const& range)\r
+ {\r
+ if (boost::size(range) < 2)\r
+ {\r
+ return;\r
+ }\r
+\r
+ typedef typename boost::range_size<Collection>::type collection_size_t;\r
+ collection_size_t c_old_size = boost::size(collection);\r
+\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+\r
+ bool is_first = true;\r
+ iterator it = boost::begin(range);\r
+\r
+ for (iterator prev = it++;\r
+ it != boost::end(range);\r
+ prev = it++)\r
+ {\r
+ typename boost::range_value<Collection>::type v(*prev, *it);\r
+\r
+ // Normalize the vector -> this results in points+direction\r
+ // and is comparible between geometries\r
+ // Avoid non-duplicate points (AND division by zero)\r
+ if (v.normalize())\r
+ {\r
+ // Avoid non-direction changing points\r
+ if (is_first || ! collection.back().next_is_collinear(v))\r
+ {\r
+ collection.push_back(v);\r
+ }\r
+ is_first = false;\r
+ }\r
+ }\r
+\r
+ // If first one has same direction as last one, remove first one\r
+ collection_size_t collected_count = boost::size(collection) - c_old_size;\r
+ if ( collected_count > 1 )\r
+ {\r
+ typedef typename boost::range_iterator<Collection>::type c_iterator;\r
+ c_iterator first = range::pos(collection, c_old_size);\r
+\r
+ if (collection.back().next_is_collinear(*first) )\r
+ {\r
+ //collection.erase(first);\r
+ // O(1) instead of O(N)\r
+ *first = collection.back();\r
+ collection.pop_back();\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+// Default version (cartesian)\r
+template <typename Box, typename Collection, typename CSTag = typename cs_tag<Box>::type>\r
+struct box_collect_vectors\r
+{\r
+ // Calculate on coordinate type, but if it is integer,\r
+ // then use double\r
+ typedef typename boost::range_value<Collection>::type item_type;\r
+ typedef typename item_type::type calculation_type;\r
+\r
+ static inline void apply(Collection& collection, Box const& box)\r
+ {\r
+ typename point_type<Box>::type lower_left, lower_right,\r
+ upper_left, upper_right;\r
+ geometry::detail::assign_box_corners(box, lower_left, lower_right,\r
+ upper_left, upper_right);\r
+\r
+ typedef typename boost::range_value<Collection>::type item;\r
+\r
+ collection.push_back(item(get<0>(lower_left), get<1>(lower_left), 0, 1));\r
+ collection.push_back(item(get<0>(upper_left), get<1>(upper_left), 1, 0));\r
+ collection.push_back(item(get<0>(upper_right), get<1>(upper_right), 0, -1));\r
+ collection.push_back(item(get<0>(lower_right), get<1>(lower_right), -1, 0));\r
+ }\r
+};\r
+\r
+// NOTE: This is not fully correct because Box in spherical and geographic\r
+// cordinate systems cannot be seen as Polygon\r
+template <typename Box, typename Collection>\r
+struct box_collect_vectors<Box, Collection, spherical_equatorial_tag>\r
+{\r
+ static inline void apply(Collection& collection, Box const& box)\r
+ {\r
+ typename point_type<Box>::type lower_left, lower_right,\r
+ upper_left, upper_right;\r
+ geometry::detail::assign_box_corners(box, lower_left, lower_right,\r
+ upper_left, upper_right);\r
+\r
+ typedef typename boost::range_value<Collection>::type item;\r
+\r
+ collection.push_back(item(lower_left, upper_left));\r
+ collection.push_back(item(upper_left, upper_right));\r
+ collection.push_back(item(upper_right, lower_right));\r
+ collection.push_back(item(lower_right, lower_left));\r
+ }\r
+};\r
+\r
+template <typename Box, typename Collection>\r
+struct box_collect_vectors<Box, Collection, spherical_polar_tag>\r
+ : box_collect_vectors<Box, Collection, spherical_equatorial_tag>\r
+{};\r
+\r
+template <typename Box, typename Collection>\r
+struct box_collect_vectors<Box, Collection, geographic_tag>\r
+ : box_collect_vectors<Box, Collection, spherical_equatorial_tag>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Collection>\r
+struct polygon_collect_vectors\r
+{\r
+ static inline void apply(Collection& collection, Polygon const& polygon)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+\r
+ typedef range_collect_vectors<ring_type, Collection> per_range;\r
+ per_range::apply(collection, exterior_ring(polygon));\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ per_range::apply(collection, *it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiGeometry, typename Collection, typename SinglePolicy>\r
+struct multi_collect_vectors\r
+{\r
+ static inline void apply(Collection& collection, MultiGeometry const& multi)\r
+ {\r
+ for (typename boost::range_iterator<MultiGeometry const>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ SinglePolicy::apply(collection, *it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::collect_vectors\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Collection,\r
+ typename Geometry\r
+>\r
+struct collect_vectors\r
+{\r
+ static inline void apply(Collection&, Geometry const&)\r
+ {}\r
+};\r
+\r
+\r
+template <typename Collection, typename Box>\r
+struct collect_vectors<box_tag, Collection, Box>\r
+ : detail::collect_vectors::box_collect_vectors<Box, Collection>\r
+{};\r
+\r
+\r
+\r
+template <typename Collection, typename Ring>\r
+struct collect_vectors<ring_tag, Collection, Ring>\r
+ : detail::collect_vectors::range_collect_vectors<Ring, Collection>\r
+{};\r
+\r
+\r
+template <typename Collection, typename LineString>\r
+struct collect_vectors<linestring_tag, Collection, LineString>\r
+ : detail::collect_vectors::range_collect_vectors<LineString, Collection>\r
+{};\r
+\r
+\r
+template <typename Collection, typename Polygon>\r
+struct collect_vectors<polygon_tag, Collection, Polygon>\r
+ : detail::collect_vectors::polygon_collect_vectors<Polygon, Collection>\r
+{};\r
+\r
+\r
+template <typename Collection, typename MultiPolygon>\r
+struct collect_vectors<multi_polygon_tag, Collection, MultiPolygon>\r
+ : detail::collect_vectors::multi_collect_vectors\r
+ <\r
+ MultiPolygon,\r
+ Collection,\r
+ detail::collect_vectors::polygon_collect_vectors\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type,\r
+ Collection\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+ \ingroup collect_vectors\r
+ \tparam Collection Collection type, should be e.g. std::vector<>\r
+ \tparam Geometry geometry type\r
+ \param collection the collection of vectors\r
+ \param geometry the geometry to make collect_vectors\r
+*/\r
+template <typename Collection, typename Geometry>\r
+inline void collect_vectors(Collection& collection, Geometry const& geometry)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ dispatch::collect_vectors\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Collection,\r
+ Geometry\r
+ >::apply(collection, geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace equals\r
+{\r
+\r
+/*!\r
+ \brief Internal utility function to detect of points are disjoint\r
+ \note To avoid circular references\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline bool equals_point_point(Point1 const& point1, Point2 const& point2)\r
+{\r
+ return ! detail::disjoint::disjoint_point_point(point1, point2);\r
+}\r
+\r
+\r
+}} // namespace detail::equals\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand/indexed.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/expand.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace expand\r
+{\r
+\r
+\r
+struct box_on_spheroid\r
+{\r
+ template <typename BoxOut, typename BoxIn>\r
+ static inline void apply(BoxOut& box_out, BoxIn const& box_in)\r
+ {\r
+ // normalize both boxes and convert box-in to be of type of box-out\r
+ BoxOut mbrs[2];\r
+ detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]);\r
+ detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]);\r
+\r
+ // compute the envelope of the two boxes\r
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::expand\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// Box + box -> new box containing two input boxes\r
+template\r
+<\r
+ typename BoxOut, typename BoxIn,\r
+ typename StrategyLess, typename StrategyGreater,\r
+ typename CSTagOut, typename CSTag\r
+>\r
+struct expand\r
+ <\r
+ BoxOut, BoxIn,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, box_tag,\r
+ CSTagOut, CSTag\r
+ > : detail::expand::expand_indexed\r
+ <\r
+ 0, dimension<BoxIn>::value, StrategyLess, StrategyGreater\r
+ >\r
+{\r
+ BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),\r
+ COORDINATE_SYSTEMS_MUST_BE_THE_SAME,\r
+ (types<CSTagOut, CSTag>()));\r
+};\r
+\r
+template\r
+<\r
+ typename BoxOut, typename BoxIn,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+struct expand\r
+ <\r
+ BoxOut, BoxIn,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, box_tag,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ > : detail::expand::box_on_spheroid\r
+{};\r
+\r
+template\r
+<\r
+ typename BoxOut, typename BoxIn,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+struct expand\r
+ <\r
+ BoxOut, BoxIn,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, box_tag,\r
+ geographic_tag, geographic_tag\r
+ > : detail::expand::box_on_spheroid\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/expand/point.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/segment.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/box.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+#include <boost/geometry/strategies/compare.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/expand.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace expand\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename StrategyLess, typename StrategyGreater,\r
+ std::size_t Index,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct indexed_loop\r
+{\r
+ template <typename Box, typename Geometry>\r
+ static inline void apply(Box& box, Geometry const& source)\r
+ {\r
+ typedef typename strategy::compare::detail::select_strategy\r
+ <\r
+ StrategyLess, 1, Box, Dimension\r
+ >::type less_type;\r
+\r
+ typedef typename strategy::compare::detail::select_strategy\r
+ <\r
+ StrategyGreater, -1, Box, Dimension\r
+ >::type greater_type;\r
+\r
+ typedef typename select_coordinate_type\r
+ <\r
+ Box,\r
+ Geometry\r
+ >::type coordinate_type;\r
+\r
+ less_type less;\r
+ greater_type greater;\r
+\r
+ coordinate_type const coord = get<Index, Dimension>(source);\r
+\r
+ if (less(coord, get<min_corner, Dimension>(box)))\r
+ {\r
+ set<min_corner, Dimension>(box, coord);\r
+ }\r
+\r
+ if (greater(coord, get<max_corner, Dimension>(box)))\r
+ {\r
+ set<max_corner, Dimension>(box, coord);\r
+ }\r
+\r
+ indexed_loop\r
+ <\r
+ StrategyLess, StrategyGreater,\r
+ Index, Dimension + 1, DimensionCount\r
+ >::apply(box, source);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename StrategyLess, typename StrategyGreater,\r
+ std::size_t Index, std::size_t DimensionCount\r
+>\r
+struct indexed_loop\r
+ <\r
+ StrategyLess, StrategyGreater,\r
+ Index, DimensionCount, DimensionCount\r
+ >\r
+{\r
+ template <typename Box, typename Geometry>\r
+ static inline void apply(Box&, Geometry const&) {}\r
+};\r
+\r
+\r
+\r
+// Changes a box such that the other box is also contained by the box\r
+template\r
+<\r
+ std::size_t Dimension, std::size_t DimensionCount,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+struct expand_indexed\r
+{\r
+ template <typename Box, typename Geometry>\r
+ static inline void apply(Box& box, Geometry const& geometry)\r
+ {\r
+ indexed_loop\r
+ <\r
+ StrategyLess, StrategyGreater,\r
+ 0, Dimension, DimensionCount\r
+ >::apply(box, geometry);\r
+\r
+ indexed_loop\r
+ <\r
+ StrategyLess, StrategyGreater,\r
+ 1, Dimension, DimensionCount\r
+ >::apply(box, geometry);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::expand\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/expand.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+ \r
+template <typename Geometry>\r
+struct expand\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Box& box, Geometry const& geometry)\r
+ {\r
+ concepts::check<Box>();\r
+ concepts::check<Geometry const>();\r
+ concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();\r
+ \r
+ dispatch::expand<Box, Geometry>::apply(box, geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Box>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ Box& m_box;\r
+ \r
+ visitor(Box& box) : m_box(box) {}\r
+ \r
+ template <typename Geometry>\r
+ void operator()(Geometry const& geometry) const\r
+ {\r
+ return expand<Geometry>::apply(m_box, geometry);\r
+ }\r
+ };\r
+ \r
+ template <class Box>\r
+ static inline void\r
+ apply(Box& box,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor<Box>(box), geometry);\r
+ }\r
+};\r
+ \r
+} // namespace resolve_variant\r
+ \r
+ \r
+/***\r
+*!\r
+\brief Expands a box using the extend (envelope) of another geometry (box, point)\r
+\ingroup expand\r
+\tparam Box type of the box\r
+\tparam Geometry of second geometry, to be expanded with the box\r
+\param box box to expand another geometry with, might be changed\r
+\param geometry other geometry\r
+\param strategy_less\r
+\param strategy_greater\r
+\note Strategy is currently ignored\r
+ *\r
+template\r
+<\r
+ typename Box, typename Geometry,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+inline void expand(Box& box, Geometry const& geometry,\r
+ StrategyLess const& strategy_less,\r
+ StrategyGreater const& strategy_greater)\r
+{\r
+ concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();\r
+\r
+ dispatch::expand<Box, Geometry>::apply(box, geometry);\r
+}\r
+***/\r
+\r
+\r
+/*!\r
+\brief Expands a box using the bounding box (envelope) of another geometry (box, point)\r
+\ingroup expand\r
+\tparam Box type of the box\r
+\tparam Geometry \tparam_geometry\r
+\param box box to be expanded using another geometry, mutable\r
+\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box\r
+\r
+\qbk{[include reference/algorithms/expand.qbk]}\r
+ */\r
+template <typename Box, typename Geometry>\r
+inline void expand(Box& box, Geometry const& geometry)\r
+{\r
+ resolve_variant::expand<Geometry>::apply(box, geometry);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+#include <boost/geometry/strategies/compare.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/normalize.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/expand.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace expand\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename StrategyLess, typename StrategyGreater,\r
+ std::size_t Dimension, std::size_t DimensionCount\r
+>\r
+struct point_loop\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box& box, Point const& source)\r
+ {\r
+ typedef typename strategy::compare::detail::select_strategy\r
+ <\r
+ StrategyLess, 1, Point, Dimension\r
+ >::type less_type;\r
+\r
+ typedef typename strategy::compare::detail::select_strategy\r
+ <\r
+ StrategyGreater, -1, Point, Dimension\r
+ >::type greater_type;\r
+\r
+ typedef typename select_coordinate_type\r
+ <\r
+ Point, Box\r
+ >::type coordinate_type;\r
+\r
+ less_type less;\r
+ greater_type greater;\r
+\r
+ coordinate_type const coord = get<Dimension>(source);\r
+\r
+ if (less(coord, get<min_corner, Dimension>(box)))\r
+ {\r
+ set<min_corner, Dimension>(box, coord);\r
+ }\r
+\r
+ if (greater(coord, get<max_corner, Dimension>(box)))\r
+ {\r
+ set<max_corner, Dimension>(box, coord);\r
+ }\r
+\r
+ point_loop\r
+ <\r
+ StrategyLess, StrategyGreater, Dimension + 1, DimensionCount\r
+ >::apply(box, source);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount\r
+>\r
+struct point_loop\r
+ <\r
+ StrategyLess, StrategyGreater, DimensionCount, DimensionCount\r
+ >\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box&, Point const&) {}\r
+};\r
+\r
+\r
+// implementation for the spherical equatorial and geographic coordinate systems\r
+template\r
+<\r
+ typename StrategyLess,\r
+ typename StrategyGreater,\r
+ std::size_t DimensionCount\r
+>\r
+struct point_loop_on_spheroid\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box& box, Point const& point)\r
+ {\r
+ typedef typename point_type<Box>::type box_point_type;\r
+ typedef typename coordinate_type<Box>::type box_coordinate_type;\r
+\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ box_coordinate_type,\r
+ typename coordinate_system<Box>::type::units\r
+ > constants;\r
+\r
+ // normalize input point and input box\r
+ Point p_normalized = detail::return_normalized<Point>(point);\r
+ detail::normalize(box, box);\r
+\r
+ // transform input point to be of the same type as the box point\r
+ box_point_type box_point;\r
+ detail::envelope::transform_units(p_normalized, box_point);\r
+\r
+ box_coordinate_type p_lon = geometry::get<0>(box_point);\r
+ box_coordinate_type p_lat = geometry::get<1>(box_point);\r
+\r
+ typename coordinate_type<Box>::type\r
+ b_lon_min = geometry::get<min_corner, 0>(box),\r
+ b_lat_min = geometry::get<min_corner, 1>(box),\r
+ b_lon_max = geometry::get<max_corner, 0>(box),\r
+ b_lat_max = geometry::get<max_corner, 1>(box);\r
+\r
+ if (math::equals(math::abs(p_lat), constants::max_latitude()))\r
+ {\r
+ // the point of expansion is the either the north or the\r
+ // south pole; the only important coordinate here is the\r
+ // pole's latitude, as the longitude can be anything;\r
+ // we, thus, take into account the point's latitude only and return\r
+ geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));\r
+ geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));\r
+ return;\r
+ }\r
+\r
+ if (math::equals(b_lat_min, b_lat_max)\r
+ && math::equals(math::abs(b_lat_min), constants::max_latitude()))\r
+ {\r
+ // the box degenerates to either the north or the south pole;\r
+ // the only important coordinate here is the pole's latitude, \r
+ // as the longitude can be anything;\r
+ // we thus take into account the box's latitude only and return\r
+ geometry::set<min_corner, 0>(box, p_lon);\r
+ geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));\r
+ geometry::set<max_corner, 0>(box, p_lon);\r
+ geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));\r
+ return;\r
+ }\r
+\r
+ // update latitudes\r
+ b_lat_min = (std::min)(b_lat_min, p_lat);\r
+ b_lat_max = (std::max)(b_lat_max, p_lat);\r
+\r
+ // update longitudes\r
+ if (math::smaller(p_lon, b_lon_min))\r
+ {\r
+ box_coordinate_type p_lon_shifted = p_lon + constants::period();\r
+\r
+ if (math::larger(p_lon_shifted, b_lon_max))\r
+ {\r
+ // here we could check using: ! math::larger(.., ..)\r
+ if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))\r
+ {\r
+ b_lon_min = p_lon;\r
+ }\r
+ else\r
+ {\r
+ b_lon_max = p_lon_shifted;\r
+ }\r
+ }\r
+ }\r
+ else if (math::larger(p_lon, b_lon_max))\r
+ {\r
+ // in this case, and since p_lon is normalized in the range\r
+ // (-180, 180], we must have that b_lon_max <= 180\r
+ if (b_lon_min < 0\r
+ && math::larger(p_lon - b_lon_max,\r
+ constants::period() - p_lon + b_lon_min))\r
+ {\r
+ b_lon_min = p_lon;\r
+ b_lon_max += constants::period();\r
+ }\r
+ else\r
+ {\r
+ b_lon_max = p_lon;\r
+ }\r
+ }\r
+\r
+ geometry::set<min_corner, 0>(box, b_lon_min);\r
+ geometry::set<min_corner, 1>(box, b_lat_min);\r
+ geometry::set<max_corner, 0>(box, b_lon_max);\r
+ geometry::set<max_corner, 1>(box, b_lat_max);\r
+\r
+ point_loop\r
+ <\r
+ StrategyLess, StrategyGreater, 2, DimensionCount\r
+ >::apply(box, point);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::expand\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// Box + point -> new box containing also point\r
+template\r
+<\r
+ typename BoxOut, typename Point,\r
+ typename StrategyLess, typename StrategyGreater,\r
+ typename CSTagOut, typename CSTag\r
+>\r
+struct expand\r
+ <\r
+ BoxOut, Point,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, point_tag,\r
+ CSTagOut, CSTag\r
+ > : detail::expand::point_loop\r
+ <\r
+ StrategyLess, StrategyGreater, 0, dimension<Point>::value\r
+ >\r
+{\r
+ BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),\r
+ COORDINATE_SYSTEMS_MUST_BE_THE_SAME,\r
+ (types<CSTagOut, CSTag>()));\r
+};\r
+\r
+template\r
+<\r
+ typename BoxOut, typename Point,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+struct expand\r
+ <\r
+ BoxOut, Point,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, point_tag,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ > : detail::expand::point_loop_on_spheroid\r
+ <\r
+ StrategyLess, StrategyGreater, dimension<Point>::value\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename BoxOut, typename Point,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+struct expand\r
+ <\r
+ BoxOut, Point,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, point_tag,\r
+ geographic_tag, geographic_tag\r
+ > : detail::expand::point_loop_on_spheroid\r
+ <\r
+ StrategyLess, StrategyGreater, dimension<Point>::value\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/box.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/segment.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand/indexed.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/expand.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace expand\r
+{\r
+\r
+\r
+struct segment_on_sphere\r
+{\r
+ template <typename Box, typename Segment>\r
+ static inline void apply(Box& box, Segment const& segment)\r
+ {\r
+ Box mbrs[2];\r
+\r
+ // compute the envelope of the segment\r
+ detail::envelope::envelope_segment_on_sphere\r
+ <\r
+ dimension<Segment>::value\r
+ >::apply(segment, mbrs[0]);\r
+\r
+ // normalize the box\r
+ detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]);\r
+\r
+ // compute the envelope of the two boxes\r
+ detail::envelope::envelope_range_of_boxes::apply(mbrs, box);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::expand\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Box, typename Segment,\r
+ typename StrategyLess, typename StrategyGreater,\r
+ typename CSTagOut, typename CSTag\r
+>\r
+struct expand\r
+ <\r
+ Box, Segment,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, segment_tag,\r
+ CSTagOut, CSTag\r
+ > : detail::expand::expand_indexed\r
+ <\r
+ 0, dimension<Segment>::value, StrategyLess, StrategyGreater\r
+ >\r
+{\r
+ BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),\r
+ COORDINATE_SYSTEMS_MUST_BE_THE_SAME,\r
+ (types<CSTagOut, CSTag>()));\r
+};\r
+\r
+template\r
+<\r
+ typename Box, typename Segment,\r
+ typename StrategyLess, typename StrategyGreater\r
+>\r
+struct expand\r
+ <\r
+ Box, Segment,\r
+ StrategyLess, StrategyGreater,\r
+ box_tag, segment_tag,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ > : detail::expand::segment_on_sphere\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace expand\r
+{\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template <typename> class PlusOrMinus,\r
+ std::size_t I = 0,\r
+ std::size_t D = dimension<Point>::value,\r
+ bool Enable = boost::is_floating_point\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >::value\r
+>\r
+struct corner_by_epsilon\r
+{\r
+ static inline void apply(Point & point)\r
+ {\r
+ typedef typename coordinate_type<Point>::type coord_type;\r
+ coord_type const coord = get<I>(point);\r
+ coord_type const eps = math::scaled_epsilon(coord);\r
+ \r
+ set<I>(point, PlusOrMinus<coord_type>()(coord, eps));\r
+\r
+ corner_by_epsilon<Point, PlusOrMinus, I+1>::apply(point);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template <typename> class PlusOrMinus,\r
+ std::size_t I,\r
+ std::size_t D\r
+>\r
+struct corner_by_epsilon<Point, PlusOrMinus, I, D, false>\r
+{\r
+ static inline void apply(Point const&) {}\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template <typename> class PlusOrMinus,\r
+ std::size_t D,\r
+ bool Enable\r
+>\r
+struct corner_by_epsilon<Point, PlusOrMinus, D, D, Enable>\r
+{\r
+ static inline void apply(Point const&) {}\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template <typename> class PlusOrMinus,\r
+ std::size_t D\r
+>\r
+struct corner_by_epsilon<Point, PlusOrMinus, D, D, false>\r
+{\r
+ static inline void apply(Point const&) {}\r
+};\r
+\r
+} // namespace expand\r
+\r
+template <typename Box>\r
+inline void expand_by_epsilon(Box & box)\r
+{\r
+ typedef detail::indexed_point_view<Box, min_corner> min_type;\r
+ min_type min_point(box);\r
+ expand::corner_by_epsilon<min_type, std::minus>::apply(min_point);\r
+\r
+ typedef detail::indexed_point_view<Box, max_corner> max_type;\r
+ max_type max_point(box);\r
+ expand::corner_by_epsilon<max_type, std::plus>::apply(max_point);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace extreme_points\r
+{\r
+\r
+template <std::size_t Dimension>\r
+struct compare\r
+{\r
+ template <typename Point>\r
+ inline bool operator()(Point const& lhs, Point const& rhs)\r
+ {\r
+ return geometry::get<Dimension>(lhs) < geometry::get<Dimension>(rhs);\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t Dimension, typename PointType, typename CoordinateType>\r
+inline void move_along_vector(PointType& point, PointType const& extreme, CoordinateType const& base_value)\r
+{\r
+ // Moves a point along the vector (point, extreme) in the direction of the extreme point\r
+ // This adapts the possibly uneven legs of the triangle (or trapezium-like shape)\r
+ // _____extreme _____\r
+ // / \ / \ .\r
+ // /base \ => / \ point .\r
+ // \ point .\r
+ //\r
+ // For so-called intruders, it can be used to adapt both legs to the level of "base"\r
+ // For the base, it can be used to adapt both legs to the level of the max-value of the intruders\r
+ // If there are 2 or more extreme values, use the one close to 'point' to have a correct vector\r
+\r
+ CoordinateType const value = geometry::get<Dimension>(point);\r
+ //if (geometry::math::equals(value, base_value))\r
+ if (value >= base_value)\r
+ {\r
+ return;\r
+ }\r
+\r
+ PointType vector = point;\r
+ subtract_point(vector, extreme);\r
+\r
+ CoordinateType const diff = geometry::get<Dimension>(vector);\r
+\r
+ // diff should never be zero\r
+ // because of the way our triangle/trapezium is build.\r
+ // We just return if it would be the case.\r
+ if (geometry::math::equals(diff, 0))\r
+ {\r
+ return;\r
+ }\r
+\r
+ CoordinateType const base_diff = base_value - geometry::get<Dimension>(extreme);\r
+\r
+ multiply_value(vector, base_diff);\r
+ divide_value(vector, diff);\r
+\r
+ // The real move:\r
+ point = extreme;\r
+ add_point(point, vector);\r
+}\r
+\r
+\r
+template <std::size_t Dimension, typename Range, typename CoordinateType>\r
+inline void move_along_vector(Range& range, CoordinateType const& base_value)\r
+{\r
+ if (range.size() >= 3)\r
+ {\r
+ move_along_vector<Dimension>(range.front(), *(range.begin() + 1), base_value);\r
+ move_along_vector<Dimension>(range.back(), *(range.rbegin() + 1), base_value);\r
+ }\r
+}\r
+\r
+\r
+template<typename Ring, std::size_t Dimension>\r
+struct extreme_points_on_ring\r
+{\r
+\r
+ typedef typename geometry::coordinate_type<Ring>::type coordinate_type;\r
+ typedef typename boost::range_iterator<Ring const>::type range_iterator;\r
+ typedef typename geometry::point_type<Ring>::type point_type;\r
+\r
+ typedef typename geometry::strategy::side::services::default_strategy\r
+ <\r
+ typename geometry::cs_tag<point_type>::type\r
+ >::type side_strategy;\r
+\r
+\r
+ template <typename CirclingIterator, typename Points>\r
+ static inline bool extend(CirclingIterator& it,\r
+ std::size_t n,\r
+ coordinate_type max_coordinate_value,\r
+ Points& points, int direction)\r
+ {\r
+ std::size_t safe_index = 0;\r
+ do\r
+ {\r
+ it += direction;\r
+\r
+ points.push_back(*it);\r
+\r
+ if (safe_index++ >= n)\r
+ {\r
+ // E.g.: ring is completely horizontal or vertical (= invalid, but we don't want to have an infinite loop)\r
+ return false;\r
+ }\r
+ } while (geometry::math::equals(geometry::get<Dimension>(*it), max_coordinate_value));\r
+\r
+ return true;\r
+ }\r
+\r
+ // Overload without adding to poinst\r
+ template <typename CirclingIterator>\r
+ static inline bool extend(CirclingIterator& it,\r
+ std::size_t n,\r
+ coordinate_type max_coordinate_value,\r
+ int direction)\r
+ {\r
+ std::size_t safe_index = 0;\r
+ do\r
+ {\r
+ it += direction;\r
+\r
+ if (safe_index++ >= n)\r
+ {\r
+ // E.g.: ring is completely horizontal or vertical (= invalid, but we don't want to have an infinite loop)\r
+ return false;\r
+ }\r
+ } while (geometry::math::equals(geometry::get<Dimension>(*it), max_coordinate_value));\r
+\r
+ return true;\r
+ }\r
+\r
+ template <typename CirclingIterator>\r
+ static inline bool extent_both_sides(Ring const& ring,\r
+ point_type extreme,\r
+ CirclingIterator& left,\r
+ CirclingIterator& right)\r
+ {\r
+ std::size_t const n = boost::size(ring);\r
+ coordinate_type const max_coordinate_value = geometry::get<Dimension>(extreme);\r
+\r
+ if (! extend(left, n, max_coordinate_value, -1))\r
+ {\r
+ return false;\r
+ }\r
+ if (! extend(right, n, max_coordinate_value, +1))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ template <typename Collection, typename CirclingIterator>\r
+ static inline bool collect(Ring const& ring,\r
+ point_type extreme,\r
+ Collection& points,\r
+ CirclingIterator& left,\r
+ CirclingIterator& right)\r
+ {\r
+ std::size_t const n = boost::size(ring);\r
+ coordinate_type const max_coordinate_value = geometry::get<Dimension>(extreme);\r
+\r
+ // Collects first left, which is reversed (if more than one point) then adds the top itself, then right\r
+ if (! extend(left, n, max_coordinate_value, points, -1))\r
+ {\r
+ return false;\r
+ }\r
+ std::reverse(points.begin(), points.end());\r
+ points.push_back(extreme);\r
+ if (! extend(right, n, max_coordinate_value, points, +1))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ template <typename Extremes, typename Intruders, typename CirclingIterator>\r
+ static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right,\r
+ Extremes const& extremes,\r
+ Intruders& intruders)\r
+ {\r
+ if (boost::size(extremes) < 3)\r
+ {\r
+ return;\r
+ }\r
+ coordinate_type const min_value = geometry::get<Dimension>(*std::min_element(boost::begin(extremes), boost::end(extremes), compare<Dimension>()));\r
+\r
+ // Also select left/right (if Dimension=1)\r
+ coordinate_type const other_min = geometry::get<1 - Dimension>(*std::min_element(boost::begin(extremes), boost::end(extremes), compare<1 - Dimension>()));\r
+ coordinate_type const other_max = geometry::get<1 - Dimension>(*std::max_element(boost::begin(extremes), boost::end(extremes), compare<1 - Dimension>()));\r
+\r
+ std::size_t defensive_check_index = 0; // in case we skip over left/right check, collect modifies right too\r
+ std::size_t const n = boost::size(ring);\r
+ while (left != right && defensive_check_index < n)\r
+ {\r
+ coordinate_type const coordinate = geometry::get<Dimension>(*right);\r
+ coordinate_type const other_coordinate = geometry::get<1 - Dimension>(*right);\r
+ if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max)\r
+ {\r
+ int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;\r
+ int const first_side = side_strategy::apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;\r
+ int const last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;\r
+\r
+ // If not lying left from any of the extemes side\r
+ if (first_side != 1 && last_side != 1)\r
+ {\r
+ //std::cout << "first " << first_side << " last " << last_side << std::endl;\r
+\r
+ // we start at this intrusion until it is handled, and don't affect our initial left iterator\r
+ CirclingIterator left_intrusion_it = right;\r
+ typename boost::range_value<Intruders>::type intruder;\r
+ collect(ring, *right, intruder, left_intrusion_it, right);\r
+\r
+ // Also moves these to base-level, makes sorting possible which can be done in case of self-tangencies\r
+ // (we might postpone this action, it is often not necessary. However it is not time-consuming)\r
+ move_along_vector<Dimension>(intruder, min_value);\r
+ intruders.push_back(intruder);\r
+ --right;\r
+ }\r
+ }\r
+ ++right;\r
+ defensive_check_index++;\r
+ }\r
+ }\r
+\r
+ template <typename Extremes, typename Intruders>\r
+ static inline void get_intruders(Ring const& ring,\r
+ Extremes const& extremes,\r
+ Intruders& intruders)\r
+ {\r
+ std::size_t const n = boost::size(ring);\r
+ if (n >= 3)\r
+ {\r
+ geometry::ever_circling_range_iterator<Ring const> left(ring);\r
+ geometry::ever_circling_range_iterator<Ring const> right(ring);\r
+ ++right;\r
+\r
+ get_intruders(ring, left, right, extremes, intruders);\r
+ }\r
+ }\r
+\r
+ template <typename Iterator>\r
+ static inline bool right_turn(Ring const& ring, Iterator it)\r
+ {\r
+ typename std::iterator_traits<Iterator>::difference_type const index\r
+ = std::distance(boost::begin(ring), it);\r
+ geometry::ever_circling_range_iterator<Ring const> left(ring);\r
+ geometry::ever_circling_range_iterator<Ring const> right(ring);\r
+ left += index;\r
+ right += index;\r
+\r
+ if (! extent_both_sides(ring, *it, left, right))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;\r
+ int const first_side = side_strategy::apply(*(right - 1), *right, *left) * factor;\r
+ int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor;\r
+\r
+//std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl;\r
+\r
+ // Turn should not be left (actually, it should be right because extent removes horizontal/collinear cases)\r
+ return first_side != 1 && last_side != 1;\r
+ }\r
+\r
+\r
+ // Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring\r
+ template <typename Extremes, typename Intruders>\r
+ static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders)\r
+ {\r
+ std::size_t const n = boost::size(ring);\r
+ if (n < 3)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Get all maxima, usually one. In case of self-tangencies, or self-crossings,\r
+ // the max might be is not valid. A valid max should make a right turn\r
+ range_iterator max_it = boost::begin(ring);\r
+ compare<Dimension> smaller;\r
+ for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)\r
+ {\r
+ if (smaller(*max_it, *it) && right_turn(ring, it))\r
+ {\r
+ max_it = it;\r
+ }\r
+ }\r
+\r
+ if (max_it == boost::end(ring))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ typename std::iterator_traits<range_iterator>::difference_type const\r
+ index = std::distance(boost::begin(ring), max_it);\r
+//std::cout << "Extreme point lies at " << index << " having " << geometry::wkt(*max_it) << std::endl;\r
+\r
+ geometry::ever_circling_range_iterator<Ring const> left(ring);\r
+ geometry::ever_circling_range_iterator<Ring const> right(ring);\r
+ left += index;\r
+ right += index;\r
+\r
+ // Collect all points (often 3) in a temporary vector\r
+ std::vector<point_type> points;\r
+ points.reserve(3);\r
+ if (! collect(ring, *max_it, points, left, right))\r
+ {\r
+ return false;\r
+ }\r
+\r
+//std::cout << "Built vector of " << points.size() << std::endl;\r
+\r
+ coordinate_type const front_value = geometry::get<Dimension>(points.front());\r
+ coordinate_type const back_value = geometry::get<Dimension>(points.back());\r
+ coordinate_type const base_value = (std::max)(front_value, back_value);\r
+ if (front_value < back_value)\r
+ {\r
+ move_along_vector<Dimension>(points.front(), *(points.begin() + 1), base_value);\r
+ }\r
+ else\r
+ {\r
+ move_along_vector<Dimension>(points.back(), *(points.rbegin() + 1), base_value);\r
+ }\r
+\r
+ std::copy(points.begin(), points.end(), std::back_inserter(extremes));\r
+\r
+ get_intruders(ring, left, right, extremes, intruders);\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+\r
+}} // namespace detail::extreme_points\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ std::size_t Dimension,\r
+ typename GeometryTag = typename tag<Geometry>::type\r
+>\r
+struct extreme_points\r
+{};\r
+\r
+\r
+template<typename Ring, std::size_t Dimension>\r
+struct extreme_points<Ring, Dimension, ring_tag>\r
+ : detail::extreme_points::extreme_points_on_ring<Ring, Dimension>\r
+{};\r
+\r
+\r
+template<typename Polygon, std::size_t Dimension>\r
+struct extreme_points<Polygon, Dimension, polygon_tag>\r
+{\r
+ template <typename Extremes, typename Intruders>\r
+ static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+ typedef detail::extreme_points::extreme_points_on_ring\r
+ <\r
+ ring_type, Dimension\r
+ > ring_implementation;\r
+\r
+ if (! ring_implementation::apply(geometry::exterior_ring(polygon), extremes, intruders))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // For a polygon, its interior rings can contain intruders\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ ring_implementation::get_intruders(*it, extremes, intruders);\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+template<typename Box>\r
+struct extreme_points<Box, 1, box_tag>\r
+{\r
+ template <typename Extremes, typename Intruders>\r
+ static inline bool apply(Box const& box, Extremes& extremes, Intruders& )\r
+ {\r
+ extremes.resize(4);\r
+ geometry::detail::assign_box_corners_oriented<false>(box, extremes);\r
+ // ll,ul,ur,lr, contains too exactly the right info\r
+ return true;\r
+ }\r
+};\r
+\r
+template<typename Box>\r
+struct extreme_points<Box, 0, box_tag>\r
+{\r
+ template <typename Extremes, typename Intruders>\r
+ static inline bool apply(Box const& box, Extremes& extremes, Intruders& )\r
+ {\r
+ extremes.resize(4);\r
+ geometry::detail::assign_box_corners_oriented<false>(box, extremes);\r
+ // ll,ul,ur,lr, rotate one to start with UL and end with LL\r
+ std::rotate(extremes.begin(), extremes.begin() + 1, extremes.end());\r
+ return true;\r
+ }\r
+};\r
+\r
+template<typename MultiPolygon, std::size_t Dimension>\r
+struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>\r
+{\r
+ template <typename Extremes, typename Intruders>\r
+ static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders)\r
+ {\r
+ // Get one for the very first polygon, that is (for the moment) enough.\r
+ // It is not guaranteed the "extreme" then, but for the current purpose\r
+ // (point_on_surface) it can just be this point.\r
+ if (boost::size(multi) >= 1)\r
+ {\r
+ return extreme_points\r
+ <\r
+ typename boost::range_value<MultiPolygon const>::type,\r
+ Dimension,\r
+ polygon_tag\r
+ >::apply(*boost::begin(multi), extremes, intruders);\r
+ }\r
+\r
+ return false;\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief Returns extreme points (for Edge=1 in dimension 1, so the top,\r
+ for Edge=0 in dimension 0, the right side)\r
+\note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that.\r
+ */\r
+template <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders>\r
+inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ // Extremes is not required to follow a geometry concept (but it should support an output iterator),\r
+ // but its elements should fulfil the point-concept\r
+ concepts::check<typename boost::range_value<Extremes>::type>();\r
+\r
+ // Intruders should contain collections which value type is point-concept\r
+ // Extremes might be anything (supporting an output iterator), but its elements should fulfil the point-concept\r
+ concepts::check\r
+ <\r
+ typename boost::range_value\r
+ <\r
+ typename boost::range_value<Intruders>::type\r
+ >::type\r
+ const\r
+ >();\r
+\r
+ return dispatch::extreme_points<Geometry, Edge>::apply(geometry, extremes, intruders);\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch\r
+{\r
+\r
+template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct flattening\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+template <typename ResultType, typename Geometry>\r
+struct flattening<ResultType, Geometry, srs_sphere_tag>\r
+{\r
+ static inline ResultType apply(Geometry const& /*geometry*/)\r
+ {\r
+ return ResultType(0);\r
+ }\r
+};\r
+\r
+template <typename ResultType, typename Geometry>\r
+struct flattening<ResultType, Geometry, srs_spheroid_tag>\r
+{\r
+ static inline ResultType apply(Geometry const& geometry)\r
+ {\r
+ return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry))\r
+ / ResultType(get_radius<0>(geometry));\r
+ }\r
+};\r
+\r
+} // namespace detail_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename ResultType, typename Geometry>\r
+ResultType flattening(Geometry const& geometry)\r
+{\r
+ return detail_dispatch::flattening<ResultType, Geometry>::apply(geometry);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/add_const_if_c.hpp>\r
+#include <boost/geometry/views/box_view.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace for_each\r
+{\r
+\r
+\r
+template <typename Range, typename Actor>\r
+struct fe_range_range\r
+{\r
+ static inline void apply(Range & range, Actor & actor)\r
+ {\r
+ actor.apply(range);\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon, typename Actor>\r
+struct fe_range_polygon\r
+{\r
+ static inline void apply(Polygon & polygon, Actor & actor)\r
+ {\r
+ actor.apply(exterior_ring(polygon));\r
+\r
+ // TODO: If some flag says true, also do the inner rings.\r
+ // for convex hull, it's not necessary\r
+ }\r
+};\r
+\r
+template <typename Box, typename Actor>\r
+struct fe_range_box\r
+{\r
+ static inline void apply(Box & box, Actor & actor)\r
+ {\r
+ actor.apply(box_view<typename boost::remove_const<Box>::type>(box));\r
+ }\r
+};\r
+\r
+template <typename Multi, typename Actor, typename SinglePolicy>\r
+struct fe_range_multi\r
+{\r
+ static inline void apply(Multi & multi, Actor & actor)\r
+ {\r
+ for ( typename boost::range_iterator<Multi>::type\r
+ it = boost::begin(multi); it != boost::end(multi); ++it)\r
+ {\r
+ SinglePolicy::apply(*it, actor);\r
+ }\r
+ }\r
+};\r
+\r
+}} // namespace detail::for_each\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Actor,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct for_each_range\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+template <typename Linestring, typename Actor>\r
+struct for_each_range<Linestring, Actor, linestring_tag>\r
+ : detail::for_each::fe_range_range<Linestring, Actor>\r
+{};\r
+\r
+\r
+template <typename Ring, typename Actor>\r
+struct for_each_range<Ring, Actor, ring_tag>\r
+ : detail::for_each::fe_range_range<Ring, Actor>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Actor>\r
+struct for_each_range<Polygon, Actor, polygon_tag>\r
+ : detail::for_each::fe_range_polygon<Polygon, Actor>\r
+{};\r
+\r
+\r
+template <typename Box, typename Actor>\r
+struct for_each_range<Box, Actor, box_tag>\r
+ : detail::for_each::fe_range_box<Box, Actor>\r
+{};\r
+\r
+\r
+template <typename MultiPoint, typename Actor>\r
+struct for_each_range<MultiPoint, Actor, multi_point_tag>\r
+ : detail::for_each::fe_range_range<MultiPoint, Actor>\r
+{};\r
+\r
+\r
+template <typename Geometry, typename Actor>\r
+struct for_each_range<Geometry, Actor, multi_linestring_tag>\r
+ : detail::for_each::fe_range_multi\r
+ <\r
+ Geometry,\r
+ Actor,\r
+ detail::for_each::fe_range_range\r
+ <\r
+ typename add_const_if_c\r
+ <\r
+ boost::is_const<Geometry>::value,\r
+ typename boost::range_value<Geometry>::type\r
+ >::type,\r
+ Actor\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+template <typename Geometry, typename Actor>\r
+struct for_each_range<Geometry, Actor, multi_polygon_tag>\r
+ : detail::for_each::fe_range_multi\r
+ <\r
+ Geometry,\r
+ Actor,\r
+ detail::for_each::fe_range_polygon\r
+ <\r
+ typename add_const_if_c\r
+ <\r
+ boost::is_const<Geometry>::value,\r
+ typename boost::range_value<Geometry>::type\r
+ >::type,\r
+ Actor\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+namespace detail\r
+{\r
+\r
+template <typename Geometry, typename Actor>\r
+inline void for_each_range(Geometry const& geometry, Actor & actor)\r
+{\r
+ dispatch::for_each_range\r
+ <\r
+ Geometry const,\r
+ Actor\r
+ >::apply(geometry, actor);\r
+}\r
+\r
+\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/iterators/closing_iterator.hpp>\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+// TODO: move this to /util/\r
+template <typename T>\r
+inline std::pair<T, T> ordered_pair(T const& first, T const& second)\r
+{\r
+ return first < second ? std::make_pair(first, second) : std::make_pair(second, first);\r
+}\r
+\r
+namespace left_turns\r
+{\r
+\r
+\r
+\r
+template <typename Vector>\r
+inline int get_quadrant(Vector const& vector)\r
+{\r
+ // Return quadrant as layouted in the code below:\r
+ // 3 | 0\r
+ // -----\r
+ // 2 | 1\r
+ return geometry::get<1>(vector) >= 0\r
+ ? (geometry::get<0>(vector) < 0 ? 3 : 0)\r
+ : (geometry::get<0>(vector) < 0 ? 2 : 1)\r
+ ;\r
+}\r
+\r
+template <typename Vector>\r
+inline int squared_length(Vector const& vector)\r
+{\r
+ return geometry::get<0>(vector) * geometry::get<0>(vector)\r
+ + geometry::get<1>(vector) * geometry::get<1>(vector)\r
+ ;\r
+}\r
+\r
+\r
+template <typename Point>\r
+struct angle_less\r
+{\r
+ typedef Point vector_type;\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type side_strategy_type;\r
+\r
+ angle_less(Point const& origin)\r
+ : m_origin(origin)\r
+ {}\r
+\r
+ template <typename Angle>\r
+ inline bool operator()(Angle const& p, Angle const& q) const\r
+ {\r
+ // Vector origin -> p and origin -> q\r
+ vector_type pv = p.point;\r
+ vector_type qv = q.point;\r
+ geometry::subtract_point(pv, m_origin);\r
+ geometry::subtract_point(qv, m_origin);\r
+\r
+ int const quadrant_p = get_quadrant(pv);\r
+ int const quadrant_q = get_quadrant(qv);\r
+ if (quadrant_p != quadrant_q)\r
+ {\r
+ return quadrant_p < quadrant_q;\r
+ }\r
+ // Same quadrant, check if p is located left of q\r
+ int const side = side_strategy_type::apply(m_origin, q.point,\r
+ p.point);\r
+ if (side != 0)\r
+ {\r
+ return side == 1;\r
+ }\r
+ // Collinear, check if one is incoming, incoming angles come first\r
+ if (p.incoming != q.incoming)\r
+ {\r
+ return int(p.incoming) < int(q.incoming);\r
+ }\r
+ // Same quadrant/side/direction, return longest first\r
+ // TODO: maybe not necessary, decide this\r
+ int const length_p = squared_length(pv);\r
+ int const length_q = squared_length(qv);\r
+ if (length_p != length_q)\r
+ {\r
+ return squared_length(pv) > squared_length(qv);\r
+ }\r
+ // They are still the same. Just compare on seg_id\r
+ return p.seg_id < q.seg_id;\r
+ }\r
+\r
+private:\r
+ Point m_origin;\r
+};\r
+\r
+template <typename Point>\r
+struct angle_equal_to\r
+{\r
+ typedef Point vector_type;\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type side_strategy_type;\r
+\r
+ inline angle_equal_to(Point const& origin)\r
+ : m_origin(origin)\r
+ {}\r
+\r
+ template <typename Angle>\r
+ inline bool operator()(Angle const& p, Angle const& q) const\r
+ {\r
+ // Vector origin -> p and origin -> q\r
+ vector_type pv = p.point;\r
+ vector_type qv = q.point;\r
+ geometry::subtract_point(pv, m_origin);\r
+ geometry::subtract_point(qv, m_origin);\r
+\r
+ if (get_quadrant(pv) != get_quadrant(qv))\r
+ {\r
+ return false;\r
+ }\r
+ // Same quadrant, check if p/q are collinear\r
+ int const side = side_strategy_type::apply(m_origin, q.point,\r
+ p.point);\r
+ return side == 0;\r
+ }\r
+\r
+private:\r
+ Point m_origin;\r
+};\r
+\r
+template <typename AngleCollection, typename Turns>\r
+inline void get_left_turns(AngleCollection const& sorted_angles,\r
+ Turns& turns)\r
+{\r
+ std::set<std::size_t> good_incoming;\r
+ std::set<std::size_t> good_outgoing;\r
+\r
+ for (typename boost::range_iterator<AngleCollection const>::type it =\r
+ sorted_angles.begin(); it != sorted_angles.end(); ++it)\r
+ {\r
+ if (!it->blocked)\r
+ {\r
+ if (it->incoming)\r
+ {\r
+ good_incoming.insert(it->turn_index);\r
+ }\r
+ else\r
+ {\r
+ good_outgoing.insert(it->turn_index);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (good_incoming.empty() || good_outgoing.empty())\r
+ {\r
+ return;\r
+ }\r
+\r
+ for (typename boost::range_iterator<AngleCollection const>::type it =\r
+ sorted_angles.begin(); it != sorted_angles.end(); ++it)\r
+ {\r
+ if (good_incoming.count(it->turn_index) == 0\r
+ || good_outgoing.count(it->turn_index) == 0)\r
+ {\r
+ turns[it->turn_index].remove_on_multi = true;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+//! Returns the number of clusters\r
+template <typename Point, typename AngleCollection>\r
+inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin)\r
+{\r
+ // Assign same cluster_index for all turns in same direction\r
+ BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u);\r
+\r
+ angle_equal_to<Point> comparator(origin);\r
+ typename boost::range_iterator<AngleCollection>::type it = sorted.begin();\r
+\r
+ std::size_t cluster_index = 0;\r
+ it->cluster_index = cluster_index;\r
+ typename boost::range_iterator<AngleCollection>::type previous = it++;\r
+ for (; it != sorted.end(); ++it)\r
+ {\r
+ if (!comparator(*previous, *it))\r
+ {\r
+ cluster_index++;\r
+ previous = it;\r
+ }\r
+ it->cluster_index = cluster_index;\r
+ }\r
+ return cluster_index + 1;\r
+}\r
+\r
+template <typename AngleCollection>\r
+inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0);\r
+\r
+ std::vector<std::pair<bool, bool> > directions;\r
+ for (std::size_t i = 0; i < cluster_size; i++)\r
+ {\r
+ directions.push_back(std::make_pair(false, false));\r
+ }\r
+\r
+ for (typename boost::range_iterator<AngleCollection const>::type it = sorted.begin();\r
+ it != sorted.end(); ++it)\r
+ {\r
+ if (it->incoming)\r
+ {\r
+ directions[it->cluster_index].first = true;\r
+ }\r
+ else\r
+ {\r
+ directions[it->cluster_index].second = true;\r
+ }\r
+ }\r
+\r
+ for (typename boost::range_iterator<AngleCollection>::type it = sorted.begin();\r
+ it != sorted.end(); ++it)\r
+ {\r
+ signed_size_type cluster_index = static_cast<signed_size_type>(it->cluster_index);\r
+ signed_size_type previous_index = cluster_index - 1;\r
+ if (previous_index < 0)\r
+ {\r
+ previous_index = cluster_size - 1;\r
+ }\r
+ signed_size_type next_index = cluster_index + 1;\r
+ if (next_index >= static_cast<signed_size_type>(cluster_size))\r
+ {\r
+ next_index = 0;\r
+ }\r
+\r
+ if (directions[cluster_index].first\r
+ && directions[cluster_index].second)\r
+ {\r
+ it->blocked = true;\r
+ }\r
+ else if (!directions[cluster_index].first\r
+ && directions[cluster_index].second\r
+ && directions[previous_index].second)\r
+ {\r
+ // Only outgoing, previous was also outgoing: block this one\r
+ it->blocked = true;\r
+ }\r
+ else if (directions[cluster_index].first\r
+ && !directions[cluster_index].second\r
+ && !directions[previous_index].first\r
+ && directions[previous_index].second)\r
+ {\r
+ // Only incoming, previous was only outgoing: block this one\r
+ it->blocked = true;\r
+ }\r
+ else if (directions[cluster_index].first\r
+ && !directions[cluster_index].second\r
+ && directions[next_index].first\r
+ && !directions[next_index].second)\r
+ {\r
+ // Only incoming, next also incoming, block this one\r
+ it->blocked = true;\r
+ }\r
+ }\r
+}\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+template <typename AngleCollection, typename Point>\r
+inline bool has_rounding_issues(AngleCollection const& angles, Point const& origin)\r
+{\r
+ for (typename boost::range_iterator<AngleCollection const>::type it =\r
+ angles.begin(); it != angles.end(); ++it)\r
+ {\r
+ // Vector origin -> p and origin -> q\r
+ typedef Point vector_type;\r
+ vector_type v = it->point;\r
+ geometry::subtract_point(v, origin);\r
+ return geometry::math::abs(geometry::get<0>(v)) <= 1\r
+ || geometry::math::abs(geometry::get<1>(v)) <= 1\r
+ ;\r
+ }\r
+ return false;\r
+}\r
+#endif\r
+\r
+\r
+} // namespace left_turns\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Box, std::size_t Dimension>\r
+struct get_max_size_box\r
+{\r
+ static inline typename coordinate_type<Box>::type apply(Box const& box)\r
+ {\r
+ typename coordinate_type<Box>::type s\r
+ = geometry::math::abs(geometry::get<1, Dimension>(box) - geometry::get<0, Dimension>(box));\r
+\r
+ return (std::max)(s, get_max_size_box<Box, Dimension - 1>::apply(box));\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct get_max_size_box<Box, 0>\r
+{\r
+ static inline typename coordinate_type<Box>::type apply(Box const& box)\r
+ {\r
+ return geometry::math::abs(geometry::get<1, 0>(box) - geometry::get<0, 0>(box));\r
+ }\r
+};\r
+\r
+// This might be implemented later on for other geometries too.\r
+// Not dispatched yet.\r
+template <typename Box>\r
+inline typename coordinate_type<Box>::type get_max_size(Box const& box)\r
+{\r
+ return get_max_size_box<Box, dimension<Box>::value - 1>::apply(box);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP\r
+\r
+#include <deque>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>\r
+\r
+#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS\r
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+# include <boost/geometry/io/dsv/write.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+\r
+/*!\r
+\brief Overlay Invalid Input Exception\r
+\ingroup overlay\r
+\details The overlay_invalid_input_exception is thrown at invalid input\r
+ */\r
+class overlay_invalid_input_exception : public geometry::exception\r
+{\r
+public:\r
+\r
+ inline overlay_invalid_input_exception() {}\r
+\r
+ virtual char const* what() const throw()\r
+ {\r
+ return "Boost.Geometry Overlay invalid input exception";\r
+ }\r
+};\r
+\r
+#endif\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template <typename Geometry, typename RobustPolicy>\r
+inline bool has_self_intersections(Geometry const& geometry,\r
+ RobustPolicy const& robust_policy,\r
+ bool throw_on_self_intersection = true)\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef turn_info\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type<point_type, RobustPolicy>::type\r
+ > turn_info;\r
+ std::deque<turn_info> turns;\r
+ detail::disjoint::disjoint_interrupt_policy policy;\r
+\r
+ geometry::self_turns<detail::overlay::assign_null_policy>(geometry, robust_policy, turns, policy);\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS\r
+ bool first = true;\r
+#endif\r
+ for(typename std::deque<turn_info>::const_iterator it = boost::begin(turns);\r
+ it != boost::end(turns); ++it)\r
+ {\r
+ turn_info const& info = *it;\r
+ bool const both_union_turn =\r
+ info.operations[0].operation == detail::overlay::operation_union\r
+ && info.operations[1].operation == detail::overlay::operation_union;\r
+ bool const both_intersection_turn =\r
+ info.operations[0].operation == detail::overlay::operation_intersection\r
+ && info.operations[1].operation == detail::overlay::operation_intersection;\r
+\r
+ bool const valid = (both_union_turn || both_intersection_turn)\r
+ && (info.method == detail::overlay::method_touch\r
+ || info.method == detail::overlay::method_touch_interior);\r
+\r
+ if (! valid)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS\r
+ if (first)\r
+ {\r
+ std::cout << "turn points: " << std::endl;\r
+ first = false;\r
+ }\r
+ std::cout << method_char(info.method);\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ std::cout << " " << operation_char(info.operations[i].operation);\r
+ std::cout << " " << info.operations[i].seg_id;\r
+ }\r
+ std::cout << " " << geometry::dsv(info.point) << std::endl;\r
+#endif\r
+\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+ if (throw_on_self_intersection)\r
+ {\r
+ throw overlay_invalid_input_exception();\r
+ }\r
+#endif\r
+ return true;\r
+ }\r
+\r
+ }\r
+ return false;\r
+}\r
+\r
+// For backward compatibility\r
+template <typename Geometry>\r
+inline bool has_self_intersections(Geometry const& geometry,\r
+ bool throw_on_self_intersection = true)\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef typename geometry::rescale_policy_type<point_type>::type\r
+ rescale_policy_type;\r
+\r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry);\r
+\r
+ return has_self_intersections(geometry, robust_policy,\r
+ throw_on_self_intersection);\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP\r
+\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP\r
+\r
+#include <boost/range/iterator.hpp>\r
+#include <boost/range/value_type.hpp>\r
+\r
+#include <boost/geometry/core/interior_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+/*!\r
+\brief Structure defining the type of interior rings iterator\r
+\note If the Geometry is const, const iterator is defined.\r
+\tparam Geometry \tparam_geometry\r
+ */\r
+template <typename Geometry>\r
+struct interior_iterator\r
+{\r
+ typedef typename boost::range_iterator\r
+ <\r
+ typename geometry::interior_type<Geometry>::type \r
+ >::type type;\r
+};\r
+\r
+template <typename BaseT, typename T>\r
+struct copy_const\r
+{\r
+ typedef T type;\r
+};\r
+\r
+template <typename BaseT, typename T>\r
+struct copy_const<BaseT const, T>\r
+{\r
+ typedef T const type;\r
+};\r
+\r
+template <typename Geometry>\r
+struct interior_ring_iterator\r
+{\r
+ typedef typename boost::range_iterator\r
+ <\r
+ typename copy_const\r
+ <\r
+ typename geometry::interior_type<Geometry>::type,\r
+ typename boost::range_value\r
+ <\r
+ typename geometry::interior_type<Geometry>::type\r
+ >::type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/intersection/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Box1, typename Box2, bool Reverse\r
+>\r
+struct intersection\r
+ <\r
+ Box1, Box2,\r
+ box_tag, box_tag,\r
+ Reverse\r
+ > : public detail::intersection::intersection_box_box\r
+ <\r
+ 0, geometry::dimension<Box1>::value\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/intersection/box_box.hpp>\r
+#include <boost/geometry/algorithms/detail/intersection/multi.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP\r
+\r
+\r
+// TODO: those headers probably may be removed\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+// By default, all is forwarded to the intersection_insert-dispatcher\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1 = typename geometry::tag<Geometry1>::type,\r
+ typename Tag2 = typename geometry::tag<Geometry2>::type,\r
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct intersection\r
+{\r
+ template <typename RobustPolicy, typename GeometryOut, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ GeometryOut& geometry_out,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename boost::range_value<GeometryOut>::type OneOut;\r
+\r
+ intersection_insert\r
+ <\r
+ Geometry1, Geometry2, OneOut,\r
+ overlay_intersection\r
+ >::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy);\r
+\r
+ return true;\r
+ }\r
+\r
+};\r
+\r
+\r
+// If reversal is needed, perform it\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1, typename Tag2\r
+>\r
+struct intersection\r
+<\r
+ Geometry1, Geometry2,\r
+ Tag1, Tag2,\r
+ true\r
+>\r
+ : intersection<Geometry2, Geometry1, Tag2, Tag1, false>\r
+{\r
+ template <typename RobustPolicy, typename GeometryOut, typename Strategy>\r
+ static inline bool apply(\r
+ Geometry1 const& g1,\r
+ Geometry2 const& g2,\r
+ RobustPolicy const& robust_policy,\r
+ GeometryOut& out,\r
+ Strategy const& strategy)\r
+ {\r
+ return intersection<\r
+ Geometry2, Geometry1,\r
+ Tag2, Tag1,\r
+ false\r
+ >::apply(g2, g1, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+ \r
+namespace resolve_variant\r
+{\r
+ \r
+template <typename Geometry1, typename Geometry2>\r
+struct intersection\r
+{\r
+ template <typename GeometryOut>\r
+ static inline bool\r
+ apply(\r
+ const Geometry1& geometry1,\r
+ const Geometry2& geometry2,\r
+ GeometryOut& geometry_out)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ \r
+ typedef typename geometry::rescale_overlay_policy_type\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::type rescale_policy_type;\r
+ \r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1,\r
+ geometry2);\r
+ \r
+ typedef intersection_strategies\r
+ <\r
+ typename cs_tag<Geometry1>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ typename geometry::point_type<Geometry1>::type,\r
+ rescale_policy_type\r
+ > strategy;\r
+ \r
+ return dispatch::intersection\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy());\r
+ }\r
+};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename GeometryOut>\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ GeometryOut& m_geometry_out;\r
+ \r
+ visitor(Geometry2 const& geometry2,\r
+ GeometryOut& geometry_out)\r
+ : m_geometry2(geometry2)\r
+ , m_geometry_out(geometry_out)\r
+ {}\r
+ \r
+ template <typename Geometry1>\r
+ result_type operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return intersection\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ GeometryOut\r
+ >\r
+ (geometry1, m_geometry2, m_geometry_out);\r
+ }\r
+ };\r
+ \r
+ template <typename GeometryOut>\r
+ static inline bool\r
+ apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ GeometryOut& geometry_out)\r
+ {\r
+ return boost::apply_visitor(visitor<GeometryOut>(geometry2, geometry_out), geometry1);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename GeometryOut>\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ GeometryOut& m_geometry_out;\r
+ \r
+ visitor(Geometry1 const& geometry1,\r
+ GeometryOut& geometry_out)\r
+ : m_geometry1(geometry1)\r
+ , m_geometry_out(geometry_out)\r
+ {}\r
+ \r
+ template <typename Geometry2>\r
+ result_type operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return intersection\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ GeometryOut\r
+ >\r
+ (m_geometry1, geometry2, m_geometry_out);\r
+ }\r
+ };\r
+ \r
+ template <typename GeometryOut>\r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,\r
+ GeometryOut& geometry_out)\r
+ {\r
+ return boost::apply_visitor(visitor<GeometryOut>(geometry1, geometry_out), geometry2);\r
+ }\r
+};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>\r
+struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >\r
+{\r
+ template <typename GeometryOut>\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ GeometryOut& m_geometry_out;\r
+ \r
+ visitor(GeometryOut& geometry_out)\r
+ : m_geometry_out(geometry_out)\r
+ {}\r
+ \r
+ template <typename Geometry1, typename Geometry2>\r
+ result_type operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return intersection\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ GeometryOut\r
+ >\r
+ (geometry1, geometry2, m_geometry_out);\r
+ }\r
+ };\r
+ \r
+ template <typename GeometryOut>\r
+ static inline bool\r
+ apply(const variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,\r
+ const variant<BOOST_VARIANT_ENUM_PARAMS(T2)>& geometry2,\r
+ GeometryOut& geometry_out)\r
+ {\r
+ return boost::apply_visitor(visitor<GeometryOut>(geometry_out), geometry1, geometry2);\r
+ }\r
+};\r
+ \r
+} // namespace resolve_variant\r
+ \r
+\r
+/*!\r
+\brief \brief_calc2{intersection}\r
+\ingroup intersection\r
+\details \details_calc2{intersection, spatial set theoretic intersection}.\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which\r
+ the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param geometry_out The output geometry, either a multi_point, multi_polygon,\r
+ multi_linestring, or a box (for intersection of two boxes)\r
+\r
+\qbk{[include reference/algorithms/intersection.qbk]}\r
+*/\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename GeometryOut\r
+>\r
+inline bool intersection(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ GeometryOut& geometry_out)\r
+{\r
+ return resolve_variant::intersection\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply\r
+ <\r
+ GeometryOut\r
+ >\r
+ (geometry1, geometry2, geometry_out);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/geometry_id.hpp>\r
+#include <boost/geometry/core/is_areal.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+// TODO: those headers probably may be removed\r
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/intersection/interface.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace intersection\r
+{\r
+\r
+\r
+template <typename PointOut>\r
+struct intersection_multi_linestring_multi_linestring_point\r
+{\r
+ template\r
+ <\r
+ typename MultiLinestring1, typename MultiLinestring2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(MultiLinestring1 const& ml1,\r
+ MultiLinestring2 const& ml2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ // Note, this loop is quadratic w.r.t. number of linestrings per input.\r
+ // Future Enhancement: first do the sections of each, then intersect.\r
+ for (typename boost::range_iterator\r
+ <\r
+ MultiLinestring1 const\r
+ >::type it1 = boost::begin(ml1);\r
+ it1 != boost::end(ml1);\r
+ ++it1)\r
+ {\r
+ for (typename boost::range_iterator\r
+ <\r
+ MultiLinestring2 const\r
+ >::type it2 = boost::begin(ml2);\r
+ it2 != boost::end(ml2);\r
+ ++it2)\r
+ {\r
+ out = intersection_linestring_linestring_point<PointOut>\r
+ ::apply(*it1, *it2, robust_policy, out, strategy);\r
+ }\r
+ }\r
+\r
+ return out;\r
+ }\r
+};\r
+\r
+\r
+template <typename PointOut>\r
+struct intersection_linestring_multi_linestring_point\r
+{\r
+ template\r
+ <\r
+ typename Linestring, typename MultiLinestring,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Linestring const& linestring,\r
+ MultiLinestring const& ml,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ for (typename boost::range_iterator\r
+ <\r
+ MultiLinestring const\r
+ >::type it = boost::begin(ml);\r
+ it != boost::end(ml);\r
+ ++it)\r
+ {\r
+ out = intersection_linestring_linestring_point<PointOut>\r
+ ::apply(linestring, *it, robust_policy, out, strategy);\r
+ }\r
+\r
+ return out;\r
+ }\r
+};\r
+\r
+\r
+// This loop is quite similar to the loop above, but beacuse the iterator\r
+// is second (above) or first (below) argument, it is not trivial to merge them.\r
+template\r
+<\r
+ bool ReverseAreal,\r
+ typename LineStringOut,\r
+ overlay_type OverlayType\r
+>\r
+struct intersection_of_multi_linestring_with_areal\r
+{\r
+ template\r
+ <\r
+ typename MultiLinestring, typename Areal,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ for (typename boost::range_iterator\r
+ <\r
+ MultiLinestring const\r
+ >::type it = boost::begin(ml);\r
+ it != boost::end(ml);\r
+ ++it)\r
+ {\r
+ out = intersection_of_linestring_with_areal\r
+ <\r
+ ReverseAreal, LineStringOut, OverlayType\r
+ >::apply(*it, areal, robust_policy, out, strategy);\r
+ }\r
+\r
+ return out;\r
+\r
+ }\r
+};\r
+\r
+// This one calls the one above with reversed arguments\r
+template\r
+<\r
+ bool ReverseAreal,\r
+ typename LineStringOut,\r
+ overlay_type OverlayType\r
+>\r
+struct intersection_of_areal_with_multi_linestring\r
+{\r
+ template\r
+ <\r
+ typename Areal, typename MultiLinestring,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ return intersection_of_multi_linestring_with_areal\r
+ <\r
+ ReverseAreal, LineStringOut, OverlayType\r
+ >::apply(ml, areal, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename LinestringOut>\r
+struct clip_multi_linestring\r
+{\r
+ template\r
+ <\r
+ typename MultiLinestring, typename Box,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(MultiLinestring const& multi_linestring,\r
+ Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out, Strategy const& )\r
+ {\r
+ typedef typename point_type<LinestringOut>::type point_type;\r
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;\r
+ for (typename boost::range_iterator<MultiLinestring const>::type it\r
+ = boost::begin(multi_linestring);\r
+ it != boost::end(multi_linestring); ++it)\r
+ {\r
+ out = detail::intersection::clip_range_with_box\r
+ <LinestringOut>(box, *it, robust_policy, out, lb_strategy);\r
+ }\r
+ return out;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::intersection\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// Linear\r
+template\r
+<\r
+ typename MultiLinestring1, typename MultiLinestring2,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiLinestring1, MultiLinestring2,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ multi_linestring_tag, multi_linestring_tag, point_tag,\r
+ false, false, false\r
+ > : detail::intersection::intersection_multi_linestring_multi_linestring_point\r
+ <\r
+ GeometryOut\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring, typename MultiLinestring,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring, MultiLinestring,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ linestring_tag, multi_linestring_tag, point_tag,\r
+ false, false, false\r
+ > : detail::intersection::intersection_linestring_multi_linestring_point\r
+ <\r
+ GeometryOut\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiLinestring, typename Box,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiLinestring, Box,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ multi_linestring_tag, box_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::clip_multi_linestring\r
+ <\r
+ GeometryOut\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring, typename MultiPolygon,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring, MultiPolygon,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReverseLinestring, ReverseMultiPolygon, ReverseOut,\r
+ linestring_tag, multi_polygon_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::intersection_of_linestring_with_areal\r
+ <\r
+ ReverseMultiPolygon,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+\r
+// Derives from areal/mls because runtime arguments are in that order.\r
+// areal/mls reverses it itself to mls/areal\r
+template\r
+<\r
+ typename Polygon, typename MultiLinestring,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Polygon, MultiLinestring,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReversePolygon, ReverseMultiLinestring, ReverseOut,\r
+ polygon_tag, multi_linestring_tag, linestring_tag,\r
+ true, false, false\r
+ > : detail::intersection::intersection_of_areal_with_multi_linestring\r
+ <\r
+ ReversePolygon,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiLinestring, typename Ring,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiLinestring, Ring,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReverseMultiLinestring, ReverseRing, ReverseOut,\r
+ multi_linestring_tag, ring_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::intersection_of_multi_linestring_with_areal\r
+ <\r
+ ReverseRing,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename MultiLinestring, typename Polygon,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiLinestring, Polygon,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReverseMultiLinestring, ReverseRing, ReverseOut,\r
+ multi_linestring_tag, polygon_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::intersection_of_multi_linestring_with_areal\r
+ <\r
+ ReverseRing,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+\r
+\r
+template\r
+<\r
+ typename MultiLinestring, typename MultiPolygon,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiLinestring, MultiPolygon,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut,\r
+ multi_linestring_tag, multi_polygon_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::intersection_of_multi_linestring_with_areal\r
+ <\r
+ ReverseMultiPolygon,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_simple.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_simple\r
+{\r
+\r
+\r
+template <typename Geometry>\r
+struct always_simple\r
+{\r
+ static inline bool apply(Geometry const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_simple\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A point is always simple\r
+template <typename Point>\r
+struct is_simple<Point, point_tag>\r
+ : detail::is_simple::always_simple<Point>\r
+{};\r
+\r
+\r
+// A valid segment is always simple.\r
+// A segment is a curve.\r
+// A curve is simple if it does not pass through the same point twice,\r
+// with the possible exception of its two endpoints\r
+//\r
+// Reference: OGC 06-103r4 (6.1.6.1)\r
+template <typename Segment>\r
+struct is_simple<Segment, segment_tag>\r
+ : detail::is_simple::always_simple<Segment>\r
+{};\r
+\r
+\r
+// A valid box is always simple\r
+// A box is a Polygon, and it satisfies the conditions for Polygon validity.\r
+//\r
+// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)\r
+template <typename Box>\r
+struct is_simple<Box, box_tag>\r
+ : detail::is_simple::always_simple<Box>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_simple.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_simple\r
+{\r
+\r
+\r
+template <typename Ring>\r
+struct is_simple_ring\r
+{\r
+ static inline bool apply(Ring const& ring)\r
+ {\r
+ simplicity_failure_policy policy;\r
+ return ! boost::empty(ring)\r
+ && ! detail::is_valid::has_duplicates\r
+ <\r
+ Ring, geometry::closure<Ring>::value\r
+ >::apply(ring, policy);\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+class is_simple_polygon\r
+{\r
+private:\r
+ template <typename InteriorRings>\r
+ static inline\r
+ bool are_simple_interior_rings(InteriorRings const& interior_rings)\r
+ {\r
+ return\r
+ detail::check_iterator_range\r
+ <\r
+ is_simple_ring\r
+ <\r
+ typename boost::range_value<InteriorRings>::type\r
+ >\r
+ >::apply(boost::begin(interior_rings),\r
+ boost::end(interior_rings));\r
+ }\r
+\r
+public:\r
+ static inline bool apply(Polygon const& polygon)\r
+ {\r
+ return\r
+ is_simple_ring\r
+ <\r
+ typename ring_type<Polygon>::type\r
+ >::apply(exterior_ring(polygon))\r
+ &&\r
+ are_simple_interior_rings(geometry::interior_rings(polygon));\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_simple\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A Ring is a Polygon.\r
+// A Polygon is always a simple geometric object provided that it is valid.\r
+//\r
+// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)\r
+template <typename Ring>\r
+struct is_simple<Ring, ring_tag>\r
+ : detail::is_simple::is_simple_ring<Ring>\r
+{};\r
+\r
+\r
+// A Polygon is always a simple geometric object provided that it is valid.\r
+//\r
+// Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1)\r
+template <typename Polygon>\r
+struct is_simple<Polygon, polygon_tag>\r
+ : detail::is_simple::is_simple_polygon<Polygon>\r
+{};\r
+\r
+\r
+// Not clear what the definition is.\r
+// Right now we consider a MultiPolygon as simple if it is valid.\r
+//\r
+// Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14)\r
+template <typename MultiPolygon>\r
+struct is_simple<MultiPolygon, multi_polygon_tag>\r
+{\r
+ static inline bool apply(MultiPolygon const& multipolygon)\r
+ {\r
+ return\r
+ detail::check_iterator_range\r
+ <\r
+ detail::is_simple::is_simple_polygon\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >,\r
+ true // allow empty multi-polygon\r
+ >::apply(boost::begin(multipolygon), boost::end(multipolygon));\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+#include <algorithm>\r
+#include <iostream>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#endif // BOOST_GEOMETRY_TEST_DEBUG\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace is_simple\r
+{\r
+\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+template <typename Linear, typename Tag = typename tag<Linear>::type>\r
+struct debug_boundary_points_printer\r
+ : not_implemented<Linear>\r
+{};\r
+\r
+template <typename Linestring>\r
+struct debug_boundary_points_printer<Linestring, linestring_tag>\r
+{\r
+ static inline void apply(Linestring const& linestring)\r
+ {\r
+ std::cout << "boundary points: ";\r
+ std::cout << " " << geometry::dsv(range::front(linestring));\r
+ std::cout << " " << geometry::dsv(range::back(linestring));\r
+ std::cout << std::endl << std::endl;\r
+ }\r
+};\r
+\r
+template <typename MultiLinestring>\r
+struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>\r
+{\r
+ static inline void apply(MultiLinestring const& multilinestring)\r
+ {\r
+ typedef typename point_type<MultiLinestring>::type point_type;\r
+ typedef std::vector<point_type> point_vector;\r
+\r
+ point_vector boundary_points;\r
+ for (typename boost::range_iterator<MultiLinestring const>::type it\r
+ = boost::begin(multilinestring);\r
+ it != boost::end(multilinestring); ++it)\r
+ {\r
+ if ( boost::size(*it) > 1\r
+ && !geometry::equals(range::front(*it), range::back(*it)) )\r
+ {\r
+ boundary_points.push_back( range::front(*it) );\r
+ boundary_points.push_back( range::back(*it) );\r
+ }\r
+ }\r
+\r
+ std::sort(boundary_points.begin(), boundary_points.end(),\r
+ geometry::less<point_type>());\r
+\r
+ std::cout << "boundary points: ";\r
+ for (typename point_vector::const_iterator\r
+ pit = boundary_points.begin();\r
+ pit != boundary_points.end(); ++pit)\r
+ {\r
+ std::cout << " " << geometry::dsv(*pit);\r
+ }\r
+ std::cout << std::endl << std::endl;\r
+ }\r
+};\r
+\r
+\r
+template <typename Linear>\r
+inline void debug_print_boundary_points(Linear const& linear)\r
+{\r
+ debug_boundary_points_printer<Linear>::apply(linear);\r
+}\r
+#else\r
+template <typename Linear>\r
+inline void debug_print_boundary_points(Linear const&)\r
+{\r
+}\r
+#endif // BOOST_GEOMETRY_TEST_DEBUG\r
+\r
+\r
+}} // namespace detail::is_simple\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP\r
+\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_simple\r
+{\r
+\r
+\r
+struct simplicity_failure_policy\r
+{\r
+ template <validity_failure_type Failure>\r
+ static inline bool apply()\r
+ {\r
+ return Failure == no_failure;\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data>\r
+ static inline bool apply(Data const&)\r
+ {\r
+ return apply<Failure>();\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data1, typename Data2>\r
+ static inline bool apply(Data1 const&, Data2 const&)\r
+ {\r
+ return apply<Failure>();\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_simple\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_IMPLEMENTATION_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/is_simple/always_simple.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/areal.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/linear.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/multipoint.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_simple.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct is_simple\r
+{\r
+ static inline bool apply(Geometry const& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+ return dispatch::is_simple<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct is_simple<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor : boost::static_visitor<bool>\r
+ {\r
+ template <typename Geometry>\r
+ bool operator()(Geometry const& geometry) const\r
+ {\r
+ return is_simple<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_check{is simple}\r
+\ingroup is_simple\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_check{is simple}\r
+\r
+\qbk{[include reference/algorithms/is_simple.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool is_simple(Geometry const& geometry)\r
+{\r
+ return resolve_variant::is_simple<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP\r
+\r
+#include <algorithm>\r
+#include <deque>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/policies/predicate_based_interrupt_policy.hpp>\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_simple.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_simple\r
+{\r
+\r
+\r
+template <typename Turn>\r
+inline bool check_segment_indices(Turn const& turn,\r
+ signed_size_type last_index)\r
+{\r
+ return\r
+ (turn.operations[0].seg_id.segment_index == 0\r
+ && turn.operations[1].seg_id.segment_index == last_index)\r
+ ||\r
+ (turn.operations[0].seg_id.segment_index == 0\r
+ && turn.operations[1].seg_id.segment_index == last_index);\r
+}\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+class is_acceptable_turn\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+template <typename Linestring>\r
+class is_acceptable_turn<Linestring, linestring_tag>\r
+{\r
+public:\r
+ is_acceptable_turn(Linestring const& linestring)\r
+ : m_linestring(linestring)\r
+ , m_is_closed(geometry::equals(range::front(linestring),\r
+ range::back(linestring)))\r
+ {}\r
+\r
+ template <typename Turn>\r
+ inline bool apply(Turn const& turn) const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(m_linestring) > 1);\r
+ return m_is_closed\r
+ && turn.method == overlay::method_none\r
+ && check_segment_indices(turn, boost::size(m_linestring) - 2)\r
+ && turn.operations[0].fraction.is_zero();\r
+ }\r
+\r
+private:\r
+ Linestring const& m_linestring;\r
+ bool const m_is_closed;\r
+};\r
+\r
+template <typename MultiLinestring>\r
+class is_acceptable_turn<MultiLinestring, multi_linestring_tag>\r
+{\r
+private:\r
+ typedef typename boost::range_value<MultiLinestring>::type linestring_type;\r
+ typedef is_acceptable_turn<linestring_type> base_type;\r
+\r
+ template <typename Point, typename Linestring>\r
+ static inline bool is_boundary_point_of(Point const& point,\r
+ Linestring const& linestring)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1);\r
+ return\r
+ ! geometry::equals(range::front(linestring),\r
+ range::back(linestring))\r
+ &&\r
+ (geometry::equals(point, range::front(linestring))\r
+ || geometry::equals(point, range::back(linestring)));\r
+ }\r
+\r
+ template <typename Turn, typename Linestring>\r
+ static inline bool is_closing_point_of(Turn const& turn,\r
+ Linestring const& linestring)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1);\r
+ return\r
+ turn.method == overlay::method_none\r
+ &&\r
+ check_segment_indices(turn, boost::size(linestring) - 2)\r
+ &&\r
+ geometry::equals(range::front(linestring), range::back(linestring))\r
+ &&\r
+ turn.operations[0].fraction.is_zero();\r
+ ;\r
+ }\r
+\r
+ template <typename Linestring1, typename Linestring2>\r
+ static inline bool have_same_boundary_points(Linestring1 const& ls1,\r
+ Linestring2 const& ls2)\r
+ {\r
+ return\r
+ geometry::equals(range::front(ls1), range::front(ls2))\r
+ ?\r
+ geometry::equals(range::back(ls1), range::back(ls2))\r
+ :\r
+ (geometry::equals(range::front(ls1), range::back(ls2))\r
+ &&\r
+ geometry::equals(range::back(ls1), range::front(ls2)))\r
+ ;\r
+ }\r
+\r
+public:\r
+ is_acceptable_turn(MultiLinestring const& multilinestring)\r
+ : m_multilinestring(multilinestring)\r
+ {}\r
+\r
+ template <typename Turn>\r
+ inline bool apply(Turn const& turn) const\r
+ {\r
+ linestring_type const& ls1 =\r
+ range::at(m_multilinestring, turn.operations[0].seg_id.multi_index);\r
+\r
+ linestring_type const& ls2 =\r
+ range::at(m_multilinestring, turn.operations[1].seg_id.multi_index);\r
+\r
+ if (turn.operations[0].seg_id.multi_index\r
+ == turn.operations[1].seg_id.multi_index)\r
+ {\r
+ return is_closing_point_of(turn, ls1);\r
+ }\r
+\r
+ return\r
+ is_boundary_point_of(turn.point, ls1)\r
+ && is_boundary_point_of(turn.point, ls2)\r
+ &&\r
+ ( boost::size(ls1) != 2\r
+ || boost::size(ls2) != 2\r
+ || ! have_same_boundary_points(ls1, ls2) );\r
+ }\r
+\r
+private:\r
+ MultiLinestring const& m_multilinestring;\r
+};\r
+\r
+\r
+template <typename Linear>\r
+inline bool has_self_intersections(Linear const& linear)\r
+{\r
+ typedef typename point_type<Linear>::type point_type;\r
+\r
+ // compute self turns\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ point_type,\r
+ geometry::segment_ratio\r
+ <\r
+ typename geometry::coordinate_type<point_type>::type\r
+ >\r
+ > turn_info;\r
+\r
+ std::deque<turn_info> turns;\r
+\r
+ typedef detail::overlay::get_turn_info\r
+ <\r
+ detail::disjoint::assign_disjoint_policy\r
+ > turn_policy;\r
+\r
+ is_acceptable_turn<Linear> predicate(linear);\r
+ detail::overlay::predicate_based_interrupt_policy\r
+ <\r
+ is_acceptable_turn<Linear>\r
+ > interrupt_policy(predicate);\r
+\r
+ detail::self_get_turn_points::get_turns\r
+ <\r
+ turn_policy\r
+ >::apply(linear,\r
+ detail::no_rescale_policy(),\r
+ turns,\r
+ interrupt_policy);\r
+\r
+ detail::is_valid::debug_print_turns(turns.begin(), turns.end());\r
+ debug_print_boundary_points(linear);\r
+\r
+ return interrupt_policy.has_intersections;\r
+}\r
+\r
+\r
+template <typename Linestring, bool CheckSelfIntersections = true>\r
+struct is_simple_linestring\r
+{\r
+ static inline bool apply(Linestring const& linestring)\r
+ {\r
+ simplicity_failure_policy policy;\r
+ return ! boost::empty(linestring)\r
+ && ! detail::is_valid::has_duplicates\r
+ <\r
+ Linestring, closed\r
+ >::apply(linestring, policy)\r
+ && ! detail::is_valid::has_spikes\r
+ <\r
+ Linestring, closed\r
+ >::apply(linestring, policy)\r
+ && ! (CheckSelfIntersections && has_self_intersections(linestring));\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct is_simple_multilinestring\r
+{\r
+ static inline bool apply(MultiLinestring const& multilinestring)\r
+ {\r
+ // check each of the linestrings for simplicity\r
+ // but do not compute self-intersections yet; these will be\r
+ // computed for the entire multilinestring\r
+ if ( ! detail::check_iterator_range\r
+ <\r
+ is_simple_linestring\r
+ <\r
+ typename boost::range_value<MultiLinestring>::type,\r
+ false // do not compute self-intersections\r
+ >,\r
+ true // allow empty multilinestring\r
+ >::apply(boost::begin(multilinestring),\r
+ boost::end(multilinestring))\r
+ )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return ! has_self_intersections(multilinestring);\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::is_simple\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+// A linestring is a curve.\r
+// A curve is simple if it does not pass through the same point twice,\r
+// with the possible exception of its two endpoints\r
+//\r
+// Reference: OGC 06-103r4 (6.1.6.1)\r
+template <typename Linestring>\r
+struct is_simple<Linestring, linestring_tag>\r
+ : detail::is_simple::is_simple_linestring<Linestring>\r
+{};\r
+\r
+\r
+// A MultiLinestring is a MultiCurve\r
+// A MultiCurve is simple if all of its elements are simple and the\r
+// only intersections between any two elements occur at Points that\r
+// are on the boundaries of both elements.\r
+//\r
+// Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)\r
+template <typename MultiLinestring>\r
+struct is_simple<MultiLinestring, multi_linestring_tag>\r
+ : detail::is_simple::is_simple_multilinestring<MultiLinestring>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_MULTIPOINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_MULTIPOINT_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_simple.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_simple\r
+{\r
+\r
+\r
+template <typename MultiPoint>\r
+struct is_simple_multipoint\r
+{\r
+ static inline bool apply(MultiPoint const& multipoint)\r
+ {\r
+ if (boost::empty(multipoint))\r
+ {\r
+ return true;\r
+ }\r
+\r
+ MultiPoint mp(multipoint);\r
+ std::sort(boost::begin(mp), boost::end(mp),\r
+ geometry::less<typename point_type<MultiPoint>::type>());\r
+\r
+ simplicity_failure_policy policy;\r
+ return !detail::is_valid::has_duplicates\r
+ <\r
+ MultiPoint, closed\r
+ >::apply(mp, policy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_simple\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A MultiPoint is simple if no two Points in the MultiPoint are equal\r
+// (have identical coordinate values in X and Y)\r
+//\r
+// Reference: OGC 06-103r4 (6.1.5)\r
+template <typename MultiPoint>\r
+struct is_simple<MultiPoint, multi_point_tag>\r
+ : detail::is_simple::is_simple_multipoint<MultiPoint>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_MULTIPOINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+template <typename Box, std::size_t I>\r
+struct has_valid_corners\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Box const& box, VisitPolicy& visitor)\r
+ {\r
+ if (math::equals(geometry::get<geometry::min_corner, I-1>(box),\r
+ geometry::get<geometry::max_corner, I-1>(box)))\r
+ {\r
+ return\r
+ visitor.template apply<failure_wrong_topological_dimension>();\r
+ }\r
+ else if (geometry::get<geometry::min_corner, I-1>(box)\r
+ >\r
+ geometry::get<geometry::max_corner, I-1>(box))\r
+ {\r
+ return visitor.template apply<failure_wrong_corner_order>();\r
+ }\r
+ return has_valid_corners<Box, I-1>::apply(box, visitor);\r
+ }\r
+};\r
+\r
+\r
+template <typename Box>\r
+struct has_valid_corners<Box, 0>\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Box const&, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+};\r
+\r
+\r
+template <typename Box>\r
+struct is_valid_box\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Box const& box, VisitPolicy& visitor)\r
+ {\r
+ return\r
+ ! has_invalid_coordinate<Box>::apply(box, visitor)\r
+ &&\r
+ has_valid_corners<Box, dimension<Box>::value>::apply(box, visitor);\r
+ }\r
+};\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A box is always simple\r
+// A box is a Polygon, and it satisfies the conditions for Polygon validity.\r
+//\r
+// The only thing we have to check is whether the max corner lies in\r
+// the upper-right quadrant as defined by the min corner\r
+//\r
+// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)\r
+template <typename Box>\r
+struct is_valid<Box, box_tag>\r
+ : detail::is_valid::is_valid_box<Box>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <set>\r
+#include <stack>\r
+#include <utility>\r
+#include <vector>\r
+\r
+#include <boost/core/addressof.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+template <typename TurnPoint>\r
+class complement_graph_vertex\r
+{\r
+public:\r
+ complement_graph_vertex(std::size_t id)\r
+ : m_id(id)\r
+ , m_turn_point(NULL)\r
+ {}\r
+\r
+ complement_graph_vertex(TurnPoint const* turn_point,\r
+ std::size_t expected_id)\r
+ : m_id(expected_id)\r
+ , m_turn_point(turn_point)\r
+ {}\r
+\r
+ inline std::size_t id() const { return m_id; }\r
+\r
+ inline bool operator<(complement_graph_vertex const& other) const\r
+ {\r
+ if ( m_turn_point != NULL && other.m_turn_point != NULL )\r
+ {\r
+ return geometry::less\r
+ <\r
+ TurnPoint\r
+ >()(*m_turn_point, *other.m_turn_point);\r
+ }\r
+ if ( m_turn_point == NULL && other.m_turn_point == NULL )\r
+ {\r
+ return m_id < other.m_id;\r
+ }\r
+ return m_turn_point == NULL;\r
+ }\r
+\r
+private:\r
+ // the value of m_turn_point determines the type of the vertex\r
+ // non-NULL: vertex corresponds to an IP\r
+ // NULL : vertex corresponds to a hole or outer space, and the id\r
+ // is the ring id of the corresponding ring of the polygon\r
+ std::size_t m_id;\r
+ TurnPoint const* m_turn_point;\r
+};\r
+\r
+\r
+\r
+\r
+template <typename TurnPoint>\r
+class complement_graph\r
+{\r
+private:\r
+ typedef complement_graph_vertex<TurnPoint> vertex;\r
+ typedef std::set<vertex> vertex_container;\r
+\r
+public:\r
+ typedef typename vertex_container::const_iterator vertex_handle;\r
+\r
+private:\r
+ struct vertex_handle_less\r
+ {\r
+ inline bool operator()(vertex_handle v1, vertex_handle v2) const\r
+ {\r
+ return v1->id() < v2->id();\r
+ }\r
+ };\r
+\r
+ typedef std::set<vertex_handle, vertex_handle_less> neighbor_container;\r
+\r
+ class has_cycles_dfs_data\r
+ {\r
+ public:\r
+ has_cycles_dfs_data(std::size_t num_nodes)\r
+ : m_visited(num_nodes, false)\r
+ , m_parent_id(num_nodes, -1)\r
+ {}\r
+\r
+ inline signed_size_type parent_id(vertex_handle v) const\r
+ {\r
+ return m_parent_id[v->id()];\r
+ }\r
+\r
+ inline void set_parent_id(vertex_handle v, signed_size_type id)\r
+ {\r
+ m_parent_id[v->id()] = id;\r
+ }\r
+\r
+ inline bool visited(vertex_handle v) const\r
+ {\r
+ return m_visited[v->id()];\r
+ }\r
+\r
+ inline void set_visited(vertex_handle v, bool value)\r
+ {\r
+ m_visited[v->id()] = value;\r
+ }\r
+ private:\r
+ std::vector<bool> m_visited;\r
+ std::vector<signed_size_type> m_parent_id;\r
+ };\r
+\r
+\r
+ inline bool has_cycles(vertex_handle start_vertex,\r
+ has_cycles_dfs_data& data) const\r
+ {\r
+ std::stack<vertex_handle> stack;\r
+ stack.push(start_vertex);\r
+\r
+ while ( !stack.empty() )\r
+ {\r
+ vertex_handle v = stack.top();\r
+ stack.pop();\r
+\r
+ data.set_visited(v, true);\r
+ for (typename neighbor_container::const_iterator nit\r
+ = m_neighbors[v->id()].begin();\r
+ nit != m_neighbors[v->id()].end(); ++nit)\r
+ {\r
+ if ( static_cast<signed_size_type>((*nit)->id()) != data.parent_id(v) )\r
+ {\r
+ if ( data.visited(*nit) )\r
+ {\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ data.set_parent_id(*nit, static_cast<signed_size_type>(v->id()));\r
+ stack.push(*nit);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+public:\r
+ // num_rings: total number of rings, including the exterior ring\r
+ complement_graph(std::size_t num_rings)\r
+ : m_num_rings(num_rings)\r
+ , m_num_turns(0)\r
+ , m_vertices()\r
+ , m_neighbors(num_rings)\r
+ {}\r
+\r
+ // inserts a ring vertex in the graph and returns its handle\r
+ // ring id's are zero-based (so the first interior ring has id 1)\r
+ inline vertex_handle add_vertex(signed_size_type id)\r
+ {\r
+ return m_vertices.insert(vertex(static_cast<std::size_t>(id))).first;\r
+ }\r
+\r
+ // inserts an IP in the graph and returns its id\r
+ inline vertex_handle add_vertex(TurnPoint const& turn_point)\r
+ {\r
+ std::pair<vertex_handle, bool> res\r
+ = m_vertices.insert(vertex(boost::addressof(turn_point),\r
+ m_num_rings + m_num_turns)\r
+ );\r
+\r
+ if ( res.second )\r
+ {\r
+ // a new element is inserted\r
+ m_neighbors.push_back(neighbor_container());\r
+ ++m_num_turns;\r
+ }\r
+ return res.first;\r
+ }\r
+\r
+ inline void add_edge(vertex_handle v1, vertex_handle v2)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( v1 != m_vertices.end() );\r
+ BOOST_GEOMETRY_ASSERT( v2 != m_vertices.end() );\r
+ m_neighbors[v1->id()].insert(v2);\r
+ m_neighbors[v2->id()].insert(v1);\r
+ }\r
+\r
+ inline bool has_cycles() const\r
+ {\r
+ // initialize all vertices as non-visited and with no parent set\r
+ // this is done by the constructor of has_cycles_dfs_data\r
+ has_cycles_dfs_data data(m_num_rings + m_num_turns);\r
+\r
+ // for each non-visited vertex, start a DFS from that vertex\r
+ for (vertex_handle it = m_vertices.begin();\r
+ it != m_vertices.end(); ++it)\r
+ {\r
+ if ( !data.visited(it) && has_cycles(it, data) )\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ template <typename OStream, typename TP>\r
+ friend inline\r
+ void debug_print_complement_graph(OStream&, complement_graph<TP> const&);\r
+\r
+private:\r
+ std::size_t m_num_rings, m_num_turns;\r
+ vertex_container m_vertices;\r
+ std::vector<neighbor_container> m_neighbors;\r
+};\r
+\r
+\r
+}} // namespace detail::is_valid\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_COMPLEMENT_GRAPH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_COMPLEMENT_GRAPH_HPP\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+#include <iostream>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+template <typename OutputStream, typename TurnPoint>\r
+inline void\r
+debug_print_complement_graph(OutputStream& os,\r
+ complement_graph<TurnPoint> const& graph)\r
+{\r
+ typedef typename complement_graph<TurnPoint>::vertex_handle vertex_handle;\r
+\r
+ os << "num rings: " << graph.m_num_rings << std::endl;\r
+ os << "vertex ids: {";\r
+ for (vertex_handle it = graph.m_vertices.begin();\r
+ it != graph.m_vertices.end(); ++it)\r
+ {\r
+ os << " " << it->id();\r
+ }\r
+ os << " }" << std::endl; \r
+\r
+ for (vertex_handle it = graph.m_vertices.begin();\r
+ it != graph.m_vertices.end(); ++it)\r
+ {\r
+ os << "neighbors of " << it->id() << ": {";\r
+ for (typename complement_graph\r
+ <\r
+ TurnPoint\r
+ >::neighbor_container::const_iterator\r
+ nit = graph.m_neighbors[it->id()].begin();\r
+ nit != graph.m_neighbors[it->id()].end(); ++nit)\r
+ {\r
+ os << " " << (*nit)->id();\r
+ }\r
+ os << "}" << std::endl; \r
+ }\r
+}\r
+#else\r
+template <typename OutputStream, typename TurnPoint>\r
+inline void debug_print_complement_graph(OutputStream&,\r
+ complement_graph<TurnPoint> const&)\r
+{\r
+}\r
+#endif\r
+\r
+\r
+}} // namespace detail::is_valid\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+#include <iostream>\r
+\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+template <typename Turn>\r
+inline void debug_print_turn(Turn const& turn)\r
+{\r
+ std::cout << " ["\r
+ << geometry::method_char(turn.method)\r
+ << ","\r
+ << geometry::operation_char(turn.operations[0].operation)\r
+ << "/"\r
+ << geometry::operation_char(turn.operations[1].operation)\r
+ << " {"\r
+ << turn.operations[0].seg_id.multi_index\r
+ << ", "\r
+ << turn.operations[1].seg_id.multi_index\r
+ << "} {"\r
+ << turn.operations[0].seg_id.ring_index\r
+ << ", "\r
+ << turn.operations[1].seg_id.ring_index\r
+ << "} {"\r
+ << turn.operations[0].seg_id.segment_index\r
+ << ", "\r
+ << turn.operations[1].seg_id.segment_index\r
+ << "} "\r
+ << geometry::dsv(turn.point)\r
+ << "]";\r
+}\r
+\r
+template <typename TurnIterator>\r
+inline void debug_print_turns(TurnIterator first, TurnIterator beyond)\r
+{\r
+ std::cout << "turns:";\r
+ for (TurnIterator tit = first; tit != beyond; ++tit)\r
+ {\r
+ debug_print_turn(*tit);\r
+ }\r
+ std::cout << std::endl << std::endl;\r
+}\r
+#else\r
+template <typename Turn>\r
+inline void debug_print_turn(Turn const&)\r
+{}\r
+\r
+template <typename TurnIterator>\r
+inline void debug_print_turns(TurnIterator, TurnIterator)\r
+{}\r
+#endif // BOOST_GEOMETRY_TEST_DEBUG\r
+\r
+}} // namespace detail::is_valid\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP\r
+\r
+#ifdef GEOMETRY_TEST_DEBUG\r
+#include <iostream>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct debug_validity_phase\r
+{\r
+ static inline void apply(int)\r
+ {\r
+ }\r
+};\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+template <typename Polygon>\r
+struct debug_validity_phase<Polygon, polygon_tag>\r
+{\r
+ static inline void apply(int phase)\r
+ {\r
+ switch (phase)\r
+ {\r
+ case 1:\r
+ std::cout << "checking exterior ring..." << std::endl;\r
+ break;\r
+ case 2:\r
+ std::cout << "checking interior rings..." << std::endl;\r
+ break;\r
+ case 3:\r
+ std::cout << "computing and analyzing turns..." << std::endl;\r
+ break;\r
+ case 4:\r
+ std::cout << "checking if interior rings are inside "\r
+ << "the exterior ring..." << std::endl;\r
+ break;\r
+ case 5:\r
+ std::cout << "checking connectivity of interior..." << std::endl;\r
+ break;\r
+ }\r
+ }\r
+};\r
+#endif\r
+\r
+}} // namespace detail::is_valid\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+\r
+#include <boost/geometry/policies/compare.hpp>\r
+#include <boost/geometry/policies/is_valid/default_policy.hpp>\r
+\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+template <typename Range, closure_selector Closure>\r
+struct has_duplicates\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Range const& range, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ typedef typename closeable_view<Range const, Closure>::type view_type;\r
+ typedef typename boost::range_const_iterator\r
+ <\r
+ view_type const\r
+ >::type const_iterator;\r
+\r
+ view_type view(range);\r
+\r
+ if ( boost::size(view) < 2 )\r
+ {\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+\r
+ geometry::equal_to<typename boost::range_value<Range>::type> equal;\r
+\r
+ const_iterator it = boost::const_begin(view);\r
+ const_iterator next = it;\r
+ ++next;\r
+ for (; next != boost::const_end(view); ++it, ++next)\r
+ {\r
+ if ( equal(*it, *next) )\r
+ {\r
+ return ! visitor.template apply<failure_duplicate_points>(*it);\r
+ }\r
+ }\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_INVALID_COORDINATE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_INVALID_COORDINATE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/util/has_non_finite_coordinate.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ \r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+struct always_valid\r
+{\r
+ template <typename Geometry, typename VisitPolicy>\r
+ static inline bool apply(Geometry const&, VisitPolicy& visitor)\r
+ {\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+};\r
+\r
+struct point_has_invalid_coordinate\r
+{\r
+ template <typename Point, typename VisitPolicy>\r
+ static inline bool apply(Point const& point, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ return\r
+ geometry::has_non_finite_coordinate(point)\r
+ ?\r
+ (! visitor.template apply<failure_invalid_coordinate>())\r
+ :\r
+ (! visitor.template apply<no_failure>());\r
+ }\r
+\r
+ template <typename Point>\r
+ static inline bool apply(Point const& point)\r
+ {\r
+ return geometry::has_non_finite_coordinate(point);\r
+ }\r
+};\r
+\r
+struct indexed_has_invalid_coordinate\r
+{\r
+ template <typename Geometry, typename VisitPolicy>\r
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)\r
+ {\r
+ geometry::detail::indexed_point_view<Geometry const, 0> p0(geometry);\r
+ geometry::detail::indexed_point_view<Geometry const, 1> p1(geometry);\r
+\r
+ return point_has_invalid_coordinate::apply(p0, visitor)\r
+ || point_has_invalid_coordinate::apply(p1, visitor);\r
+ }\r
+};\r
+\r
+\r
+struct range_has_invalid_coordinate\r
+{\r
+ struct point_has_valid_coordinates\r
+ {\r
+ template <typename Point>\r
+ static inline bool apply(Point const& point)\r
+ {\r
+ return ! point_has_invalid_coordinate::apply(point);\r
+ }\r
+ };\r
+\r
+ template <typename Geometry, typename VisitPolicy>\r
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ bool const has_valid_coordinates = detail::check_iterator_range\r
+ <\r
+ point_has_valid_coordinates,\r
+ true // do not consider an empty range as problematic\r
+ >::apply(geometry::points_begin(geometry),\r
+ geometry::points_end(geometry));\r
+\r
+ return has_valid_coordinates\r
+ ?\r
+ (! visitor.template apply<no_failure>())\r
+ :\r
+ (! visitor.template apply<failure_invalid_coordinate>());\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type,\r
+ bool HasFloatingPointCoordinates = boost::is_floating_point\r
+ <\r
+ typename coordinate_type<Geometry>::type\r
+ >::value\r
+>\r
+struct has_invalid_coordinate\r
+ : range_has_invalid_coordinate\r
+{};\r
+\r
+template <typename Geometry, typename Tag>\r
+struct has_invalid_coordinate<Geometry, Tag, false>\r
+ : always_valid\r
+{};\r
+\r
+template <typename Point>\r
+struct has_invalid_coordinate<Point, point_tag, true>\r
+ : point_has_invalid_coordinate\r
+{};\r
+\r
+template <typename Segment>\r
+struct has_invalid_coordinate<Segment, segment_tag, true>\r
+ : indexed_has_invalid_coordinate\r
+{};\r
+\r
+template <typename Box>\r
+struct has_invalid_coordinate<Box, box_tag, true>\r
+ : indexed_has_invalid_coordinate\r
+{};\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_INVALID_COORDINATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/policies/is_valid/default_policy.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+template <typename Point>\r
+struct equal_to\r
+{\r
+ Point const& m_point;\r
+\r
+ equal_to(Point const& point)\r
+ : m_point(point)\r
+ {}\r
+\r
+ template <typename OtherPoint>\r
+ inline bool operator()(OtherPoint const& other) const\r
+ {\r
+ return geometry::equals(m_point, other);\r
+ }\r
+};\r
+\r
+template <typename Point>\r
+struct not_equal_to\r
+{\r
+ Point const& m_point;\r
+\r
+ not_equal_to(Point const& point)\r
+ : m_point(point)\r
+ {}\r
+\r
+ template <typename OtherPoint>\r
+ inline bool operator()(OtherPoint const& other) const\r
+ {\r
+ return ! geometry::equals(other, m_point);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename Range, closure_selector Closure>\r
+struct has_spikes\r
+{\r
+ template <typename Iterator>\r
+ static inline Iterator find_different_from_first(Iterator first,\r
+ Iterator last)\r
+ {\r
+ typedef not_equal_to<typename point_type<Range>::type> not_equal;\r
+\r
+ BOOST_GEOMETRY_ASSERT(first != last);\r
+\r
+ Iterator second = first;\r
+ ++second;\r
+ return std::find_if(second, last, not_equal(*first));\r
+ }\r
+\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Range const& range, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ typedef typename closeable_view<Range const, Closure>::type view_type;\r
+ typedef typename boost::range_iterator<view_type const>::type iterator; \r
+\r
+ bool const is_linear\r
+ = boost::is_same<typename tag<Range>::type, linestring_tag>::value;\r
+\r
+ view_type const view(range);\r
+\r
+ iterator prev = boost::begin(view);\r
+\r
+ iterator cur = find_different_from_first(prev, boost::end(view));\r
+ if (cur == boost::end(view))\r
+ {\r
+ // the range has only one distinct point, so it\r
+ // cannot have a spike\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+\r
+ iterator next = find_different_from_first(cur, boost::end(view));\r
+ if (next == boost::end(view))\r
+ {\r
+ // the range has only two distinct points, so it\r
+ // cannot have a spike\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+\r
+ while (next != boost::end(view))\r
+ {\r
+ if ( geometry::detail::point_is_spike_or_equal(*prev,\r
+ *next,\r
+ *cur) )\r
+ {\r
+ return\r
+ ! visitor.template apply<failure_spikes>(is_linear, *cur);\r
+ }\r
+ prev = cur;\r
+ cur = next;\r
+ next = find_different_from_first(cur, boost::end(view));\r
+ }\r
+\r
+ if (geometry::equals(range::front(view), range::back(view)))\r
+ {\r
+ iterator cur = boost::begin(view);\r
+ typename boost::range_reverse_iterator\r
+ <\r
+ view_type const\r
+ >::type prev = find_different_from_first(boost::rbegin(view),\r
+ boost::rend(view));\r
+\r
+ iterator next = find_different_from_first(cur, boost::end(view));\r
+ if (detail::point_is_spike_or_equal(*prev, *next, *cur))\r
+ {\r
+ return\r
+ ! visitor.template apply<failure_spikes>(is_linear, *cur);\r
+ }\r
+ else\r
+ {\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+ }\r
+\r
+ return ! visitor.template apply<no_failure>();\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP\r
+\r
+#include <vector>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/policies/predicate_based_interrupt_policy.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename IsAcceptableTurn = is_acceptable_turn<Geometry>\r
+>\r
+class has_valid_self_turns\r
+{\r
+private:\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ typedef typename geometry::rescale_policy_type\r
+ <\r
+ point_type\r
+ >::type rescale_policy_type;\r
+\r
+ typedef detail::overlay::get_turn_info\r
+ <\r
+ detail::overlay::assign_null_policy\r
+ > turn_policy;\r
+\r
+public:\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ point_type,\r
+ typename geometry::segment_ratio_type\r
+ <\r
+ point_type,\r
+ rescale_policy_type\r
+ >::type\r
+ > turn_type;\r
+\r
+ // returns true if all turns are valid\r
+ template <typename Turns, typename VisitPolicy>\r
+ static inline bool apply(Geometry const& geometry,\r
+ Turns& turns,\r
+ VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry);\r
+\r
+ detail::overlay::stateless_predicate_based_interrupt_policy\r
+ <\r
+ IsAcceptableTurn\r
+ > interrupt_policy;\r
+\r
+ geometry::self_turns<turn_policy>(geometry,\r
+ robust_policy,\r
+ turns,\r
+ interrupt_policy);\r
+\r
+ if (interrupt_policy.has_intersections)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(! boost::empty(turns));\r
+ return visitor.template apply<failure_self_intersections>(turns);\r
+ }\r
+ else\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ }\r
+\r
+ // returns true if all turns are valid\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)\r
+ {\r
+ std::vector<turn_type> turns;\r
+ return apply(geometry, turns, visitor);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IMPLEMENTATION_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/pointlike.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/linear.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/polygon.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/multipolygon.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/ring.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/segment.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/box.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP\r
+\r
+#include <sstream>\r
+#include <string>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+#include <boost/geometry/policies/is_valid/default_policy.hpp>\r
+#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>\r
+#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct is_valid\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)\r
+ {\r
+ concepts::check<Geometry const>();\r
+ return dispatch::is_valid<Geometry>::apply(geometry, visitor);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename VisitPolicy>\r
+ struct visitor : boost::static_visitor<bool>\r
+ {\r
+ visitor(VisitPolicy& policy) : m_policy(policy) {}\r
+\r
+ template <typename Geometry>\r
+ bool operator()(Geometry const& geometry) const\r
+ {\r
+ return is_valid<Geometry>::apply(geometry, m_policy);\r
+ }\r
+\r
+ VisitPolicy& m_policy;\r
+ };\r
+\r
+ template <typename VisitPolicy>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ VisitPolicy& policy_visitor)\r
+ {\r
+ return boost::apply_visitor(visitor<VisitPolicy>(policy_visitor),\r
+ geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+// Undocumented for now\r
+template <typename Geometry, typename VisitPolicy>\r
+inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor)\r
+{\r
+ return resolve_variant::is_valid<Geometry>::apply(geometry, visitor);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_check{is valid (in the OGC sense)}\r
+\ingroup is_valid\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_check{is valid (in the OGC sense);\r
+ furthermore, the following geometries are considered valid:\r
+ multi-geometries with no elements,\r
+ linear geometries containing spikes,\r
+ areal geometries with duplicate (consecutive) points}\r
+\r
+\qbk{[include reference/algorithms/is_valid.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool is_valid(Geometry const& geometry)\r
+{\r
+ is_valid_default_policy<> policy_visitor;\r
+ return geometry::is_valid(geometry, policy_visitor);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_check{is valid (in the OGC sense)}\r
+\ingroup is_valid\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\param failure An enumeration value indicating that the geometry is\r
+ valid or not, and if not valid indicating the reason why\r
+\return \return_check{is valid (in the OGC sense);\r
+ furthermore, the following geometries are considered valid:\r
+ multi-geometries with no elements,\r
+ linear geometries containing spikes,\r
+ areal geometries with duplicate (consecutive) points}\r
+\r
+\qbk{distinguish,with failure value}\r
+\qbk{[include reference/algorithms/is_valid_with_failure.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool is_valid(Geometry const& geometry, validity_failure_type& failure)\r
+{\r
+ failure_type_policy<> policy_visitor;\r
+ bool result = geometry::is_valid(geometry, policy_visitor);\r
+ failure = policy_visitor.failure();\r
+ return result;\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_check{is valid (in the OGC sense)}\r
+\ingroup is_valid\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\param message A string containing a message stating if the geometry\r
+ is valid or not, and if not valid a reason why\r
+\return \return_check{is valid (in the OGC sense);\r
+ furthermore, the following geometries are considered valid:\r
+ multi-geometries with no elements,\r
+ linear geometries containing spikes,\r
+ areal geometries with duplicate (consecutive) points}\r
+\r
+\qbk{distinguish,with message}\r
+\qbk{[include reference/algorithms/is_valid_with_message.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool is_valid(Geometry const& geometry, std::string& message)\r
+{\r
+ std::ostringstream stream;\r
+ failing_reason_policy<> policy_visitor(stream);\r
+ bool result = geometry::is_valid(geometry, policy_visitor);\r
+ message = stream.str();\r
+ return result;\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ order_selector Order = geometry::point_order<Geometry>::value,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct acceptable_operation\r
+{};\r
+\r
+template <typename Polygon>\r
+struct acceptable_operation<Polygon, counterclockwise, polygon_tag>\r
+{\r
+ static const detail::overlay::operation_type value =\r
+ detail::overlay::operation_union;\r
+};\r
+\r
+template <typename Polygon>\r
+struct acceptable_operation<Polygon, clockwise, polygon_tag>\r
+{\r
+ static const detail::overlay::operation_type value =\r
+ detail::overlay::operation_intersection;\r
+};\r
+\r
+template <typename MultiPolygon>\r
+struct acceptable_operation<MultiPolygon, counterclockwise, multi_polygon_tag>\r
+{\r
+ static const detail::overlay::operation_type value =\r
+ detail::overlay::operation_intersection;\r
+};\r
+\r
+template <typename MultiPolygon>\r
+struct acceptable_operation<MultiPolygon, clockwise, multi_polygon_tag>\r
+{\r
+ static const detail::overlay::operation_type value =\r
+ detail::overlay::operation_union;\r
+};\r
+\r
+\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct is_acceptable_turn\r
+{};\r
+\r
+template <typename Ring>\r
+struct is_acceptable_turn<Ring, ring_tag>\r
+{\r
+ template <typename Turn>\r
+ static inline bool apply(Turn const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Polygon>\r
+class is_acceptable_turn<Polygon, polygon_tag>\r
+{\r
+protected:\r
+ template <typename Turn, typename Method, typename Operation>\r
+ static inline bool check_turn(Turn const& turn,\r
+ Method method,\r
+ Operation operation)\r
+ {\r
+ return turn.method == method\r
+ && turn.operations[0].operation == operation\r
+ && turn.operations[1].operation == operation;\r
+ }\r
+\r
+\r
+public:\r
+ template <typename Turn>\r
+ static inline bool apply(Turn const& turn)\r
+ {\r
+ using namespace detail::overlay;\r
+\r
+ if ( turn.operations[0].seg_id.ring_index\r
+ == turn.operations[1].seg_id.ring_index )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ operation_type const op = acceptable_operation<Polygon>::value;\r
+\r
+ return check_turn(turn, method_touch_interior, op)\r
+ || check_turn(turn, method_touch, op)\r
+ ;\r
+ }\r
+};\r
+\r
+template <typename MultiPolygon>\r
+class is_acceptable_turn<MultiPolygon, multi_polygon_tag>\r
+ : is_acceptable_turn<typename boost::range_value<MultiPolygon>::type>\r
+{\r
+private:\r
+ typedef typename boost::range_value<MultiPolygon>::type polygon;\r
+ typedef is_acceptable_turn<polygon> base;\r
+\r
+public:\r
+ template <typename Turn>\r
+ static inline bool apply(Turn const& turn)\r
+ {\r
+ using namespace detail::overlay;\r
+\r
+ if ( turn.operations[0].seg_id.multi_index\r
+ == turn.operations[1].seg_id.multi_index )\r
+ {\r
+ return base::apply(turn);\r
+ }\r
+\r
+ operation_type const op = acceptable_operation<MultiPolygon>::value;\r
+\r
+ return base::check_turn(turn, method_touch_interior, op)\r
+ || base::check_turn(turn, method_touch, op)\r
+ ;\r
+ }\r
+}; \r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>\r
+#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+template <typename Linestring>\r
+struct is_valid_linestring\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Linestring const& linestring,\r
+ VisitPolicy& visitor)\r
+ {\r
+ if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (boost::size(linestring) < 2)\r
+ {\r
+ return visitor.template apply<failure_few_points>();\r
+ }\r
+\r
+ std::size_t num_distinct = detail::num_distinct_consecutive_points\r
+ <\r
+ Linestring,\r
+ 3u,\r
+ true,\r
+ not_equal_to<typename point_type<Linestring>::type>\r
+ >::apply(linestring);\r
+\r
+ if (num_distinct < 2u)\r
+ {\r
+ return\r
+ visitor.template apply<failure_wrong_topological_dimension>();\r
+ }\r
+\r
+ if (num_distinct == 2u)\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ return ! has_spikes<Linestring, closed>::apply(linestring, visitor);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A linestring is a curve.\r
+// A curve is 1-dimensional so it has to have at least two distinct\r
+// points.\r
+// A curve is simple if it does not pass through the same point twice,\r
+// with the possible exception of its two endpoints\r
+//\r
+// There is an option here as to whether spikes are allowed for linestrings; \r
+// here we pass this as an additional template parameter: allow_spikes\r
+// If allow_spikes is set to true, spikes are allowed, false otherwise.\r
+// By default, spikes are disallowed\r
+//\r
+// Reference: OGC 06-103r4 (6.1.6.1)\r
+template <typename Linestring, bool AllowEmptyMultiGeometries>\r
+struct is_valid\r
+ <\r
+ Linestring, linestring_tag, AllowEmptyMultiGeometries\r
+ > : detail::is_valid::is_valid_linestring<Linestring>\r
+{};\r
+\r
+\r
+// A MultiLinestring is a MultiCurve\r
+// A MultiCurve is simple if all of its elements are simple and the\r
+// only intersections between any two elements occur at Points that\r
+// are on the boundaries of both elements.\r
+//\r
+// Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)\r
+template <typename MultiLinestring, bool AllowEmptyMultiGeometries>\r
+class is_valid\r
+ <\r
+ MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries\r
+ >\r
+{\r
+private:\r
+ template <typename VisitPolicy>\r
+ struct per_linestring\r
+ {\r
+ per_linestring(VisitPolicy& policy) : m_policy(policy) {}\r
+\r
+ template <typename Linestring>\r
+ inline bool apply(Linestring const& linestring) const\r
+ {\r
+ return detail::is_valid::is_valid_linestring\r
+ <\r
+ Linestring\r
+ >::apply(linestring, m_policy);\r
+ }\r
+\r
+ VisitPolicy& m_policy;\r
+ };\r
+\r
+public:\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(MultiLinestring const& multilinestring,\r
+ VisitPolicy& visitor)\r
+ {\r
+ if (BOOST_GEOMETRY_CONDITION(\r
+ AllowEmptyMultiGeometries && boost::empty(multilinestring)))\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+\r
+ return detail::check_iterator_range\r
+ <\r
+ per_linestring<VisitPolicy>,\r
+ false // do not check for empty multilinestring (done above)\r
+ >::apply(boost::begin(multilinestring),\r
+ boost::end(multilinestring),\r
+ per_linestring<VisitPolicy>(visitor));\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTIPOLYGON_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTIPOLYGON_HPP\r
+\r
+#include <deque>\r
+#include <vector>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/iterator/filter_iterator.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/polygon.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+template <typename MultiPolygon, bool AllowEmptyMultiGeometries>\r
+class is_valid_multipolygon\r
+ : is_valid_polygon\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type,\r
+ true // check only the validity of rings\r
+ >\r
+{\r
+private:\r
+ typedef is_valid_polygon\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type,\r
+ true\r
+ > base;\r
+\r
+\r
+\r
+ template\r
+ <\r
+ typename PolygonIterator,\r
+ typename TurnIterator,\r
+ typename VisitPolicy\r
+ >\r
+ static inline\r
+ bool are_polygon_interiors_disjoint(PolygonIterator polygons_first,\r
+ PolygonIterator polygons_beyond,\r
+ TurnIterator turns_first,\r
+ TurnIterator turns_beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ // collect all polygons that have turns\r
+ std::set<signed_size_type> multi_indices;\r
+ for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)\r
+ {\r
+ multi_indices.insert(tit->operations[0].seg_id.multi_index);\r
+ multi_indices.insert(tit->operations[1].seg_id.multi_index);\r
+ }\r
+\r
+ // put polygon iterators without turns in a vector\r
+ std::vector<PolygonIterator> polygon_iterators;\r
+ signed_size_type multi_index = 0;\r
+ for (PolygonIterator it = polygons_first; it != polygons_beyond;\r
+ ++it, ++multi_index)\r
+ {\r
+ if (multi_indices.find(multi_index) == multi_indices.end())\r
+ {\r
+ polygon_iterators.push_back(it);\r
+ }\r
+ }\r
+\r
+ typename base::item_visitor_type item_visitor;\r
+\r
+ geometry::partition\r
+ <\r
+ geometry::model::box<typename point_type<MultiPolygon>::type>,\r
+ typename base::expand_box,\r
+ typename base::overlaps_box\r
+ >::apply(polygon_iterators, item_visitor);\r
+\r
+ if (item_visitor.items_overlap)\r
+ {\r
+ return visitor.template apply<failure_intersecting_interiors>();\r
+ }\r
+ else\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ }\r
+\r
+\r
+\r
+ class has_multi_index\r
+ {\r
+ public:\r
+ has_multi_index(signed_size_type multi_index)\r
+ : m_multi_index(multi_index)\r
+ {}\r
+\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& turn) const\r
+ {\r
+ return turn.operations[0].seg_id.multi_index == m_multi_index\r
+ && turn.operations[1].seg_id.multi_index == m_multi_index;\r
+ }\r
+\r
+ private:\r
+ signed_size_type const m_multi_index;\r
+ };\r
+\r
+\r
+\r
+ template <typename Predicate>\r
+ struct has_property_per_polygon\r
+ {\r
+ template\r
+ <\r
+ typename PolygonIterator,\r
+ typename TurnIterator,\r
+ typename VisitPolicy\r
+ >\r
+ static inline bool apply(PolygonIterator polygons_first,\r
+ PolygonIterator polygons_beyond,\r
+ TurnIterator turns_first,\r
+ TurnIterator turns_beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ signed_size_type multi_index = 0;\r
+ for (PolygonIterator it = polygons_first; it != polygons_beyond;\r
+ ++it, ++multi_index)\r
+ {\r
+ has_multi_index index_predicate(multi_index);\r
+\r
+ typedef boost::filter_iterator\r
+ <\r
+ has_multi_index, TurnIterator\r
+ > filtered_turn_iterator;\r
+\r
+ filtered_turn_iterator filtered_turns_first(index_predicate,\r
+ turns_first,\r
+ turns_beyond);\r
+\r
+ filtered_turn_iterator filtered_turns_beyond(index_predicate,\r
+ turns_beyond,\r
+ turns_beyond);\r
+\r
+ if (! Predicate::apply(*it,\r
+ filtered_turns_first,\r
+ filtered_turns_beyond,\r
+ visitor))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ };\r
+\r
+\r
+\r
+ template\r
+ <\r
+ typename PolygonIterator,\r
+ typename TurnIterator,\r
+ typename VisitPolicy\r
+ >\r
+ static inline bool have_holes_inside(PolygonIterator polygons_first,\r
+ PolygonIterator polygons_beyond,\r
+ TurnIterator turns_first,\r
+ TurnIterator turns_beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ return has_property_per_polygon\r
+ <\r
+ typename base::has_holes_inside\r
+ >::apply(polygons_first, polygons_beyond,\r
+ turns_first, turns_beyond, visitor);\r
+ }\r
+\r
+\r
+\r
+ template\r
+ <\r
+ typename PolygonIterator,\r
+ typename TurnIterator,\r
+ typename VisitPolicy\r
+ >\r
+ static inline bool have_connected_interior(PolygonIterator polygons_first,\r
+ PolygonIterator polygons_beyond,\r
+ TurnIterator turns_first,\r
+ TurnIterator turns_beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ return has_property_per_polygon\r
+ <\r
+ typename base::has_connected_interior\r
+ >::apply(polygons_first, polygons_beyond,\r
+ turns_first, turns_beyond, visitor);\r
+ }\r
+\r
+\r
+ template <typename VisitPolicy>\r
+ struct per_polygon\r
+ {\r
+ per_polygon(VisitPolicy& policy) : m_policy(policy) {}\r
+\r
+ template <typename Polygon>\r
+ inline bool apply(Polygon const& polygon) const\r
+ {\r
+ return base::apply(polygon, m_policy);\r
+ }\r
+\r
+ VisitPolicy& m_policy;\r
+ };\r
+public:\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(MultiPolygon const& multipolygon,\r
+ VisitPolicy& visitor)\r
+ {\r
+ typedef debug_validity_phase<MultiPolygon> debug_phase;\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(\r
+ AllowEmptyMultiGeometries && boost::empty(multipolygon)))\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+\r
+ // check validity of all polygons ring\r
+ debug_phase::apply(1);\r
+\r
+ if (! detail::check_iterator_range\r
+ <\r
+ per_polygon<VisitPolicy>,\r
+ false // do not check for empty multipolygon (done above)\r
+ >::apply(boost::begin(multipolygon),\r
+ boost::end(multipolygon),\r
+ per_polygon<VisitPolicy>(visitor)))\r
+ {\r
+ return false;\r
+ }\r
+\r
+\r
+ // compute turns and check if all are acceptable\r
+ debug_phase::apply(2);\r
+\r
+ typedef has_valid_self_turns<MultiPolygon> has_valid_turns;\r
+\r
+ std::deque<typename has_valid_turns::turn_type> turns;\r
+ bool has_invalid_turns =\r
+ ! has_valid_turns::apply(multipolygon, turns, visitor);\r
+ debug_print_turns(turns.begin(), turns.end());\r
+\r
+ if (has_invalid_turns)\r
+ {\r
+ return false;\r
+ }\r
+\r
+\r
+ // check if each polygon's interior rings are inside the\r
+ // exterior and not one inside the other\r
+ debug_phase::apply(3);\r
+\r
+ if (! have_holes_inside(boost::begin(multipolygon),\r
+ boost::end(multipolygon),\r
+ turns.begin(),\r
+ turns.end(),\r
+ visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+\r
+ // check that each polygon's interior is connected\r
+ debug_phase::apply(4);\r
+\r
+ if (! have_connected_interior(boost::begin(multipolygon),\r
+ boost::end(multipolygon),\r
+ turns.begin(),\r
+ turns.end(),\r
+ visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+\r
+ // check if polygon interiors are disjoint\r
+ debug_phase::apply(5);\r
+ return are_polygon_interiors_disjoint(boost::begin(multipolygon),\r
+ boost::end(multipolygon),\r
+ turns.begin(),\r
+ turns.end(),\r
+ visitor);\r
+ }\r
+};\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// Not clear what the definition is.\r
+// Right now we check that each element is simple (in fact valid), and\r
+// that the MultiPolygon is also valid.\r
+//\r
+// Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14)\r
+template <typename MultiPolygon, bool AllowEmptyMultiGeometries>\r
+struct is_valid\r
+ <\r
+ MultiPolygon, multi_polygon_tag, AllowEmptyMultiGeometries\r
+ > : detail::is_valid::is_valid_multipolygon\r
+ <\r
+ MultiPolygon, AllowEmptyMultiGeometries\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTIPOLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+// A point is always simple\r
+template <typename Point>\r
+struct is_valid<Point, point_tag>\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Point const& point, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+ return ! detail::is_valid::has_invalid_coordinate\r
+ <\r
+ Point\r
+ >::apply(point, visitor);\r
+ }\r
+};\r
+\r
+\r
+\r
+// A MultiPoint is simple if no two Points in the MultiPoint are equal\r
+// (have identical coordinate values in X and Y)\r
+//\r
+// Reference: OGC 06-103r4 (6.1.5)\r
+template <typename MultiPoint, bool AllowEmptyMultiGeometries>\r
+struct is_valid<MultiPoint, multi_point_tag, AllowEmptyMultiGeometries>\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(MultiPoint const& multipoint,\r
+ VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(multipoint, visitor);\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(\r
+ AllowEmptyMultiGeometries || !boost::empty(multipoint)))\r
+ {\r
+ // we allow empty multi-geometries, so an empty multipoint\r
+ // is considered valid\r
+ return ! detail::is_valid::has_invalid_coordinate\r
+ <\r
+ MultiPoint\r
+ >::apply(multipoint, visitor);\r
+ }\r
+ else\r
+ {\r
+ // we do not allow an empty multipoint\r
+ return visitor.template apply<failure_few_points>();\r
+ }\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP\r
+\r
+#include <cstddef>\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+#include <iostream>\r
+#endif // BOOST_GEOMETRY_TEST_DEBUG\r
+\r
+#include <algorithm>\r
+#include <deque>\r
+#include <iterator>\r
+#include <set>\r
+#include <vector>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/complement_graph.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/ring.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp>\r
+\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+template <typename Polygon, bool CheckRingValidityOnly = false>\r
+class is_valid_polygon\r
+{\r
+protected:\r
+ typedef debug_validity_phase<Polygon> debug_phase;\r
+\r
+ template <typename VisitPolicy>\r
+ struct per_ring\r
+ {\r
+ per_ring(VisitPolicy& policy) : m_policy(policy) {}\r
+\r
+ template <typename Ring>\r
+ inline bool apply(Ring const& ring) const\r
+ {\r
+ return detail::is_valid::is_valid_ring\r
+ <\r
+ Ring, false, true\r
+ >::apply(ring, m_policy);\r
+ }\r
+\r
+ VisitPolicy& m_policy;\r
+ };\r
+\r
+ template <typename InteriorRings, typename VisitPolicy>\r
+ static bool has_valid_interior_rings(InteriorRings const& interior_rings,\r
+ VisitPolicy& visitor)\r
+ {\r
+ return\r
+ detail::check_iterator_range\r
+ <\r
+ per_ring<VisitPolicy>,\r
+ true // allow for empty interior ring range\r
+ >::apply(boost::begin(interior_rings),\r
+ boost::end(interior_rings),\r
+ per_ring<VisitPolicy>(visitor));\r
+ }\r
+\r
+ struct has_valid_rings\r
+ {\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)\r
+ {\r
+ typedef typename ring_type<Polygon>::type ring_type;\r
+\r
+ // check validity of exterior ring\r
+ debug_phase::apply(1);\r
+\r
+ if (! detail::is_valid::is_valid_ring\r
+ <\r
+ ring_type,\r
+ false // do not check self intersections\r
+ >::apply(exterior_ring(polygon), visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // check validity of interior rings\r
+ debug_phase::apply(2);\r
+\r
+ return has_valid_interior_rings(geometry::interior_rings(polygon),\r
+ visitor);\r
+ }\r
+ };\r
+\r
+\r
+ // structs for partition -- start\r
+ struct expand_box\r
+ {\r
+ template <typename Box, typename Iterator>\r
+ static inline void apply(Box& total, Iterator const& it)\r
+ {\r
+ geometry::expand(total, geometry::return_envelope<Box>(*it));\r
+ }\r
+\r
+ };\r
+\r
+ struct overlaps_box\r
+ {\r
+ template <typename Box, typename Iterator>\r
+ static inline bool apply(Box const& box, Iterator const& it)\r
+ {\r
+ return ! geometry::disjoint(*it, box);\r
+ }\r
+ };\r
+\r
+\r
+ struct item_visitor_type\r
+ {\r
+ bool items_overlap;\r
+\r
+ item_visitor_type() : items_overlap(false) {}\r
+\r
+ template <typename Item1, typename Item2>\r
+ inline void apply(Item1 const& item1, Item2 const& item2)\r
+ {\r
+ if (! items_overlap\r
+ && (geometry::within(*points_begin(*item1), *item2)\r
+ || geometry::within(*points_begin(*item2), *item1))\r
+ )\r
+ {\r
+ items_overlap = true;\r
+ }\r
+ }\r
+ };\r
+ // structs for partition -- end\r
+\r
+\r
+ template\r
+ <\r
+ typename RingIterator,\r
+ typename ExteriorRing,\r
+ typename TurnIterator,\r
+ typename VisitPolicy\r
+ >\r
+ static inline bool are_holes_inside(RingIterator rings_first,\r
+ RingIterator rings_beyond,\r
+ ExteriorRing const& exterior_ring,\r
+ TurnIterator turns_first,\r
+ TurnIterator turns_beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ // collect the interior ring indices that have turns with the\r
+ // exterior ring\r
+ std::set<signed_size_type> ring_indices;\r
+ for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)\r
+ {\r
+ if (tit->operations[0].seg_id.ring_index == -1)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(tit->operations[1].seg_id.ring_index != -1);\r
+ ring_indices.insert(tit->operations[1].seg_id.ring_index);\r
+ }\r
+ else if (tit->operations[1].seg_id.ring_index == -1)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(tit->operations[0].seg_id.ring_index != -1);\r
+ ring_indices.insert(tit->operations[0].seg_id.ring_index);\r
+ }\r
+ }\r
+\r
+ signed_size_type ring_index = 0;\r
+ for (RingIterator it = rings_first; it != rings_beyond;\r
+ ++it, ++ring_index)\r
+ {\r
+ // do not examine interior rings that have turns with the\r
+ // exterior ring\r
+ if (ring_indices.find(ring_index) == ring_indices.end()\r
+ && ! geometry::covered_by(range::front(*it), exterior_ring))\r
+ {\r
+ return visitor.template apply<failure_interior_rings_outside>();\r
+ }\r
+ }\r
+\r
+ // collect all rings (exterior and/or interior) that have turns\r
+ for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)\r
+ {\r
+ ring_indices.insert(tit->operations[0].seg_id.ring_index);\r
+ ring_indices.insert(tit->operations[1].seg_id.ring_index);\r
+ }\r
+\r
+ // put iterators for interior rings without turns in a vector\r
+ std::vector<RingIterator> ring_iterators;\r
+ ring_index = 0;\r
+ for (RingIterator it = rings_first; it != rings_beyond;\r
+ ++it, ++ring_index)\r
+ {\r
+ if (ring_indices.find(ring_index) == ring_indices.end())\r
+ {\r
+ ring_iterators.push_back(it);\r
+ }\r
+ }\r
+\r
+ // call partition to check is interior rings are disjoint from\r
+ // each other\r
+ item_visitor_type item_visitor;\r
+\r
+ geometry::partition\r
+ <\r
+ geometry::model::box<typename point_type<Polygon>::type>,\r
+ expand_box,\r
+ overlaps_box\r
+ >::apply(ring_iterators, item_visitor);\r
+\r
+ if (item_visitor.items_overlap)\r
+ {\r
+ return visitor.template apply<failure_nested_interior_rings>();\r
+ }\r
+ else\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ typename InteriorRings,\r
+ typename ExteriorRing,\r
+ typename TurnIterator,\r
+ typename VisitPolicy\r
+ >\r
+ static inline bool are_holes_inside(InteriorRings const& interior_rings,\r
+ ExteriorRing const& exterior_ring,\r
+ TurnIterator first,\r
+ TurnIterator beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ return are_holes_inside(boost::begin(interior_rings),\r
+ boost::end(interior_rings),\r
+ exterior_ring,\r
+ first,\r
+ beyond,\r
+ visitor);\r
+ }\r
+\r
+ struct has_holes_inside\r
+ { \r
+ template <typename TurnIterator, typename VisitPolicy>\r
+ static inline bool apply(Polygon const& polygon,\r
+ TurnIterator first,\r
+ TurnIterator beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ return are_holes_inside(geometry::interior_rings(polygon),\r
+ geometry::exterior_ring(polygon),\r
+ first,\r
+ beyond,\r
+ visitor);\r
+ }\r
+ };\r
+\r
+\r
+\r
+\r
+ struct has_connected_interior\r
+ {\r
+ template <typename TurnIterator, typename VisitPolicy>\r
+ static inline bool apply(Polygon const& polygon,\r
+ TurnIterator first,\r
+ TurnIterator beyond,\r
+ VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ typedef typename std::iterator_traits\r
+ <\r
+ TurnIterator\r
+ >::value_type turn_type;\r
+ typedef complement_graph<typename turn_type::point_type> graph;\r
+\r
+ graph g(geometry::num_interior_rings(polygon) + 1);\r
+ for (TurnIterator tit = first; tit != beyond; ++tit)\r
+ {\r
+ typename graph::vertex_handle v1 = g.add_vertex\r
+ ( tit->operations[0].seg_id.ring_index + 1 );\r
+ typename graph::vertex_handle v2 = g.add_vertex\r
+ ( tit->operations[1].seg_id.ring_index + 1 );\r
+ typename graph::vertex_handle vip = g.add_vertex(tit->point);\r
+\r
+ g.add_edge(v1, vip);\r
+ g.add_edge(v2, vip);\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+ debug_print_complement_graph(std::cout, g);\r
+#endif // BOOST_GEOMETRY_TEST_DEBUG\r
+\r
+ if (g.has_cycles())\r
+ {\r
+ return visitor.template apply<failure_disconnected_interior>();\r
+ }\r
+ else\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ }\r
+ };\r
+\r
+public:\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Polygon const& polygon, VisitPolicy& visitor)\r
+ {\r
+ if (! has_valid_rings::apply(polygon, visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(CheckRingValidityOnly))\r
+ {\r
+ return true;\r
+ }\r
+\r
+ // compute turns and check if all are acceptable\r
+ debug_phase::apply(3);\r
+\r
+ typedef has_valid_self_turns<Polygon> has_valid_turns;\r
+\r
+ std::deque<typename has_valid_turns::turn_type> turns;\r
+ bool has_invalid_turns\r
+ = ! has_valid_turns::apply(polygon, turns, visitor);\r
+ debug_print_turns(turns.begin(), turns.end());\r
+\r
+ if (has_invalid_turns)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // check if all interior rings are inside the exterior ring\r
+ debug_phase::apply(4);\r
+\r
+ if (! has_holes_inside::apply(polygon,\r
+ turns.begin(), turns.end(),\r
+ visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // check whether the interior of the polygon is a connected set\r
+ debug_phase::apply(5);\r
+\r
+ return has_connected_interior::apply(polygon,\r
+ turns.begin(),\r
+ turns.end(),\r
+ visitor);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A Polygon is always a simple geometric object provided that it is valid.\r
+//\r
+// Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1)\r
+template <typename Polygon, bool AllowEmptyMultiGeometries>\r
+struct is_valid\r
+ <\r
+ Polygon, polygon_tag, AllowEmptyMultiGeometries\r
+ > : detail::is_valid::is_valid_polygon<Polygon>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP\r
+\r
+#include <deque>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+\r
+#include <boost/geometry/util/order_as_direction.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>\r
+\r
+#include <boost/geometry/strategies/area.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_TEST_DEBUG\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_valid\r
+{\r
+\r
+\r
+// struct to check whether a ring is topologically closed\r
+template <typename Ring, closure_selector Closure /* open */>\r
+struct is_topologically_closed\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Ring const&, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+};\r
+\r
+template <typename Ring>\r
+struct is_topologically_closed<Ring, closed>\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ if (geometry::equals(range::front(ring), range::back(ring)))\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ else\r
+ {\r
+ return visitor.template apply<failure_not_closed>();\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename ResultType, bool IsInteriorRing /* false */>\r
+struct ring_area_predicate\r
+{\r
+ typedef std::greater<ResultType> type;\r
+};\r
+\r
+template <typename ResultType>\r
+struct ring_area_predicate<ResultType, true>\r
+{\r
+ typedef std::less<ResultType> type;\r
+};\r
+\r
+\r
+\r
+template <typename Ring, bool IsInteriorRing>\r
+struct is_properly_oriented\r
+{\r
+ typedef typename point_type<Ring>::type point_type;\r
+\r
+ typedef typename strategy::area::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type,\r
+ point_type\r
+ >::type strategy_type;\r
+\r
+ typedef detail::area::ring_area\r
+ <\r
+ order_as_direction<geometry::point_order<Ring>::value>::value,\r
+ geometry::closure<Ring>::value\r
+ > ring_area_type;\r
+\r
+ typedef typename default_area_result<Ring>::type area_result_type;\r
+\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ typename ring_area_predicate\r
+ <\r
+ area_result_type, IsInteriorRing\r
+ >::type predicate;\r
+\r
+ // Check area\r
+ area_result_type const zero = area_result_type();\r
+ if (predicate(ring_area_type::apply(ring, strategy_type()), zero))\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ else\r
+ {\r
+ return visitor.template apply<failure_wrong_orientation>();\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Ring,\r
+ bool CheckSelfIntersections = true,\r
+ bool IsInteriorRing = false\r
+>\r
+struct is_valid_ring\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Ring const& ring, VisitPolicy& visitor)\r
+ {\r
+ // return invalid if any of the following condition holds:\r
+ // (a) the ring's point coordinates are not invalid (e.g., NaN)\r
+ // (b) the ring's size is below the minimal one\r
+ // (c) the ring consists of at most two distinct points\r
+ // (d) the ring is not topologically closed\r
+ // (e) the ring has spikes\r
+ // (f) the ring has duplicate points (if AllowDuplicates is false)\r
+ // (g) the boundary of the ring has self-intersections\r
+ // (h) the order of the points is inconsistent with the defined order\r
+ //\r
+ // Note: no need to check if the area is zero. If this is the\r
+ // case, then the ring must have at least two spikes, which is\r
+ // checked by condition (d).\r
+\r
+ if (has_invalid_coordinate<Ring>::apply(ring, visitor))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ closure_selector const closure = geometry::closure<Ring>::value;\r
+ typedef typename closeable_view<Ring const, closure>::type view_type;\r
+\r
+ if (boost::size(ring)\r
+ < core_detail::closure::minimum_ring_size<closure>::value)\r
+ {\r
+ return visitor.template apply<failure_few_points>();\r
+ }\r
+\r
+ view_type const view(ring);\r
+ if (detail::num_distinct_consecutive_points\r
+ <\r
+ view_type, 4u, true,\r
+ not_equal_to<typename point_type<Ring>::type>\r
+ >::apply(view)\r
+ < 4u)\r
+ {\r
+ return\r
+ visitor.template apply<failure_wrong_topological_dimension>();\r
+ }\r
+\r
+ return\r
+ is_topologically_closed<Ring, closure>::apply(ring, visitor)\r
+ && ! has_duplicates<Ring, closure>::apply(ring, visitor)\r
+ && ! has_spikes<Ring, closure>::apply(ring, visitor)\r
+ && (! CheckSelfIntersections\r
+ || has_valid_self_turns<Ring>::apply(ring, visitor))\r
+ && is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_valid\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+// A Ring is a Polygon with exterior boundary only.\r
+// The Ring's boundary must be a LinearRing (see OGC 06-103-r4,\r
+// 6.1.7.1, for the definition of LinearRing)\r
+//\r
+// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)\r
+template <typename Ring, bool AllowEmptyMultiGeometries>\r
+struct is_valid\r
+ <\r
+ Ring, ring_tag, AllowEmptyMultiGeometries\r
+ > : detail::is_valid::is_valid_ring<Ring>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>\r
+#include <boost/geometry/algorithms/dispatch/is_valid.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// A segment is a curve.\r
+// A curve is simple if it does not pass through the same point twice,\r
+// with the possible exception of its two endpoints\r
+// A curve is 1-dimensional, hence we have to check is the two\r
+// endpoints of the segment coincide, since in this case it is\r
+// 0-dimensional.\r
+//\r
+// Reference: OGC 06-103r4 (6.1.6.1)\r
+template <typename Segment>\r
+struct is_valid<Segment, segment_tag>\r
+{\r
+ template <typename VisitPolicy>\r
+ static inline bool apply(Segment const& segment, VisitPolicy& visitor)\r
+ {\r
+ boost::ignore_unused(visitor);\r
+\r
+ typename point_type<Segment>::type p[2];\r
+ detail::assign_point_from_index<0>(segment, p[0]);\r
+ detail::assign_point_from_index<1>(segment, p[1]);\r
+\r
+ if (detail::is_valid::has_invalid_coordinate\r
+ <\r
+ Segment\r
+ >::apply(segment, visitor))\r
+ {\r
+ return false;\r
+ }\r
+ else if (! geometry::equals(p[0], p[1]))\r
+ {\r
+ return visitor.template apply<no_failure>();\r
+ }\r
+ else\r
+ {\r
+ return\r
+ visitor.template apply<failure_wrong_topological_dimension>();\r
+ }\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP\r
+\r
+#include <cstddef>\r
+#include <queue>\r
+#include <utility>\r
+#include <vector>\r
+\r
+#include <boost/core/ref.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/algorithms/detail/sweep.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace max_interval_gap\r
+{\r
+\r
+// the class Interval must provide the following:\r
+// * must define the type value_type\r
+// * must define the type difference_type\r
+// * must have the methods:\r
+// value_type get<Index>() const\r
+// difference_type length() const\r
+// where an Index value of 0 (resp., 1) refers to the left (resp.,\r
+// right) endpoint of the interval\r
+\r
+template <typename Interval>\r
+class sweep_event\r
+{\r
+public:\r
+ typedef Interval interval_type;\r
+ typedef typename Interval::value_type time_type;\r
+\r
+ sweep_event(Interval const& interval, bool start_event = true)\r
+ : m_interval(boost::cref(interval))\r
+ , m_start_event(start_event)\r
+ {}\r
+\r
+ inline bool is_start_event() const\r
+ {\r
+ return m_start_event;\r
+ }\r
+\r
+ inline interval_type const& interval() const\r
+ {\r
+ return m_interval;\r
+ }\r
+\r
+ inline time_type time() const\r
+ {\r
+ return (m_start_event)\r
+ ? interval().template get<0>()\r
+ : interval().template get<1>();\r
+ }\r
+\r
+ inline bool operator<(sweep_event const& other) const\r
+ {\r
+ if (! math::equals(time(), other.time()))\r
+ {\r
+ return time() < other.time();\r
+ }\r
+ // a start-event is before an end-event with the same event time\r
+ return is_start_event() && ! other.is_start_event();\r
+ }\r
+\r
+private:\r
+ boost::reference_wrapper<Interval const> m_interval;\r
+ bool m_start_event;\r
+};\r
+\r
+template <typename Event>\r
+struct event_greater\r
+{\r
+ inline bool operator()(Event const& event1, Event const& event2) const\r
+ {\r
+ return event2 < event1;\r
+ }\r
+};\r
+\r
+\r
+struct initialization_visitor\r
+{\r
+ template <typename Range, typename PriorityQueue, typename EventVisitor>\r
+ static inline void apply(Range const& range,\r
+ PriorityQueue& queue,\r
+ EventVisitor&)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(queue.empty());\r
+\r
+ // it is faster to build the queue directly from the entire\r
+ // range, rather than insert elements one after the other\r
+ PriorityQueue pq(boost::begin(range), boost::end(range));\r
+ std::swap(pq, queue);\r
+ }\r
+};\r
+\r
+\r
+template <typename Event>\r
+class event_visitor\r
+{\r
+ typedef typename Event::time_type event_time_type;\r
+ typedef typename Event::interval_type::difference_type difference_type;\r
+\r
+ typedef typename boost::remove_const\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ event_time_type\r
+ >::type\r
+ >::type bare_time_type;\r
+\r
+\r
+public:\r
+ event_visitor()\r
+ : m_overlap_count(0)\r
+ , m_max_gap_left(0)\r
+ , m_max_gap_right(0)\r
+ {}\r
+\r
+ template <typename PriorityQueue>\r
+ inline void apply(Event const& event, PriorityQueue& queue)\r
+ {\r
+ if (event.is_start_event())\r
+ {\r
+ ++m_overlap_count;\r
+ queue.push(Event(event.interval(), false));\r
+ }\r
+ else\r
+ {\r
+ --m_overlap_count;\r
+ if (m_overlap_count == 0 && ! queue.empty())\r
+ {\r
+ // we may have a gap\r
+ BOOST_GEOMETRY_ASSERT(queue.top().is_start_event());\r
+\r
+ event_time_type next_event_time\r
+ = queue.top().interval().template get<0>();\r
+ difference_type gap = next_event_time - event.time();\r
+ if (gap > max_gap())\r
+ {\r
+ m_max_gap_left = event.time();\r
+ m_max_gap_right = next_event_time;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ bare_time_type const& max_gap_left() const\r
+ {\r
+ return m_max_gap_left;\r
+ }\r
+\r
+ bare_time_type const& max_gap_right() const\r
+ {\r
+ return m_max_gap_right;\r
+ }\r
+\r
+ difference_type max_gap() const\r
+ {\r
+ return m_max_gap_right - m_max_gap_left;\r
+ }\r
+\r
+private:\r
+ std::size_t m_overlap_count;\r
+ bare_time_type m_max_gap_left, m_max_gap_right;\r
+};\r
+\r
+}} // namespace detail::max_interval_gap\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+// Given a range of intervals I1, I2, ..., In, maximum_gap() returns\r
+// the maximum length of an interval M that satisfies the following\r
+// properties:\r
+//\r
+// 1. M.left >= min(I1, I2, ..., In)\r
+// 2. M.right <= max(I1, I2, ..., In)\r
+// 3. intersection(interior(M), Ik) is the empty set for all k=1, ..., n\r
+// 4. length(M) is maximal\r
+//\r
+// where M.left and M.right denote the left and right extreme values\r
+// for the interval M, and length(M) is equal to M.right - M.left.\r
+//\r
+// If M does not exist (or, alternatively, M is identified as the\r
+// empty set), 0 is returned.\r
+//\r
+// The algorithm proceeds for performing a sweep: the left endpoints\r
+// are inserted into a min-priority queue with the priority being the\r
+// value of the endpoint. The sweep algorithm maintains an "overlap\r
+// counter" that counts the number of overlaping intervals at any\r
+// specific sweep-time value.\r
+// There are two types of events encountered during the sweep:\r
+// (a) a start event: the left endpoint of an interval is found.\r
+// In this case the overlap count is increased by one and the\r
+// right endpoint of the interval in inserted into the event queue\r
+// (b) an end event: the right endpoint of an interval is found.\r
+// In this case the overlap count is decreased by one. If the\r
+// updated overlap count is 0, then we could expect to have a gap\r
+// in-between intervals. This gap is measured as the (absolute)\r
+// distance of the current interval right endpoint (being\r
+// processed) to the upcoming left endpoint of the next interval\r
+// to be processed (if such an interval exists). If the measured\r
+// gap is greater than the current maximum gap, it is recorded.\r
+// The initial maximum gap is initialized to 0. This value is returned\r
+// if no gap is found during the sweeping procedure.\r
+\r
+template <typename RangeOfIntervals, typename T>\r
+inline typename boost::range_value<RangeOfIntervals>::type::difference_type\r
+maximum_gap(RangeOfIntervals const& range_of_intervals,\r
+ T& max_gap_left, T& max_gap_right)\r
+{\r
+ typedef typename boost::range_value<RangeOfIntervals>::type interval_type;\r
+ typedef detail::max_interval_gap::sweep_event<interval_type> event_type;\r
+\r
+ // create a min-priority queue for the events\r
+ std::priority_queue\r
+ <\r
+ event_type,\r
+ std::vector<event_type>, \r
+ detail::max_interval_gap::event_greater<event_type>\r
+ > queue;\r
+\r
+ // define initialization and event-process visitors\r
+ detail::max_interval_gap::initialization_visitor init_visitor;\r
+ detail::max_interval_gap::event_visitor<event_type> sweep_visitor;\r
+\r
+ // perform the sweep\r
+ geometry::sweep(range_of_intervals,\r
+ queue,\r
+ init_visitor,\r
+ sweep_visitor);\r
+\r
+ max_gap_left = sweep_visitor.max_gap_left();\r
+ max_gap_right = sweep_visitor.max_gap_right();\r
+ return sweep_visitor.max_gap();\r
+}\r
+\r
+template <typename RangeOfIntervals>\r
+inline typename boost::range_value<RangeOfIntervals>::type::difference_type\r
+maximum_gap(RangeOfIntervals const& range_of_intervals)\r
+{\r
+ typedef typename boost::remove_const\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename boost::range_value\r
+ <\r
+ RangeOfIntervals\r
+ >::type::value_type\r
+ >::type\r
+ >::type value_type;\r
+\r
+ value_type left, right;\r
+\r
+ return maximum_gap(range_of_intervals, left, right);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename MultiGeometry, typename Policy>\r
+struct multi_modify\r
+{\r
+ static inline void apply(MultiGeometry& multi)\r
+ {\r
+ typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;\r
+ for (iterator_type it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ Policy::apply(*it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_WITH_PREDICATE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_WITH_PREDICATE_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename MultiGeometry, typename Predicate, typename Policy>\r
+struct multi_modify_with_predicate\r
+{\r
+ static inline void apply(MultiGeometry& multi, Predicate const& predicate)\r
+ {\r
+ typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;\r
+ for (iterator_type it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ Policy::apply(*it, predicate);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_WITH_PREDICATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_SUM_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_SUM_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+struct multi_sum\r
+{\r
+ template <typename ReturnType, typename Policy, typename MultiGeometry, typename Strategy>\r
+ static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy)\r
+ {\r
+ ReturnType sum = ReturnType();\r
+ for (typename boost::range_iterator\r
+ <\r
+ MultiGeometry const\r
+ >::type it = boost::begin(geometry);\r
+ it != boost::end(geometry);\r
+ ++it)\r
+ {\r
+ sum += Policy::apply(*it, strategy);\r
+ }\r
+ return sum;\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_SUM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>\r
+#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>\r
+\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace normalization\r
+{\r
+\r
+\r
+struct do_nothing\r
+{\r
+ template <typename GeometryIn, typename GeometryOut>\r
+ static inline void apply(GeometryIn const&, GeometryOut&)\r
+ {\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct assign_loop\r
+{\r
+ template <typename CoordinateType, typename PointIn, typename PointOut>\r
+ static inline void apply(CoordinateType const& longitude,\r
+ CoordinateType const& latitude,\r
+ PointIn const& point_in,\r
+ PointOut& point_out)\r
+ {\r
+ geometry::set<Dimension>(point_out, boost::numeric_cast\r
+ <\r
+ typename coordinate_type<PointOut>::type\r
+ >(geometry::get<Dimension>(point_in)));\r
+\r
+ assign_loop\r
+ <\r
+ Dimension + 1, DimensionCount\r
+ >::apply(longitude, latitude, point_in, point_out);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct assign_loop<DimensionCount, DimensionCount>\r
+{\r
+ template <typename CoordinateType, typename PointIn, typename PointOut>\r
+ static inline void apply(CoordinateType const&,\r
+ CoordinateType const&,\r
+ PointIn const&,\r
+ PointOut&)\r
+ {\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct assign_loop<0, DimensionCount>\r
+{\r
+ template <typename CoordinateType, typename PointIn, typename PointOut>\r
+ static inline void apply(CoordinateType const& longitude,\r
+ CoordinateType const& latitude,\r
+ PointIn const& point_in,\r
+ PointOut& point_out)\r
+ {\r
+ geometry::set<0>(point_out, boost::numeric_cast\r
+ <\r
+ typename coordinate_type<PointOut>::type\r
+ >(longitude));\r
+\r
+ assign_loop\r
+ <\r
+ 1, DimensionCount\r
+ >::apply(longitude, latitude, point_in, point_out);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct assign_loop<1, DimensionCount>\r
+{\r
+ template <typename CoordinateType, typename PointIn, typename PointOut>\r
+ static inline void apply(CoordinateType const& longitude,\r
+ CoordinateType const& latitude,\r
+ PointIn const& point_in,\r
+ PointOut& point_out)\r
+ {\r
+ geometry::set<1>(point_out, boost::numeric_cast\r
+ <\r
+ typename coordinate_type<PointOut>::type\r
+ >(latitude));\r
+\r
+ assign_loop\r
+ <\r
+ 2, DimensionCount\r
+ >::apply(longitude, latitude, point_in, point_out);\r
+ }\r
+};\r
+\r
+\r
+template <typename PointIn, typename PointOut>\r
+struct normalize_point\r
+{\r
+ static inline void apply(PointIn const& point_in, PointOut& point_out)\r
+ {\r
+ typedef typename coordinate_type<PointIn>::type in_coordinate_type;\r
+\r
+ in_coordinate_type longitude = geometry::get<0>(point_in);\r
+ in_coordinate_type latitude = geometry::get<1>(point_in);\r
+\r
+ math::normalize_spheroidal_coordinates\r
+ <\r
+ typename coordinate_system<PointIn>::type::units,\r
+ in_coordinate_type\r
+ >(longitude, latitude);\r
+\r
+ assign_loop\r
+ <\r
+ 0, dimension<PointIn>::value\r
+ >::apply(longitude, latitude, point_in, point_out);\r
+ }\r
+};\r
+\r
+\r
+template <typename BoxIn, typename BoxOut>\r
+class normalize_box\r
+{\r
+ template <typename UnitsIn, typename UnitsOut, typename CoordinateInType>\r
+ static inline void apply_to_coordinates(CoordinateInType& lon_min,\r
+ CoordinateInType& lat_min,\r
+ CoordinateInType& lon_max,\r
+ CoordinateInType& lat_max,\r
+ BoxIn const& box_in,\r
+ BoxOut& box_out)\r
+ {\r
+ detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out);\r
+ assign_loop\r
+ <\r
+ 0, dimension<BoxIn>::value\r
+ >::apply(lon_min,\r
+ lat_min,\r
+ detail::indexed_point_view\r
+ <\r
+ BoxIn const, min_corner\r
+ >(box_in),\r
+ p_min_out);\r
+\r
+ detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out);\r
+ assign_loop\r
+ <\r
+ 0, dimension<BoxIn>::value\r
+ >::apply(lon_max,\r
+ lat_max,\r
+ detail::indexed_point_view\r
+ <\r
+ BoxIn const, max_corner\r
+ >(box_in),\r
+ p_max_out);\r
+ }\r
+\r
+public:\r
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out)\r
+ {\r
+ typedef typename coordinate_type<BoxIn>::type in_coordinate_type;\r
+\r
+ in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in);\r
+ in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in);\r
+ in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in);\r
+ in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in);\r
+\r
+ math::normalize_spheroidal_box_coordinates\r
+ <\r
+ typename coordinate_system<BoxIn>::type::units,\r
+ in_coordinate_type\r
+ >(lon_min, lat_min, lon_max, lat_max);\r
+\r
+ apply_to_coordinates\r
+ <\r
+ typename coordinate_system<BoxIn>::type::units,\r
+ typename coordinate_system<BoxOut>::type::units\r
+ >(lon_min, lat_min, lon_max, lat_max, box_in, box_out);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::normalization\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename GeometryIn,\r
+ typename GeometryOut,\r
+ typename TagIn = typename tag<GeometryIn>::type,\r
+ typename TagOut = typename tag<GeometryOut>::type,\r
+ typename CSTagIn = typename cs_tag<GeometryIn>::type,\r
+ typename CSTagOut = typename cs_tag<GeometryOut>::type\r
+>\r
+struct normalize : detail::normalization::do_nothing\r
+{};\r
+\r
+\r
+template <typename PointIn, typename PointOut>\r
+struct normalize\r
+ <\r
+ PointIn, PointOut, point_tag, point_tag,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ > : detail::normalization::normalize_point<PointIn, PointOut>\r
+{};\r
+\r
+\r
+template <typename PointIn, typename PointOut>\r
+struct normalize\r
+ <\r
+ PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag\r
+ > : detail::normalization::normalize_point<PointIn, PointOut>\r
+{};\r
+\r
+\r
+template <typename BoxIn, typename BoxOut>\r
+struct normalize\r
+ <\r
+ BoxIn, BoxOut, box_tag, box_tag,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ > : detail::normalization::normalize_box<BoxIn, BoxOut>\r
+{};\r
+\r
+\r
+template <typename BoxIn, typename BoxOut>\r
+struct normalize\r
+ <\r
+ BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag\r
+ > : detail::normalization::normalize_box<BoxIn, BoxOut>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename GeometryIn, typename GeometryOut>\r
+inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out)\r
+{\r
+ dispatch::normalize\r
+ <\r
+ GeometryIn, GeometryOut\r
+ >::apply(geometry_in, geometry_out);\r
+}\r
+\r
+template <typename GeometryOut, typename GeometryIn>\r
+inline GeometryOut return_normalized(GeometryIn const& geometry_in)\r
+{\r
+ GeometryOut geometry_out;\r
+ detail::normalize(geometry_in, geometry_out);\r
+ return geometry_out;\r
+}\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+\r
+/*!\r
+\brief Structure negating the result of specified policy\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Policy\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return Negation of the result of the policy\r
+ */\r
+template <typename Policy>\r
+struct not_\r
+{\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ return ! Policy::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NUM_DISTINCT_CONSECUTIVE_POINTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NUM_DISTINCT_CONSECUTIVE_POINTS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/range.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+// returns the number of distinct values in the range;\r
+// return values are 0u through MaximumNumber, where MaximumNumber\r
+// corresponds to MaximumNumber or more distinct values\r
+//\r
+// FUTURE: take into account topologically closed ranges;\r
+// add appropriate template parameter(s) to control whether\r
+// the closing point for topologically closed ranges is to be\r
+// accounted for separately or not\r
+template\r
+<\r
+ typename Range,\r
+ std::size_t MaximumNumber,\r
+ bool AllowDuplicates /* true */,\r
+ typename NotEqualTo\r
+>\r
+struct num_distinct_consecutive_points\r
+{\r
+ static inline std::size_t apply(Range const& range)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+\r
+ std::size_t const size = boost::size(range);\r
+\r
+ if ( size < 2u )\r
+ {\r
+ return (size < MaximumNumber) ? size : MaximumNumber;\r
+ }\r
+\r
+ iterator current = boost::begin(range);\r
+ std::size_t counter(0);\r
+ do\r
+ {\r
+ ++counter;\r
+ iterator next = std::find_if(current,\r
+ boost::end(range),\r
+ NotEqualTo(*current));\r
+ current = next;\r
+ }\r
+ while ( current != boost::end(range) && counter <= MaximumNumber );\r
+\r
+ return counter;\r
+ }\r
+};\r
+\r
+\r
+template <typename Range, std::size_t MaximumNumber, typename NotEqualTo>\r
+struct num_distinct_consecutive_points<Range, MaximumNumber, false, NotEqualTo>\r
+{\r
+ static inline std::size_t apply(Range const& range)\r
+ {\r
+ std::size_t const size = boost::size(range);\r
+ return (size < MaximumNumber) ? size : MaximumNumber;\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NUM_DISTINCT_CONSECUTIVE_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP\r
+\r
+#include <algorithm>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/policies/compare.hpp>\r
+#include <boost/geometry/iterators/closing_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/get_left_turns.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Point, typename T>\r
+struct angle_info\r
+{\r
+ typedef T angle_type;\r
+ typedef Point point_type;\r
+\r
+ segment_identifier seg_id;\r
+ std::size_t turn_index;\r
+ int operation_index;\r
+ std::size_t cluster_index;\r
+ Point intersection_point;\r
+ Point point; // either incoming or outgoing point\r
+ bool incoming;\r
+ bool blocked;\r
+ bool included;\r
+\r
+ inline angle_info()\r
+ : blocked(false)\r
+ , included(false)\r
+ {}\r
+};\r
+\r
+template <typename AngleInfo>\r
+class occupation_info\r
+{\r
+public :\r
+ typedef std::vector<AngleInfo> collection_type;\r
+\r
+ std::size_t count;\r
+\r
+ inline occupation_info()\r
+ : count(0)\r
+ {}\r
+\r
+ template <typename RobustPoint>\r
+ inline void add(RobustPoint const& incoming_point,\r
+ RobustPoint const& outgoing_point,\r
+ RobustPoint const& intersection_point,\r
+ std::size_t turn_index, int operation_index,\r
+ segment_identifier const& seg_id)\r
+ {\r
+ geometry::equal_to<RobustPoint> comparator;\r
+ if (comparator(incoming_point, intersection_point))\r
+ {\r
+ return;\r
+ }\r
+ if (comparator(outgoing_point, intersection_point))\r
+ {\r
+ return;\r
+ }\r
+\r
+ AngleInfo info;\r
+ info.seg_id = seg_id;\r
+ info.turn_index = turn_index;\r
+ info.operation_index = operation_index;\r
+ info.intersection_point = intersection_point;\r
+\r
+ {\r
+ info.point = incoming_point;\r
+ info.incoming = true;\r
+ m_angles.push_back(info);\r
+ }\r
+ {\r
+ info.point = outgoing_point;\r
+ info.incoming = false;\r
+ m_angles.push_back(info);\r
+ }\r
+ }\r
+\r
+ template <typename RobustPoint, typename Turns>\r
+ inline void get_left_turns(RobustPoint const& origin, Turns& turns)\r
+ {\r
+ // Sort on angle\r
+ std::sort(m_angles.begin(), m_angles.end(),\r
+ detail::left_turns::angle_less<typename AngleInfo::point_type>(origin));\r
+\r
+ // Group same-angled elements\r
+ std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin);\r
+ // Block all turns on the right side of any turn\r
+ detail::left_turns::block_turns(m_angles, cluster_size);\r
+ detail::left_turns::get_left_turns(m_angles, turns);\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)\r
+ template <typename RobustPoint>\r
+ inline bool has_rounding_issues(RobustPoint const& origin) const\r
+ {\r
+ return detail::left_turns::has_rounding_issues(angles, origin);\r
+ }\r
+#endif\r
+\r
+private :\r
+ collection_type m_angles; // each turn splitted in incoming/outgoing vectors\r
+};\r
+\r
+template<typename Pieces>\r
+inline void move_index(Pieces const& pieces, signed_size_type& index, signed_size_type& piece_index, int direction)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(direction == 1 || direction == -1);\r
+ BOOST_GEOMETRY_ASSERT(\r
+ piece_index >= 0\r
+ && piece_index < static_cast<signed_size_type>(boost::size(pieces)) );\r
+ BOOST_GEOMETRY_ASSERT(\r
+ index >= 0\r
+ && index < static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring)));\r
+\r
+ // NOTE: both index and piece_index must be in valid range\r
+ // this means that then they could be of type std::size_t\r
+ // if the code below was refactored\r
+\r
+ index += direction;\r
+ if (direction == -1 && index < 0)\r
+ {\r
+ piece_index--;\r
+ if (piece_index < 0)\r
+ {\r
+ piece_index = boost::size(pieces) - 1;\r
+ }\r
+ index = boost::size(pieces[piece_index].robust_ring) - 1;\r
+ }\r
+ if (direction == 1\r
+ && index >= static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring)))\r
+ {\r
+ piece_index++;\r
+ if (piece_index >= static_cast<signed_size_type>(boost::size(pieces)))\r
+ {\r
+ piece_index = 0;\r
+ }\r
+ index = 0;\r
+ }\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename RobustPoint,\r
+ typename Turn,\r
+ typename Pieces,\r
+ typename Info\r
+>\r
+inline void add_incoming_and_outgoing_angles(\r
+ RobustPoint const& intersection_point, // rescaled\r
+ Turn const& turn,\r
+ Pieces const& pieces, // using rescaled offsets of it\r
+ int operation_index,\r
+ segment_identifier seg_id,\r
+ Info& info)\r
+{\r
+ segment_identifier real_seg_id = seg_id;\r
+ geometry::equal_to<RobustPoint> comparator;\r
+\r
+ // Move backward and forward\r
+ RobustPoint direction_points[2];\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ signed_size_type index = turn.operations[operation_index].index_in_robust_ring;\r
+ signed_size_type piece_index = turn.operations[operation_index].piece_index;\r
+ while(comparator(pieces[piece_index].robust_ring[index], intersection_point))\r
+ {\r
+ move_index(pieces, index, piece_index, i == 0 ? -1 : 1);\r
+ }\r
+ direction_points[i] = pieces[piece_index].robust_ring[index];\r
+ }\r
+\r
+ info.add(direction_points[0], direction_points[1], intersection_point,\r
+ turn.turn_index, operation_index, real_seg_id);\r
+}\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RingCollection\r
+>\r
+inline void convert_and_add(GeometryOut& result,\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RingCollection const& collection,\r
+ ring_identifier id,\r
+ bool reversed, bool append)\r
+{\r
+ typedef typename geometry::tag<Geometry1>::type tag1;\r
+ typedef typename geometry::tag<Geometry2>::type tag2;\r
+ typedef typename geometry::tag<GeometryOut>::type tag_out;\r
+\r
+ if (id.source_index == 0)\r
+ {\r
+ convert_ring<tag_out>::apply(result,\r
+ get_ring<tag1>::apply(id, geometry1),\r
+ append, reversed);\r
+ }\r
+ else if (id.source_index == 1)\r
+ {\r
+ convert_ring<tag_out>::apply(result,\r
+ get_ring<tag2>::apply(id, geometry2),\r
+ append, reversed);\r
+ }\r
+ else if (id.source_index == 2)\r
+ {\r
+ convert_ring<tag_out>::apply(result,\r
+ get_ring<void>::apply(id, collection),\r
+ append, reversed);\r
+ }\r
+}\r
+\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename SelectionMap,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RingCollection,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator add_rings(SelectionMap const& map,\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RingCollection const& collection,\r
+ OutputIterator out)\r
+{\r
+ typedef typename SelectionMap::const_iterator iterator;\r
+ typedef typename SelectionMap::mapped_type property_type;\r
+ typedef typename property_type::area_type area_type;\r
+\r
+ area_type const zero = 0;\r
+ std::size_t const min_num_points = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure\r
+ <\r
+ typename boost::range_value\r
+ <\r
+ RingCollection const\r
+ >::type\r
+ >::value\r
+ >::value;\r
+\r
+\r
+ for (iterator it = boost::begin(map);\r
+ it != boost::end(map);\r
+ ++it)\r
+ {\r
+ if (! it->second.discarded\r
+ && it->second.parent.source_index == -1)\r
+ {\r
+ GeometryOut result;\r
+ convert_and_add(result, geometry1, geometry2, collection,\r
+ it->first, it->second.reversed, false);\r
+\r
+ // Add children\r
+ for (typename std::vector<ring_identifier>::const_iterator child_it\r
+ = it->second.children.begin();\r
+ child_it != it->second.children.end();\r
+ ++child_it)\r
+ {\r
+ iterator mit = map.find(*child_it);\r
+ if (mit != map.end()\r
+ && ! mit->second.discarded)\r
+ {\r
+ convert_and_add(result, geometry1, geometry2, collection,\r
+ *child_it, mit->second.reversed, true);\r
+ }\r
+ }\r
+\r
+ // Only add rings if they satisfy minimal requirements.\r
+ // This cannot be done earlier (during traversal), not\r
+ // everything is figured out yet (sum of positive/negative rings)\r
+ if (geometry::num_points(result) >= min_num_points\r
+ && math::larger(geometry::area(result), zero))\r
+ {\r
+ *out++ = result;\r
+ }\r
+ }\r
+ }\r
+ return out;\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename SelectionMap,\r
+ typename Geometry,\r
+ typename RingCollection,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator add_rings(SelectionMap const& map,\r
+ Geometry const& geometry,\r
+ RingCollection const& collection,\r
+ OutputIterator out)\r
+{\r
+ Geometry empty;\r
+ return add_rings<GeometryOut>(map, geometry, empty, collection, out);\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template <typename Range, typename Point>\r
+inline void append_no_duplicates(Range& range, Point const& point, bool force = false)\r
+{\r
+ if (boost::size(range) == 0\r
+ || force\r
+ || ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point))\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION\r
+ std::cout << " add: ("\r
+ << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"\r
+ << std::endl;\r
+#endif\r
+ geometry::append(range, point);\r
+ }\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+// TODO: move this / rename this\r
+template <typename Point1, typename Point2, typename RobustPolicy>\r
+inline bool points_equal_or_close(Point1 const& point1,\r
+ Point2 const& point2,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+ if (detail::equals::equals_point_point(point1, point2))\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Try using specified robust policy\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ Point1,\r
+ RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ robust_point_type point1_rob, point2_rob;\r
+ geometry::recalculate(point1_rob, point1, robust_policy);\r
+ geometry::recalculate(point2_rob, point2, robust_policy);\r
+\r
+ return detail::equals::equals_point_point(point1_rob, point2_rob);\r
+}\r
+\r
+\r
+template <typename Range, typename Point, typename RobustPolicy>\r
+inline void append_no_dups_or_spikes(Range& range, Point const& point,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION\r
+ std::cout << " add: ("\r
+ << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"\r
+ << std::endl;\r
+#endif\r
+ // The code below this condition checks all spikes/dups\r
+ // for geometries >= 3 points.\r
+ // So we have to check the first potential duplicate differently\r
+ if (boost::size(range) == 1\r
+ && points_equal_or_close(*(boost::begin(range)), point, robust_policy))\r
+ {\r
+ return;\r
+ }\r
+\r
+ traits::push_back<Range>::apply(range, point);\r
+\r
+ // If a point is equal, or forming a spike, remove the pen-ultimate point\r
+ // because this one caused the spike.\r
+ // If so, the now-new-pen-ultimate point can again cause a spike\r
+ // (possibly at a corner). So keep doing this.\r
+ // Besides spikes it will also avoid adding duplicates.\r
+ while(boost::size(range) >= 3\r
+ && point_is_spike_or_equal(point,\r
+ *(boost::end(range) - 3),\r
+ *(boost::end(range) - 2),\r
+ robust_policy))\r
+ {\r
+ // Use the Concept/traits, so resize and append again\r
+ traits::resize<Range>::apply(range, boost::size(range) - 2);\r
+ traits::push_back<Range>::apply(range, point);\r
+ }\r
+}\r
+\r
+template <typename Range, typename RobustPolicy>\r
+inline void clean_closing_dups_and_spikes(Range& range,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+ std::size_t const minsize\r
+ = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Range>::value\r
+ >::value;\r
+\r
+ if (boost::size(range) <= minsize)\r
+ {\r
+ return;\r
+ }\r
+\r
+ typedef typename boost::range_iterator<Range>::type iterator_type;\r
+ static bool const closed = geometry::closure<Range>::value == geometry::closed;\r
+\r
+// TODO: the following algorithm could be rewritten to first look for spikes\r
+// and then erase some number of points from the beginning of the Range\r
+\r
+ bool found = false;\r
+ do\r
+ {\r
+ found = false;\r
+ iterator_type first = boost::begin(range);\r
+ iterator_type second = first + 1;\r
+ iterator_type ultimate = boost::end(range) - 1;\r
+ if (BOOST_GEOMETRY_CONDITION(closed))\r
+ {\r
+ ultimate--;\r
+ }\r
+\r
+ // Check if closing point is a spike (this is so if the second point is\r
+ // considered as a spike w.r.t. the last segment)\r
+ if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy))\r
+ {\r
+ range::erase(range, first);\r
+ if (BOOST_GEOMETRY_CONDITION(closed))\r
+ {\r
+ // Remove closing last point\r
+ range::resize(range, boost::size(range) - 1);\r
+ // Add new closing point\r
+ range::push_back(range, range::front(range));\r
+ }\r
+ found = true;\r
+ }\r
+ } while(found && boost::size(range) > minsize);\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Item,\r
+ typename Geometry1, typename Geometry2,\r
+ typename RingCollection\r
+>\r
+static inline bool within_selected_input(Item const& item2, ring_identifier const& ring_id,\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RingCollection const& collection)\r
+{\r
+ typedef typename geometry::tag<Geometry1>::type tag1;\r
+ typedef typename geometry::tag<Geometry2>::type tag2;\r
+\r
+ switch (ring_id.source_index)\r
+ {\r
+ case 0 :\r
+ return geometry::within(item2.point,\r
+ get_ring<tag1>::apply(ring_id, geometry1));\r
+ break;\r
+ case 1 :\r
+ return geometry::within(item2.point,\r
+ get_ring<tag2>::apply(ring_id, geometry2));\r
+ break;\r
+ case 2 :\r
+ return geometry::within(item2.point,\r
+ get_ring<void>::apply(ring_id, collection));\r
+ break;\r
+ }\r
+ return false;\r
+}\r
+\r
+\r
+template <typename Point>\r
+struct ring_info_helper\r
+{\r
+ typedef typename geometry::default_area_result<Point>::type area_type;\r
+\r
+ ring_identifier id;\r
+ area_type real_area;\r
+ area_type abs_area;\r
+ model::box<Point> envelope;\r
+\r
+ inline ring_info_helper()\r
+ : real_area(0), abs_area(0)\r
+ {}\r
+\r
+ inline ring_info_helper(ring_identifier i, area_type a)\r
+ : id(i), real_area(a), abs_area(geometry::math::abs(a))\r
+ {}\r
+};\r
+\r
+\r
+struct ring_info_helper_get_box\r
+{\r
+ template <typename Box, typename InputItem>\r
+ static inline void apply(Box& total, InputItem const& item)\r
+ {\r
+ geometry::expand(total, item.envelope);\r
+ }\r
+};\r
+\r
+struct ring_info_helper_ovelaps_box\r
+{\r
+ template <typename Box, typename InputItem>\r
+ static inline bool apply(Box const& box, InputItem const& item)\r
+ {\r
+ return ! geometry::detail::disjoint::disjoint_box_box(box, item.envelope);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Collection, typename RingMap>\r
+struct assign_visitor\r
+{\r
+ typedef typename RingMap::mapped_type ring_info_type;\r
+\r
+ Geometry1 const& m_geometry1;\r
+ Geometry2 const& m_geometry2;\r
+ Collection const& m_collection;\r
+ RingMap& m_ring_map;\r
+ bool m_check_for_orientation;\r
+\r
+\r
+ inline assign_visitor(Geometry1 const& g1, Geometry2 const& g2, Collection const& c,\r
+ RingMap& map, bool check)\r
+ : m_geometry1(g1)\r
+ , m_geometry2(g2)\r
+ , m_collection(c)\r
+ , m_ring_map(map)\r
+ , m_check_for_orientation(check)\r
+ {}\r
+\r
+ template <typename Item>\r
+ inline void apply(Item const& outer, Item const& inner, bool first = true)\r
+ {\r
+ if (first && outer.abs_area < inner.abs_area)\r
+ {\r
+ // Apply with reversed arguments\r
+ apply(inner, outer, false);\r
+ return;\r
+ }\r
+\r
+ if (m_check_for_orientation\r
+ || (math::larger(outer.real_area, 0)\r
+ && math::smaller(inner.real_area, 0)))\r
+ {\r
+ ring_info_type& inner_in_map = m_ring_map[inner.id];\r
+\r
+ if (geometry::within(inner_in_map.point, outer.envelope)\r
+ && within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection)\r
+ )\r
+ {\r
+ // Assign a parent if there was no earlier parent, or the newly\r
+ // found parent is smaller than the previous one\r
+ if (inner_in_map.parent.source_index == -1\r
+ || outer.abs_area < inner_in_map.parent_area)\r
+ {\r
+ inner_in_map.parent = outer.id;\r
+ inner_in_map.parent_area = outer.abs_area;\r
+ }\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename RingCollection,\r
+ typename RingMap\r
+>\r
+inline void assign_parents(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RingCollection const& collection,\r
+ RingMap& ring_map,\r
+ bool check_for_orientation = false)\r
+{\r
+ typedef typename geometry::tag<Geometry1>::type tag1;\r
+ typedef typename geometry::tag<Geometry2>::type tag2;\r
+\r
+ typedef typename RingMap::mapped_type ring_info_type;\r
+ typedef typename ring_info_type::point_type point_type;\r
+ typedef model::box<point_type> box_type;\r
+\r
+ typedef typename RingMap::iterator map_iterator_type;\r
+\r
+ {\r
+ typedef ring_info_helper<point_type> helper;\r
+ typedef std::vector<helper> vector_type;\r
+ typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;\r
+\r
+ std::size_t count_total = ring_map.size();\r
+ std::size_t count_positive = 0;\r
+ std::size_t index_positive = 0; // only used if count_positive>0\r
+ std::size_t index = 0;\r
+\r
+ // Copy to vector (with new approach this might be obsolete as well, using the map directly)\r
+ vector_type vector(count_total);\r
+\r
+ for (map_iterator_type it = boost::begin(ring_map);\r
+ it != boost::end(ring_map); ++it, ++index)\r
+ {\r
+ vector[index] = helper(it->first, it->second.get_area());\r
+ helper& item = vector[index];\r
+ switch(it->first.source_index)\r
+ {\r
+ case 0 :\r
+ geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),\r
+ item.envelope);\r
+ break;\r
+ case 1 :\r
+ geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),\r
+ item.envelope);\r
+ break;\r
+ case 2 :\r
+ geometry::envelope(get_ring<void>::apply(it->first, collection),\r
+ item.envelope);\r
+ break;\r
+ }\r
+ if (item.real_area > 0)\r
+ {\r
+ count_positive++;\r
+ index_positive = index;\r
+ }\r
+ }\r
+\r
+ if (! check_for_orientation)\r
+ {\r
+ if (count_positive == count_total)\r
+ {\r
+ // Optimization for only positive rings\r
+ // -> no assignment of parents or reversal necessary, ready here.\r
+ return;\r
+ }\r
+\r
+ if (count_positive == 1)\r
+ {\r
+ // Optimization for one outer ring\r
+ // -> assign this as parent to all others (all interior rings)\r
+ // In unions, this is probably the most occuring case and gives\r
+ // a dramatic improvement (factor 5 for star_comb testcase)\r
+ ring_identifier id_of_positive = vector[index_positive].id;\r
+ ring_info_type& outer = ring_map[id_of_positive];\r
+ index = 0;\r
+ for (vector_iterator_type it = boost::begin(vector);\r
+ it != boost::end(vector); ++it, ++index)\r
+ {\r
+ if (index != index_positive)\r
+ {\r
+ ring_info_type& inner = ring_map[it->id];\r
+ inner.parent = id_of_positive;\r
+ outer.children.push_back(it->id);\r
+ }\r
+ }\r
+ return;\r
+ }\r
+ }\r
+\r
+ assign_visitor\r
+ <\r
+ Geometry1, Geometry2,\r
+ RingCollection, RingMap\r
+ > visitor(geometry1, geometry2, collection, ring_map, check_for_orientation);\r
+\r
+ geometry::partition\r
+ <\r
+ box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box\r
+ >::apply(vector, visitor);\r
+ }\r
+\r
+ if (check_for_orientation)\r
+ {\r
+ for (map_iterator_type it = boost::begin(ring_map);\r
+ it != boost::end(ring_map); ++it)\r
+ {\r
+ if (geometry::math::equals(it->second.get_area(), 0))\r
+ {\r
+ it->second.discarded = true;\r
+ }\r
+ else if (it->second.parent.source_index >= 0\r
+ && math::larger(it->second.get_area(), 0))\r
+ {\r
+ const ring_info_type& parent = ring_map[it->second.parent];\r
+\r
+ if (math::larger(parent.area, 0))\r
+ {\r
+ // Discard positive inner ring with positive parent\r
+ it->second.discarded = true;\r
+ }\r
+ // Remove parent ID from any positive inner ring\r
+ it->second.parent.source_index = -1;\r
+ }\r
+ else if (it->second.parent.source_index < 0\r
+ && math::smaller(it->second.get_area(), 0))\r
+ {\r
+ // Reverse negative ring without parent\r
+ it->second.reversed = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Assign childlist\r
+ for (map_iterator_type it = boost::begin(ring_map);\r
+ it != boost::end(ring_map); ++it)\r
+ {\r
+ if (it->second.parent.source_index >= 0)\r
+ {\r
+ ring_map[it->second.parent].children.push_back(it->first);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+// Version for one geometry (called by buffer)\r
+template\r
+<\r
+ typename Geometry,\r
+ typename RingCollection,\r
+ typename RingMap\r
+>\r
+inline void assign_parents(Geometry const& geometry,\r
+ RingCollection const& collection,\r
+ RingMap& ring_map,\r
+ bool check_for_orientation)\r
+{\r
+ // Call it with an empty geometry as second geometry (source_id == 1)\r
+ // (ring_map should be empty for source_id==1)\r
+\r
+ Geometry empty;\r
+ assign_parents(geometry, empty, collection, ring_map, check_for_orientation);\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP\r
+\r
+#include <cstddef>\r
+#include <string>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/has_self_intersections.hpp>\r
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT)\r
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+# include <boost/geometry/io/wkt/wkt.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template <typename Turns>\r
+inline void clear_visit_info(Turns& turns)\r
+{\r
+ typedef typename boost::range_value<Turns>::type tp_type;\r
+\r
+ for (typename boost::range_iterator<Turns>::type\r
+ it = boost::begin(turns);\r
+ it != boost::end(turns);\r
+ ++it)\r
+ {\r
+ for (typename boost::range_iterator\r
+ <\r
+ typename tp_type::container_type\r
+ >::type op_it = boost::begin(it->operations);\r
+ op_it != boost::end(it->operations);\r
+ ++op_it)\r
+ {\r
+ op_it->visited.clear();\r
+ }\r
+ }\r
+}\r
+\r
+struct backtrack_state\r
+{\r
+ bool m_good;\r
+\r
+ inline backtrack_state() : m_good(true) {}\r
+ inline void reset() { m_good = true; }\r
+ inline bool good() const { return m_good; }\r
+};\r
+\r
+\r
+enum traverse_error_type\r
+{\r
+ traverse_error_none,\r
+ traverse_error_no_next_ip_at_start,\r
+ traverse_error_no_next_ip,\r
+ traverse_error_dead_end_at_start,\r
+ traverse_error_dead_end,\r
+ traverse_error_visit_again,\r
+ traverse_error_endless_loop\r
+};\r
+\r
+inline std::string traverse_error_string(traverse_error_type error)\r
+{\r
+ switch (error)\r
+ {\r
+ case traverse_error_none : return "";\r
+ case traverse_error_no_next_ip_at_start : return "No next IP at start";\r
+ case traverse_error_no_next_ip : return "No next IP";\r
+ case traverse_error_dead_end_at_start : return "Dead end at start";\r
+ case traverse_error_dead_end : return "Dead end";\r
+ case traverse_error_visit_again : return "Visit again";\r
+ case traverse_error_endless_loop : return "Endless loop";\r
+ default : return "";\r
+ }\r
+ return "";\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2\r
+>\r
+class backtrack_check_self_intersections\r
+{\r
+ struct state : public backtrack_state\r
+ {\r
+ bool m_checked;\r
+ inline state()\r
+ : m_checked(true)\r
+ {}\r
+ };\r
+public :\r
+ typedef state state_type;\r
+\r
+ template <typename Operation, typename Rings, typename Ring, typename Turns, typename RobustPolicy, typename Visitor>\r
+ static inline void apply(std::size_t size_at_start,\r
+ Rings& rings, Ring& ring,\r
+ Turns& turns,\r
+ typename boost::range_value<Turns>::type const& turn,\r
+ Operation& operation,\r
+ traverse_error_type traverse_error,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ state_type& state,\r
+ Visitor& visitor\r
+ )\r
+ {\r
+ visitor.visit_traverse_reject(turns, turn, operation, traverse_error);\r
+\r
+ state.m_good = false;\r
+\r
+ // Check self-intersections and throw exception if appropriate\r
+ if (! state.m_checked)\r
+ {\r
+ state.m_checked = true;\r
+ has_self_intersections(geometry1, robust_policy);\r
+ has_self_intersections(geometry2, robust_policy);\r
+ }\r
+\r
+ // Make bad output clean\r
+ rings.resize(size_at_start);\r
+ geometry::traits::clear<typename boost::range_value<Rings>::type>::apply(ring);\r
+\r
+ // Reject this as a starting point\r
+ operation.visited.set_rejected();\r
+\r
+ // And clear all visit info\r
+ clear_visit_info(turns);\r
+ }\r
+};\r
+\r
+#ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2\r
+>\r
+class backtrack_debug\r
+{\r
+public :\r
+ typedef backtrack_state state_type;\r
+\r
+ template <typename Operation, typename Rings, typename Turns>\r
+ static inline void apply(std::size_t size_at_start,\r
+ Rings& rings, typename boost::range_value<Rings>::type& ring,\r
+ Turns& turns, Operation& operation,\r
+ std::string const& reason,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ state_type& state\r
+ )\r
+ {\r
+ std::cout << " REJECT " << reason << std::endl;\r
+\r
+ state.m_good = false;\r
+\r
+ rings.resize(size_at_start);\r
+ ring.clear();\r
+ operation.visited.set_rejected();\r
+ clear_visit_info(turns);\r
+\r
+ int c = 0;\r
+ for (int i = 0; i < turns.size(); i++)\r
+ {\r
+ for (int j = 0; j < 2; j++)\r
+ {\r
+ if (turns[i].operations[j].visited.rejected())\r
+ {\r
+ c++;\r
+ }\r
+ }\r
+ }\r
+ std::cout << "BACKTRACK (" << reason << " )"\r
+ << " " << c << " of " << turns.size() << " rejected"\r
+ << std::endl;\r
+ std::cout\r
+ << geometry::wkt(geometry1) << std::endl\r
+ << geometry::wkt(geometry2) << std::endl;\r
+ }\r
+};\r
+#endif // BOOST_GEOMETRY_OVERLAY_REPORT_WKT\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template<typename Turn>\r
+struct meta_turn\r
+{\r
+ int index;\r
+ Turn const* turn;\r
+ bool handled[2];\r
+\r
+ inline meta_turn(int i, Turn const& t)\r
+ : index(i), turn(&t)\r
+ {\r
+ handled[0] = false;\r
+ handled[1] = false;\r
+ }\r
+};\r
+\r
+\r
+template <typename MetaTurn>\r
+inline void display(MetaTurn const& meta_turn, std::string const& reason = "")\r
+{\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ std::cout << meta_turn.index\r
+ << "\tMethods: " << method_char(meta_turn.turn->method)\r
+ << " operations: " << operation_char(meta_turn.turn->operations[0].operation)\r
+ << operation_char(meta_turn.turn->operations[1].operation)\r
+ << " travels to " << meta_turn.turn->operations[0].enriched.travels_to_ip_index\r
+ << " and " << meta_turn.turn->operations[1].enriched.travels_to_ip_index\r
+ //<< " -> " << op_index\r
+ << " " << reason\r
+ << std::endl;\r
+#endif\r
+}\r
+\r
+\r
+template <typename MetaTurns, typename MetaTurn>\r
+inline void check_detailed(MetaTurns& meta_turns, MetaTurn const& meta_turn,\r
+ int op_index, int cycle, int start, operation_type for_operation,\r
+ bool& error)\r
+{\r
+ display(meta_turn);\r
+ int const ip_index = meta_turn.turn->operations[op_index].enriched.travels_to_ip_index;\r
+ if (ip_index >= 0)\r
+ {\r
+ bool found = false;\r
+\r
+ if (ip_index == start)\r
+ {\r
+ display(meta_turns[ip_index], " FINISH");\r
+ return;\r
+ }\r
+\r
+ // check on continuing, or on same-operation-on-same-geometry\r
+ if (! meta_turns[ip_index].handled[op_index]\r
+ && (meta_turns[ip_index].turn->operations[op_index].operation == operation_continue\r
+ || meta_turns[ip_index].turn->operations[op_index].operation == for_operation)\r
+ )\r
+ {\r
+ meta_turns[ip_index].handled[op_index] = true;\r
+ check_detailed(meta_turns, meta_turns[ip_index], op_index, cycle, start, for_operation, error);\r
+ found = true;\r
+ }\r
+ // check on other geometry\r
+ if (! found)\r
+ {\r
+ int const other_index = 1 - op_index;\r
+ if (! meta_turns[ip_index].handled[other_index]\r
+ && meta_turns[ip_index].turn->operations[other_index].operation == for_operation)\r
+ {\r
+ meta_turns[ip_index].handled[other_index] = true;\r
+ check_detailed(meta_turns, meta_turns[ip_index], other_index, cycle, start, for_operation, error);\r
+ found = true;\r
+ }\r
+ }\r
+\r
+ if (! found)\r
+ {\r
+ display(meta_turns[ip_index], " STOP");\r
+ error = true;\r
+#ifndef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ //std::cout << " STOP";\r
+#endif\r
+ }\r
+ }\r
+}\r
+\r
+\r
+template <typename TurnPoints>\r
+inline bool check_graph(TurnPoints& turn_points, operation_type for_operation)\r
+{\r
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;\r
+\r
+ bool error = false;\r
+ int index = 0;\r
+\r
+ std::vector<meta_turn<turn_point_type> > meta_turns;\r
+ for (typename boost::range_iterator<TurnPoints const>::type\r
+ it = boost::begin(turn_points);\r
+ it != boost::end(turn_points);\r
+ ++it, ++index)\r
+ {\r
+ meta_turns.push_back(meta_turn<turn_point_type>(index, *it));\r
+ }\r
+\r
+ int cycle = 0;\r
+ for (typename boost::range_iterator<std::vector<meta_turn<turn_point_type> > > ::type\r
+ it = boost::begin(meta_turns);\r
+ it != boost::end(meta_turns);\r
+ ++it)\r
+ {\r
+ if (! (it->turn->blocked() || it->turn->discarded))\r
+ {\r
+ for (int i = 0 ; i < 2; i++)\r
+ {\r
+ if (! it->handled[i]\r
+ && it->turn->operations[i].operation == for_operation)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ std::cout << "CYCLE " << cycle << std::endl;\r
+#endif\r
+ it->handled[i] = true;\r
+ check_detailed(meta_turns, *it, i, cycle++, it->index, for_operation, error);\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ std::cout <<" END CYCLE " << it->index << std::endl;\r
+#endif\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return error;\r
+}\r
+\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>\r
+\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace intersection\r
+{\r
+\r
+/*!\r
+ \brief Strategy: line clipping algorithm after Liang Barsky\r
+ \ingroup overlay\r
+ \details The Liang-Barsky line clipping algorithm clips a line with a clipping box.\r
+ It is slightly adapted in the sense that it returns which points are clipped\r
+ \tparam B input box type of clipping box\r
+ \tparam P input/output point-type of segments to be clipped\r
+ \note The algorithm is currently only implemented for 2D Cartesian points\r
+ \note Though it is implemented in namespace strategy, and theoretically another\r
+ strategy could be used, it is not (yet) updated to the general strategy concepts,\r
+ and not (yet) splitted into a file in folder strategies\r
+ \author Barend Gehrels, and the following recourses\r
+ - A tutorial: http://www.skytopia.com/project/articles/compsci/clipping.html\r
+ - a German applet (link broken): http://ls7-www.cs.uni-dortmund.de/students/projectgroups/acit/lineclip.shtml\r
+*/\r
+template<typename Box, typename Point>\r
+class liang_barsky\r
+{\r
+private:\r
+ typedef model::referring_segment<Point> segment_type;\r
+\r
+ template <typename CoordinateType, typename CalcType>\r
+ inline bool check_edge(CoordinateType const& p, CoordinateType const& q, CalcType& t1, CalcType& t2) const\r
+ {\r
+ bool visible = true;\r
+\r
+ if(p < 0)\r
+ {\r
+ CalcType const r = static_cast<CalcType>(q) / p;\r
+ if (r > t2)\r
+ visible = false;\r
+ else if (r > t1)\r
+ t1 = r;\r
+ }\r
+ else if(p > 0)\r
+ {\r
+ CalcType const r = static_cast<CalcType>(q) / p;\r
+ if (r < t1)\r
+ visible = false;\r
+ else if (r < t2)\r
+ t2 = r;\r
+ }\r
+ else\r
+ {\r
+ if (q < 0)\r
+ visible = false;\r
+ }\r
+\r
+ return visible;\r
+ }\r
+\r
+public:\r
+\r
+ inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const\r
+ {\r
+ typedef typename select_coordinate_type<Box, Point>::type coordinate_type;\r
+ typedef typename select_most_precise<coordinate_type, double>::type calc_type;\r
+\r
+ calc_type t1 = 0;\r
+ calc_type t2 = 1;\r
+\r
+ coordinate_type const dx = get<1, 0>(s) - get<0, 0>(s);\r
+ coordinate_type const dy = get<1, 1>(s) - get<0, 1>(s);\r
+\r
+ coordinate_type const p1 = -dx;\r
+ coordinate_type const p2 = dx;\r
+ coordinate_type const p3 = -dy;\r
+ coordinate_type const p4 = dy;\r
+\r
+ coordinate_type const q1 = get<0, 0>(s) - get<min_corner, 0>(b);\r
+ coordinate_type const q2 = get<max_corner, 0>(b) - get<0, 0>(s);\r
+ coordinate_type const q3 = get<0, 1>(s) - get<min_corner, 1>(b);\r
+ coordinate_type const q4 = get<max_corner, 1>(b) - get<0, 1>(s);\r
+\r
+ if (check_edge(p1, q1, t1, t2) // left\r
+ && check_edge(p2, q2, t1, t2) // right\r
+ && check_edge(p3, q3, t1, t2) // bottom\r
+ && check_edge(p4, q4, t1, t2)) // top\r
+ {\r
+ sp1_clipped = t1 > 0;\r
+ sp2_clipped = t2 < 1;\r
+\r
+ if (sp2_clipped)\r
+ {\r
+ set<1, 0>(s, get<0, 0>(s) + t2 * dx);\r
+ set<1, 1>(s, get<0, 1>(s) + t2 * dy);\r
+ }\r
+\r
+ if(sp1_clipped)\r
+ {\r
+ set<0, 0>(s, get<0, 0>(s) + t1 * dx);\r
+ set<0, 1>(s, get<0, 1>(s) + t1 * dy);\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ template<typename Linestring, typename OutputIterator>\r
+ inline void apply(Linestring& line_out, OutputIterator out) const\r
+ {\r
+ if (!boost::empty(line_out))\r
+ {\r
+ *out = line_out;\r
+ ++out;\r
+ geometry::clear(line_out);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace strategy::intersection\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace intersection\r
+{\r
+\r
+/*!\r
+ \brief Clips a linestring with a box\r
+ \details A linestring is intersected (clipped) by the specified box\r
+ and the resulting linestring, or pieces of linestrings, are sent to the specified output operator.\r
+ \tparam OutputLinestring type of the output linestrings\r
+ \tparam OutputIterator an output iterator which outputs linestrings\r
+ \tparam Linestring linestring-type, for example a vector of points, matching the output-iterator type,\r
+ the points should also match the input-iterator type\r
+ \tparam Box box type\r
+ \tparam Strategy strategy, a clipping strategy which should implement the methods "clip_segment" and "apply"\r
+*/\r
+template\r
+<\r
+ typename OutputLinestring,\r
+ typename OutputIterator,\r
+ typename Range,\r
+ typename RobustPolicy,\r
+ typename Box,\r
+ typename Strategy\r
+>\r
+OutputIterator clip_range_with_box(Box const& b, Range const& range,\r
+ RobustPolicy const&,\r
+ OutputIterator out, Strategy const& strategy)\r
+{\r
+ if (boost::begin(range) == boost::end(range))\r
+ {\r
+ return out;\r
+ }\r
+\r
+ typedef typename point_type<OutputLinestring>::type point_type;\r
+\r
+ OutputLinestring line_out;\r
+\r
+ typedef typename boost::range_iterator<Range const>::type iterator_type;\r
+ iterator_type vertex = boost::begin(range);\r
+ for(iterator_type previous = vertex++;\r
+ vertex != boost::end(range);\r
+ ++previous, ++vertex)\r
+ {\r
+ point_type p1, p2;\r
+ geometry::convert(*previous, p1);\r
+ geometry::convert(*vertex, p2);\r
+\r
+ // Clip the segment. Five situations:\r
+ // 1. Segment is invisible, finish line if any (shouldn't occur)\r
+ // 2. Segment is completely visible. Add (p1)-p2 to line\r
+ // 3. Point 1 is invisible (clipped), point 2 is visible. Start new line from p1-p2...\r
+ // 4. Point 1 is visible, point 2 is invisible (clipped). End the line with ...p2\r
+ // 5. Point 1 and point 2 are both invisible (clipped). Start/finish an independant line p1-p2\r
+ //\r
+ // This results in:\r
+ // a. if p1 is clipped, start new line\r
+ // b. if segment is partly or completely visible, add the segment\r
+ // c. if p2 is clipped, end the line\r
+\r
+ bool c1 = false;\r
+ bool c2 = false;\r
+ model::referring_segment<point_type> s(p1, p2);\r
+\r
+ if (!strategy.clip_segment(b, s, c1, c2))\r
+ {\r
+ strategy.apply(line_out, out);\r
+ }\r
+ else\r
+ {\r
+ // a. If necessary, finish the line and add a start a new one\r
+ if (c1)\r
+ {\r
+ strategy.apply(line_out, out);\r
+ }\r
+\r
+ // b. Add p1 only if it is the first point, then add p2\r
+ if (boost::empty(line_out))\r
+ {\r
+ detail::overlay::append_no_duplicates(line_out, p1, true);\r
+ }\r
+ detail::overlay::append_no_duplicates(line_out, p2);\r
+\r
+ // c. If c2 is clipped, finish the line\r
+ if (c2)\r
+ {\r
+ strategy.apply(line_out, out);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ // Add last part\r
+ strategy.apply(line_out, out);\r
+ return out;\r
+}\r
+\r
+}} // namespace detail::intersection\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP\r
+\r
+\r
+#include <set>\r
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+struct cluster_info\r
+{\r
+ std::set<signed_size_type> turn_indices;\r
+\r
+ bool switch_source; // For clusters with a touch, conform turn_info uu\r
+\r
+ //! Number of open spaces (e.g. 2 for touch)\r
+ std::size_t open_count;\r
+\r
+ inline cluster_info()\r
+ : switch_source(false)\r
+ , open_count(0)\r
+ {}\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/range/algorithm/reverse.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template<typename Tag>\r
+struct convert_ring\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TAG\r
+ , (types<Tag>)\r
+ );\r
+};\r
+\r
+template<>\r
+struct convert_ring<ring_tag>\r
+{\r
+ template<typename Destination, typename Source>\r
+ static inline void apply(Destination& destination, Source const& source,\r
+ bool append, bool reverse)\r
+ {\r
+ if (! append)\r
+ {\r
+ geometry::convert(source, destination);\r
+ if (reverse)\r
+ {\r
+ boost::reverse(destination);\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template<>\r
+struct convert_ring<polygon_tag>\r
+{\r
+ template<typename Destination, typename Source>\r
+ static inline void apply(Destination& destination, Source const& source,\r
+ bool append, bool reverse)\r
+ {\r
+ if (! append)\r
+ {\r
+ geometry::convert(source, exterior_ring(destination));\r
+ if (reverse)\r
+ {\r
+ boost::reverse(exterior_ring(destination));\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Avoid adding interior rings which are invalid\r
+ // because of its number of points:\r
+ std::size_t const min_num_points\r
+ = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Destination>::value\r
+ >::value;\r
+\r
+ if (geometry::num_points(source) >= min_num_points)\r
+ {\r
+ interior_rings(destination).resize(\r
+ interior_rings(destination).size() + 1);\r
+ geometry::convert(source, interior_rings(destination).back());\r
+ if (reverse)\r
+ {\r
+ boost::reverse(interior_rings(destination).back());\r
+ }\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP\r
+\r
+\r
+#include <boost/array.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace copy_segments\r
+{\r
+\r
+\r
+template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point_range\r
+{\r
+ static inline bool apply(Range const& range,\r
+ SegmentIdentifier const& seg_id, int offset,\r
+ PointOut& point)\r
+ {\r
+ typedef typename closeable_view\r
+ <\r
+ Range const,\r
+ closure<Range>::value\r
+ >::type cview_type;\r
+\r
+ typedef typename reversible_view\r
+ <\r
+ cview_type const,\r
+ Reverse ? iterate_reverse : iterate_forward\r
+ >::type rview_type;\r
+\r
+ cview_type cview(range);\r
+ rview_type view(cview);\r
+\r
+ typedef typename boost::range_iterator<rview_type>::type iterator;\r
+ geometry::ever_circling_iterator<iterator> it(boost::begin(view), boost::end(view),\r
+ boost::begin(view) + seg_id.segment_index, true);\r
+\r
+ for (signed_size_type i = 0; i < offset; ++i, ++it)\r
+ {\r
+ }\r
+\r
+ geometry::convert(*it, point);\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point_polygon\r
+{\r
+ static inline bool apply(Polygon const& polygon,\r
+ SegmentIdentifier const& seg_id, int offset,\r
+ PointOut& point)\r
+ {\r
+ // Call ring-version with the right ring\r
+ return copy_segment_point_range\r
+ <\r
+ typename geometry::ring_type<Polygon>::type,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >::apply\r
+ (\r
+ seg_id.ring_index < 0\r
+ ? geometry::exterior_ring(polygon)\r
+ : range::at(geometry::interior_rings(polygon), seg_id.ring_index),\r
+ seg_id, offset,\r
+ point\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point_box\r
+{\r
+ static inline bool apply(Box const& box,\r
+ SegmentIdentifier const& seg_id, int offset,\r
+ PointOut& point)\r
+ {\r
+ signed_size_type index = seg_id.segment_index;\r
+ for (int i = 0; i < offset; i++)\r
+ {\r
+ index++;\r
+ }\r
+\r
+ boost::array<typename point_type<Box>::type, 4> bp;\r
+ assign_box_corners_oriented<Reverse>(box, bp);\r
+ point = bp[index % 4];\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename MultiGeometry,\r
+ typename SegmentIdentifier,\r
+ typename PointOut,\r
+ typename Policy\r
+>\r
+struct copy_segment_point_multi\r
+{\r
+ static inline bool apply(MultiGeometry const& multi,\r
+ SegmentIdentifier const& seg_id, int offset,\r
+ PointOut& point)\r
+ {\r
+\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ seg_id.multi_index >= 0\r
+ && seg_id.multi_index < int(boost::size(multi))\r
+ );\r
+\r
+ // Call the single-version\r
+ return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::copy_segments\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename GeometryIn,\r
+ bool Reverse,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+struct copy_segment_point\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<GeometryIn>)\r
+ );\r
+};\r
+\r
+\r
+template <typename LineString, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point<linestring_tag, LineString, Reverse, SegmentIdentifier, PointOut>\r
+ : detail::copy_segments::copy_segment_point_range\r
+ <\r
+ LineString, Reverse, SegmentIdentifier, PointOut\r
+ >\r
+{};\r
+\r
+\r
+template <typename Ring, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point<ring_tag, Ring, Reverse, SegmentIdentifier, PointOut>\r
+ : detail::copy_segments::copy_segment_point_range\r
+ <\r
+ Ring, Reverse, SegmentIdentifier, PointOut\r
+ >\r
+{};\r
+\r
+template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point<polygon_tag, Polygon, Reverse, SegmentIdentifier, PointOut>\r
+ : detail::copy_segments::copy_segment_point_polygon\r
+ <\r
+ Polygon, Reverse, SegmentIdentifier, PointOut\r
+ >\r
+{};\r
+\r
+\r
+template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>\r
+struct copy_segment_point<box_tag, Box, Reverse, SegmentIdentifier, PointOut>\r
+ : detail::copy_segments::copy_segment_point_box\r
+ <\r
+ Box, Reverse, SegmentIdentifier, PointOut\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiGeometry,\r
+ bool Reverse,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+struct copy_segment_point\r
+ <\r
+ multi_polygon_tag,\r
+ MultiGeometry,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >\r
+ : detail::copy_segments::copy_segment_point_multi\r
+ <\r
+ MultiGeometry,\r
+ SegmentIdentifier,\r
+ PointOut,\r
+ detail::copy_segments::copy_segment_point_polygon\r
+ <\r
+ typename boost::range_value<MultiGeometry>::type,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename MultiGeometry,\r
+ bool Reverse,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+struct copy_segment_point\r
+ <\r
+ multi_linestring_tag,\r
+ MultiGeometry,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >\r
+ : detail::copy_segments::copy_segment_point_multi\r
+ <\r
+ MultiGeometry,\r
+ SegmentIdentifier,\r
+ PointOut,\r
+ detail::copy_segments::copy_segment_point_range\r
+ <\r
+ typename boost::range_value<MultiGeometry>::type,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+\r
+\r
+/*!\r
+ \brief Helper function, copies a point from a segment\r
+ \ingroup overlay\r
+ */\r
+template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut>\r
+inline bool copy_segment_point(Geometry const& geometry,\r
+ SegmentIdentifier const& seg_id, int offset,\r
+ PointOut& point_out)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::copy_segment_point\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ Reverse,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >::apply(geometry, seg_id, offset, point_out);\r
+}\r
+\r
+\r
+/*!\r
+ \brief Helper function, to avoid the same construct several times,\r
+ copies a point, based on a source-index and two geometries\r
+ \ingroup overlay\r
+ */\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Geometry1, typename Geometry2,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ SegmentIdentifier const& seg_id, int offset,\r
+ PointOut& point_out)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1);\r
+\r
+ if (seg_id.source_index == 0)\r
+ {\r
+ return dispatch::copy_segment_point\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ Geometry1,\r
+ Reverse1,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >::apply(geometry1, seg_id, offset, point_out);\r
+ }\r
+ else if (seg_id.source_index == 1)\r
+ {\r
+ return dispatch::copy_segment_point\r
+ <\r
+ typename tag<Geometry2>::type,\r
+ Geometry2,\r
+ Reverse2,\r
+ SegmentIdentifier,\r
+ PointOut\r
+ >::apply(geometry2, seg_id, offset, point_out);\r
+ }\r
+ // Exception?\r
+ return false;\r
+}\r
+\r
+\r
+/*!\r
+ \brief Helper function, to avoid the same construct several times,\r
+ copies a point, based on a source-index and two geometries\r
+ \ingroup overlay\r
+ */\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Geometry1, typename Geometry2,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ SegmentIdentifier const& seg_id,\r
+ PointOut& point1, PointOut& point2)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)\r
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2);\r
+}\r
+\r
+/*!\r
+ \brief Helper function, copies three points: two from the specified segment\r
+ (from, to) and the next one\r
+ \ingroup overlay\r
+ */\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Geometry1, typename Geometry2,\r
+ typename SegmentIdentifier,\r
+ typename PointOut\r
+>\r
+inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ SegmentIdentifier const& seg_id,\r
+ PointOut& point1, PointOut& point2, PointOut& point3)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)\r
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2)\r
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 2, point3);\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP\r
+\r
+\r
+#include <vector>\r
+\r
+#include <boost/array.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/integral_constant.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace copy_segments\r
+{\r
+\r
+\r
+template <bool Reverse>\r
+struct copy_segments_ring\r
+{\r
+ template\r
+ <\r
+ typename Ring,\r
+ typename SegmentIdentifier,\r
+ typename RobustPolicy,\r
+ typename RangeOut\r
+ >\r
+ static inline void apply(Ring const& ring,\r
+ SegmentIdentifier const& seg_id,\r
+ signed_size_type to_index,\r
+ RobustPolicy const& robust_policy,\r
+ RangeOut& current_output)\r
+ {\r
+ typedef typename closeable_view\r
+ <\r
+ Ring const,\r
+ closure<Ring>::value\r
+ >::type cview_type;\r
+\r
+ typedef typename reversible_view\r
+ <\r
+ cview_type const,\r
+ Reverse ? iterate_reverse : iterate_forward\r
+ >::type rview_type;\r
+\r
+ typedef typename boost::range_iterator<rview_type const>::type iterator;\r
+ typedef geometry::ever_circling_iterator<iterator> ec_iterator;\r
+\r
+\r
+ cview_type cview(ring);\r
+ rview_type view(cview);\r
+\r
+ // The problem: sometimes we want to from "3" to "2"\r
+ // -> end = "3" -> end == begin\r
+ // This is not convenient with iterators.\r
+\r
+ // So we use the ever-circling iterator and determine when to step out\r
+\r
+ signed_size_type const from_index = seg_id.segment_index + 1;\r
+\r
+ // Sanity check\r
+ BOOST_GEOMETRY_ASSERT(from_index < static_cast<signed_size_type>(boost::size(view)));\r
+\r
+ ec_iterator it(boost::begin(view), boost::end(view),\r
+ boost::begin(view) + from_index);\r
+\r
+ // [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK\r
+ // [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK\r
+ // [1..1], travel the whole ring round\r
+ signed_size_type const count = from_index <= to_index\r
+ ? to_index - from_index + 1\r
+ : static_cast<signed_size_type>(boost::size(view))\r
+ - from_index + to_index + 1;\r
+\r
+ for (signed_size_type i = 0; i < count; ++i, ++it)\r
+ {\r
+ detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy);\r
+ }\r
+ }\r
+};\r
+\r
+template <bool Reverse, bool RemoveSpikes = true>\r
+class copy_segments_linestring\r
+{\r
+private:\r
+ // remove spikes\r
+ template <typename RangeOut, typename Point, typename RobustPolicy>\r
+ static inline void append_to_output(RangeOut& current_output,\r
+ Point const& point,\r
+ RobustPolicy const& robust_policy,\r
+ boost::true_type const&)\r
+ {\r
+ detail::overlay::append_no_dups_or_spikes(current_output, point,\r
+ robust_policy);\r
+ }\r
+\r
+ // keep spikes\r
+ template <typename RangeOut, typename Point, typename RobustPolicy>\r
+ static inline void append_to_output(RangeOut& current_output,\r
+ Point const& point,\r
+ RobustPolicy const&,\r
+ boost::false_type const&)\r
+ {\r
+ detail::overlay::append_no_duplicates(current_output, point);\r
+ }\r
+\r
+public:\r
+ template\r
+ <\r
+ typename LineString,\r
+ typename SegmentIdentifier,\r
+ typename RobustPolicy,\r
+ typename RangeOut\r
+ >\r
+ static inline void apply(LineString const& ls,\r
+ SegmentIdentifier const& seg_id,\r
+ signed_size_type to_index,\r
+ RobustPolicy const& robust_policy,\r
+ RangeOut& current_output)\r
+ {\r
+ signed_size_type const from_index = seg_id.segment_index + 1;\r
+\r
+ // Sanity check\r
+ if ( from_index > to_index\r
+ || from_index < 0\r
+ || to_index >= static_cast<signed_size_type>(boost::size(ls)) )\r
+ {\r
+ return;\r
+ }\r
+\r
+ signed_size_type const count = to_index - from_index + 1;\r
+\r
+ typename boost::range_iterator<LineString const>::type\r
+ it = boost::begin(ls) + from_index;\r
+\r
+ for (signed_size_type i = 0; i < count; ++i, ++it)\r
+ {\r
+ append_to_output(current_output, *it, robust_policy,\r
+ boost::integral_constant<bool, RemoveSpikes>());\r
+ }\r
+ }\r
+};\r
+\r
+template <bool Reverse>\r
+struct copy_segments_polygon\r
+{\r
+ template\r
+ <\r
+ typename Polygon,\r
+ typename SegmentIdentifier,\r
+ typename RobustPolicy,\r
+ typename RangeOut\r
+ >\r
+ static inline void apply(Polygon const& polygon,\r
+ SegmentIdentifier const& seg_id,\r
+ signed_size_type to_index,\r
+ RobustPolicy const& robust_policy,\r
+ RangeOut& current_output)\r
+ {\r
+ // Call ring-version with the right ring\r
+ copy_segments_ring<Reverse>::apply\r
+ (\r
+ seg_id.ring_index < 0\r
+ ? geometry::exterior_ring(polygon)\r
+ : range::at(geometry::interior_rings(polygon), seg_id.ring_index),\r
+ seg_id, to_index,\r
+ robust_policy,\r
+ current_output\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template <bool Reverse>\r
+struct copy_segments_box\r
+{\r
+ template\r
+ <\r
+ typename Box,\r
+ typename SegmentIdentifier,\r
+ typename RobustPolicy,\r
+ typename RangeOut\r
+ >\r
+ static inline void apply(Box const& box,\r
+ SegmentIdentifier const& seg_id,\r
+ signed_size_type to_index,\r
+ RobustPolicy const& robust_policy,\r
+ RangeOut& current_output)\r
+ {\r
+ signed_size_type index = seg_id.segment_index + 1;\r
+ BOOST_GEOMETRY_ASSERT(index < 5);\r
+\r
+ signed_size_type const count = index <= to_index\r
+ ? to_index - index + 1\r
+ : 5 - index + to_index + 1;\r
+\r
+ // Create array of points, the fifth one closes it\r
+ boost::array<typename point_type<Box>::type, 5> bp;\r
+ assign_box_corners_oriented<Reverse>(box, bp);\r
+ bp[4] = bp[0];\r
+\r
+ // (possibly cyclic) copy to output\r
+ // (see comments in ring-version)\r
+ for (signed_size_type i = 0; i < count; i++, index++)\r
+ {\r
+ detail::overlay::append_no_dups_or_spikes(current_output,\r
+ bp[index % 5], robust_policy);\r
+\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template<typename Policy>\r
+struct copy_segments_multi\r
+{\r
+ template\r
+ <\r
+ typename MultiGeometry,\r
+ typename SegmentIdentifier,\r
+ typename RobustPolicy,\r
+ typename RangeOut\r
+ >\r
+ static inline void apply(MultiGeometry const& multi_geometry,\r
+ SegmentIdentifier const& seg_id,\r
+ signed_size_type to_index,\r
+ RobustPolicy const& robust_policy,\r
+ RangeOut& current_output)\r
+ {\r
+\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ seg_id.multi_index >= 0\r
+ && static_cast<std::size_t>(seg_id.multi_index) < boost::size(multi_geometry)\r
+ );\r
+\r
+ // Call the single-version\r
+ Policy::apply(range::at(multi_geometry, seg_id.multi_index),\r
+ seg_id, to_index,\r
+ robust_policy,\r
+ current_output);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::copy_segments\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ bool Reverse\r
+>\r
+struct copy_segments : not_implemented<Tag>\r
+{};\r
+\r
+\r
+template <bool Reverse>\r
+struct copy_segments<ring_tag, Reverse>\r
+ : detail::copy_segments::copy_segments_ring<Reverse>\r
+{};\r
+\r
+\r
+template <bool Reverse>\r
+struct copy_segments<linestring_tag, Reverse>\r
+ : detail::copy_segments::copy_segments_linestring<Reverse>\r
+{};\r
+\r
+template <bool Reverse>\r
+struct copy_segments<polygon_tag, Reverse>\r
+ : detail::copy_segments::copy_segments_polygon<Reverse>\r
+{};\r
+\r
+\r
+template <bool Reverse>\r
+struct copy_segments<box_tag, Reverse>\r
+ : detail::copy_segments::copy_segments_box<Reverse>\r
+{};\r
+\r
+\r
+template<bool Reverse>\r
+struct copy_segments<multi_polygon_tag, Reverse>\r
+ : detail::copy_segments::copy_segments_multi\r
+ <\r
+ detail::copy_segments::copy_segments_polygon<Reverse>\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+ \brief Copy segments from a geometry, starting with the specified segment (seg_id)\r
+ until the specified index (to_index)\r
+ \ingroup overlay\r
+ */\r
+template\r
+<\r
+ bool Reverse,\r
+ typename Geometry,\r
+ typename SegmentIdentifier,\r
+ typename RobustPolicy,\r
+ typename RangeOut\r
+>\r
+inline void copy_segments(Geometry const& geometry,\r
+ SegmentIdentifier const& seg_id,\r
+ signed_size_type to_index,\r
+ RobustPolicy const& robust_policy,\r
+ RangeOut& range_out)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ dispatch::copy_segments\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Reverse\r
+ >::apply(geometry, seg_id, to_index, robust_policy, range_out);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/visit_info.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+inline char method_char(detail::overlay::method_type const& method)\r
+{\r
+ using namespace detail::overlay;\r
+ switch(method)\r
+ {\r
+ case method_none : return '-';\r
+ case method_disjoint : return 'd';\r
+ case method_crosses : return 'i';\r
+ case method_touch : return 't';\r
+ case method_touch_interior : return 'm';\r
+ case method_collinear : return 'c';\r
+ case method_equal : return 'e';\r
+ case method_error : return '!';\r
+ default : return '?';\r
+ }\r
+}\r
+\r
+inline char operation_char(detail::overlay::operation_type const& operation)\r
+{\r
+ using namespace detail::overlay;\r
+ switch(operation)\r
+ {\r
+ case operation_none : return '-';\r
+ case operation_union : return 'u';\r
+ case operation_intersection : return 'i';\r
+ case operation_blocked : return 'x';\r
+ case operation_continue : return 'c';\r
+ case operation_opposite : return 'o';\r
+ default : return '?';\r
+ }\r
+}\r
+\r
+inline char visited_char(detail::overlay::visit_info const& v)\r
+{\r
+ if (v.rejected()) return 'R';\r
+ if (v.started()) return 's';\r
+ if (v.visited()) return 'v';\r
+ if (v.none()) return '-';\r
+ if (v.finished()) return 'f';\r
+ return '?';\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DO_REVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DO_REVERSE_HPP\r
+\r
+#include <boost/geometry/core/point_order.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+// Metafunction helper for intersection and union\r
+template <order_selector Selector, bool Reverse = false>\r
+struct do_reverse {};\r
+\r
+template <>\r
+struct do_reverse<clockwise, false> : boost::false_type {};\r
+\r
+template <>\r
+struct do_reverse<clockwise, true> : boost::true_type {};\r
+\r
+template <>\r
+struct do_reverse<counterclockwise, false> : boost::true_type {};\r
+\r
+template <>\r
+struct do_reverse<counterclockwise, true> : boost::false_type {};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DO_REVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <map>\r
+#include <set>\r
+#include <vector>\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+# include <iostream>\r
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+# include <boost/geometry/io/wkt/wkt.hpp>\r
+# define BOOST_GEOMETRY_DEBUG_IDENTIFIER\r
+#endif\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/handle_colocations.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>\r
+#include <boost/geometry/policies/robustness/robust_type.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+// Sorts IP-s of this ring on segment-identifier, and if on same segment,\r
+// on distance.\r
+// Then assigns for each IP which is the next IP on this segment,\r
+// plus the vertex-index to travel to, plus the next IP\r
+// (might be on another segment)\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Operations,\r
+ typename Turns,\r
+ typename Geometry1, typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename Strategy\r
+>\r
+inline void enrich_sort(Operations& operations,\r
+ Turns const& turns,\r
+ operation_type for_operation,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ Strategy const& /*strategy*/)\r
+{\r
+ std::sort(boost::begin(operations),\r
+ boost::end(operations),\r
+ less_by_segment_ratio\r
+ <\r
+ Turns,\r
+ typename boost::range_value<Operations>::type,\r
+ Geometry1, Geometry2,\r
+ RobustPolicy,\r
+ Reverse1, Reverse2\r
+ >(turns, for_operation, geometry1, geometry2, robust_policy));\r
+}\r
+\r
+\r
+template <typename Operations, typename Turns>\r
+inline void enrich_assign(Operations& operations, Turns& turns)\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type op_type;\r
+ typedef typename boost::range_iterator<Operations>::type iterator_type;\r
+\r
+\r
+ if (operations.size() > 0)\r
+ {\r
+ // Assign travel-to-vertex/ip index for each turning point.\r
+ // Iterator "next" is circular\r
+\r
+ geometry::ever_circling_range_iterator<Operations const> next(operations);\r
+ ++next;\r
+\r
+ for (iterator_type it = boost::begin(operations);\r
+ it != boost::end(operations); ++it)\r
+ {\r
+ turn_type& turn = turns[it->turn_index];\r
+ op_type& op = turn.operations[it->operation_index];\r
+\r
+ // Normal behaviour: next should point at next turn:\r
+ if (it->turn_index == next->turn_index)\r
+ {\r
+ ++next;\r
+ }\r
+\r
+ // Cluster behaviour: next should point after cluster, unless\r
+ // their seg_ids are not the same\r
+ while (turn.cluster_id != -1\r
+ && it->turn_index != next->turn_index\r
+ && turn.cluster_id == turns[next->turn_index].cluster_id\r
+ && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)\r
+ {\r
+ ++next;\r
+ }\r
+\r
+ turn_type const& next_turn = turns[next->turn_index];\r
+ op_type const& next_op = next_turn.operations[next->operation_index];\r
+\r
+ op.enriched.travels_to_ip_index\r
+ = static_cast<signed_size_type>(next->turn_index);\r
+ op.enriched.travels_to_vertex_index\r
+ = next->subject->seg_id.segment_index;\r
+\r
+ if (op.seg_id.segment_index == next_op.seg_id.segment_index\r
+ && op.fraction < next_op.fraction)\r
+ {\r
+ // Next turn is located further on same segment\r
+ // assign next_ip_index\r
+ // (this is one not circular therefore fraction is considered)\r
+ op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);\r
+ }\r
+ }\r
+ }\r
+\r
+ // DEBUG\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ {\r
+ for (iterator_type it = boost::begin(operations);\r
+ it != boost::end(operations);\r
+ ++it)\r
+ {\r
+ op_type& op = turns[it->turn_index]\r
+ .operations[it->operation_index];\r
+\r
+ std::cout << it->turn_index\r
+ << " cl=" << turns[it->turn_index].cluster_id\r
+ << " meth=" << method_char(turns[it->turn_index].method)\r
+ << " seg=" << op.seg_id\r
+ << " dst=" << op.fraction // needs define\r
+ << " op=" << operation_char(turns[it->turn_index].operations[0].operation)\r
+ << operation_char(turns[it->turn_index].operations[1].operation)\r
+ << " (" << operation_char(op.operation) << ")"\r
+ << " nxt=" << op.enriched.next_ip_index\r
+ << " / " << op.enriched.travels_to_ip_index\r
+ << " [vx " << op.enriched.travels_to_vertex_index << "]"\r
+ << std::boolalpha << turns[it->turn_index].discarded\r
+ << std::endl;\r
+ ;\r
+ }\r
+ }\r
+#endif\r
+ // END DEBUG\r
+\r
+}\r
+\r
+\r
+template <typename Turns, typename MappedVector>\r
+inline void create_map(Turns const& turns,\r
+ detail::overlay::operation_type for_operation,\r
+ MappedVector& mapped_vector)\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::container_type container_type;\r
+ typedef typename MappedVector::mapped_type mapped_type;\r
+ typedef typename boost::range_value<mapped_type>::type indexed_type;\r
+\r
+ std::size_t index = 0;\r
+ for (typename boost::range_iterator<Turns const>::type\r
+ it = boost::begin(turns);\r
+ it != boost::end(turns);\r
+ ++it, ++index)\r
+ {\r
+ // Add all (non discarded) operations on this ring\r
+ // Blocked operations or uu on clusters (for intersection)\r
+ // should be included, to block potential paths in clusters\r
+ turn_type const& turn = *it;\r
+ if (turn.discarded)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (for_operation == operation_intersection\r
+ && turn.cluster_id == -1\r
+ && turn.both(operation_union))\r
+ {\r
+ // Only include uu turns if part of cluster (to block potential paths),\r
+ // otherwise they can block possibly viable paths\r
+ continue;\r
+ }\r
+\r
+ std::size_t op_index = 0;\r
+ for (typename boost::range_iterator<container_type const>::type\r
+ op_it = boost::begin(turn.operations);\r
+ op_it != boost::end(turn.operations);\r
+ ++op_it, ++op_index)\r
+ {\r
+ ring_identifier const ring_id\r
+ (\r
+ op_it->seg_id.source_index,\r
+ op_it->seg_id.multi_index,\r
+ op_it->seg_id.ring_index\r
+ );\r
+ mapped_vector[ring_id].push_back\r
+ (\r
+ indexed_type(index, op_index, *op_it,\r
+ it->operations[1 - op_index].seg_id)\r
+ );\r
+ }\r
+ }\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+/*!\r
+\brief All intersection points are enriched with successor information\r
+\ingroup overlay\r
+\tparam Turns type of intersection container\r
+ (e.g. vector of "intersection/turn point"'s)\r
+\tparam Clusters type of cluster container\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Strategy side strategy type\r
+\param turns container containing intersection points\r
+\param clusters container containing clusters\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param robust_policy policy to handle robustness issues\r
+\param strategy strategy\r
+ */\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ overlay_type OverlayType,\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename Geometry1, typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename Strategy\r
+>\r
+inline void enrich_intersection_points(Turns& turns,\r
+ Clusters& clusters,\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ Strategy const& strategy)\r
+{\r
+ static const detail::overlay::operation_type for_operation\r
+ = detail::overlay::operation_from_overlay<OverlayType>::value;\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type op_type;\r
+ typedef detail::overlay::indexed_turn_operation\r
+ <\r
+ op_type\r
+ > indexed_turn_operation;\r
+\r
+ typedef std::map\r
+ <\r
+ ring_identifier,\r
+ std::vector<indexed_turn_operation>\r
+ > mapped_vector_type;\r
+\r
+ bool const has_colocations\r
+ = detail::overlay::handle_colocations<Reverse1, Reverse2>(turns,\r
+ clusters, geometry1, geometry2);\r
+\r
+ // Discard none turns, if any\r
+ for (typename boost::range_iterator<Turns>::type\r
+ it = boost::begin(turns);\r
+ it != boost::end(turns);\r
+ ++it)\r
+ {\r
+ if (it->both(detail::overlay::operation_none))\r
+ {\r
+ it->discarded = true;\r
+ }\r
+ }\r
+\r
+ // Create a map of vectors of indexed operation-types to be able\r
+ // to sort intersection points PER RING\r
+ mapped_vector_type mapped_vector;\r
+\r
+ detail::overlay::create_map(turns, for_operation, mapped_vector);\r
+\r
+ // No const-iterator; contents of mapped copy is temporary,\r
+ // and changed by enrich\r
+ for (typename mapped_vector_type::iterator mit\r
+ = mapped_vector.begin();\r
+ mit != mapped_vector.end();\r
+ ++mit)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ std::cout << "ENRICH-sort Ring "\r
+ << mit->first << std::endl;\r
+#endif\r
+ detail::overlay::enrich_sort<Reverse1, Reverse2>(\r
+ mit->second, turns, for_operation,\r
+ geometry1, geometry2,\r
+ robust_policy, strategy);\r
+ }\r
+\r
+ for (typename mapped_vector_type::iterator mit\r
+ = mapped_vector.begin();\r
+ mit != mapped_vector.end();\r
+ ++mit)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ std::cout << "ENRICH-assign Ring "\r
+ << mit->first << std::endl;\r
+#endif\r
+ detail::overlay::enrich_assign(mit->second, turns);\r
+ }\r
+\r
+ if (has_colocations)\r
+ {\r
+ detail::overlay::gather_cluster_properties<Reverse1, Reverse2>(\r
+ clusters, turns, for_operation, geometry1, geometry2);\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH\r
+ //detail::overlay::check_graph(turns, for_operation);\r
+#endif\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+/*!\r
+\brief Keeps info to enrich intersection info (per source)\r
+\details Class to keep information necessary for traversal phase (a phase\r
+ of the overlay process). The information is gathered during the\r
+ enrichment phase\r
+ */\r
+template<typename Point>\r
+struct enrichment_info\r
+{\r
+ inline enrichment_info()\r
+ : travels_to_vertex_index(-1)\r
+ , travels_to_ip_index(-1)\r
+ , next_ip_index(-1)\r
+ , startable(true)\r
+ , count_left(0)\r
+ , count_right(0)\r
+ , zone(-1)\r
+ {}\r
+\r
+ // vertex to which is free travel after this IP,\r
+ // so from "segment_index+1" to "travels_to_vertex_index", without IP-s,\r
+ // can be -1\r
+ signed_size_type travels_to_vertex_index;\r
+\r
+ // same but now IP index, so "next IP index" but not on THIS segment\r
+ signed_size_type travels_to_ip_index;\r
+\r
+ // index of next IP on this segment, -1 if there is no one\r
+ signed_size_type next_ip_index;\r
+\r
+ bool startable; // Can be used to start in traverse\r
+\r
+ // Counts if polygons left/right of this operation\r
+ std::size_t count_left;\r
+ std::size_t count_right;\r
+ signed_size_type zone; // open zone, in cluster\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+namespace following\r
+{\r
+\r
+template <typename Turn, typename Operation>\r
+static inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op)\r
+{\r
+ // (Blocked means: blocked for polygon/polygon intersection, because\r
+ // they are reversed. But for polygon/line it is similar to continue)\r
+ return op.operation == operation_intersection\r
+ || op.operation == operation_continue\r
+ || op.operation == operation_blocked\r
+ ;\r
+}\r
+\r
+template\r
+<\r
+ typename Turn,\r
+ typename Operation,\r
+ typename LineString,\r
+ typename Polygon\r
+>\r
+static inline bool last_covered_by(Turn const& turn, Operation const& op,\r
+ LineString const& linestring, Polygon const& polygon)\r
+{\r
+ // Check any point between the this one and the first IP\r
+ typedef typename geometry::point_type<LineString>::type point_type;\r
+ point_type point_in_between;\r
+ detail::point_on_border::midpoint_helper\r
+ <\r
+ point_type,\r
+ 0, dimension<point_type>::value\r
+ >::apply(point_in_between, *(::boost::begin(linestring) + op.seg_id.segment_index), turn.point);\r
+\r
+ return geometry::covered_by(point_in_between, polygon);\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Turn,\r
+ typename Operation,\r
+ typename LineString,\r
+ typename Polygon\r
+>\r
+static inline bool is_leaving(Turn const& turn, Operation const& op,\r
+ bool entered, bool first,\r
+ LineString const& linestring, Polygon const& polygon)\r
+{\r
+ if (op.operation == operation_union)\r
+ {\r
+ return entered\r
+ || turn.method == method_crosses\r
+ || (first && last_covered_by(turn, op, linestring, polygon))\r
+ ;\r
+ }\r
+ return false;\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Turn,\r
+ typename Operation,\r
+ typename LineString,\r
+ typename Polygon\r
+>\r
+static inline bool is_staying_inside(Turn const& turn, Operation const& op,\r
+ bool entered, bool first,\r
+ LineString const& linestring, Polygon const& polygon)\r
+{\r
+ if (turn.method == method_crosses)\r
+ {\r
+ // The normal case, this is completely covered with entering/leaving\r
+ // so stay out of this time consuming "covered_by"\r
+ return false;\r
+ }\r
+\r
+ if (is_entering(turn, op))\r
+ {\r
+ return entered || (first && last_covered_by(turn, op, linestring, polygon));\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+template\r
+<\r
+ typename Turn,\r
+ typename Operation,\r
+ typename Linestring,\r
+ typename Polygon\r
+>\r
+static inline bool was_entered(Turn const& turn, Operation const& op, bool first,\r
+ Linestring const& linestring, Polygon const& polygon)\r
+{\r
+ if (first && (turn.method == method_collinear || turn.method == method_equal))\r
+ {\r
+ return last_covered_by(turn, op, linestring, polygon);\r
+ }\r
+ return false;\r
+}\r
+\r
+\r
+// Template specialization structure to call the right actions for the right type\r
+template <overlay_type OverlayType, bool RemoveSpikes = true>\r
+struct action_selector\r
+{\r
+ // If you get here the overlay type is not intersection or difference\r
+ // BOOST_MPL_ASSERT(false);\r
+};\r
+\r
+// Specialization for intersection, containing the implementation\r
+template <bool RemoveSpikes>\r
+struct action_selector<overlay_intersection, RemoveSpikes>\r
+{\r
+ template\r
+ <\r
+ typename OutputIterator,\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Point,\r
+ typename Operation,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void enter(LineStringOut& current_piece,\r
+ LineString const& ,\r
+ segment_identifier& segment_id,\r
+ signed_size_type , Point const& point,\r
+ Operation const& operation,\r
+ RobustPolicy const& ,\r
+ OutputIterator& )\r
+ {\r
+ // On enter, append the intersection point and remember starting point\r
+ // TODO: we don't check on spikes for linestrings (?). Consider this.\r
+ detail::overlay::append_no_duplicates(current_piece, point);\r
+ segment_id = operation.seg_id;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OutputIterator,\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Point,\r
+ typename Operation,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void leave(LineStringOut& current_piece,\r
+ LineString const& linestring,\r
+ segment_identifier& segment_id,\r
+ signed_size_type index, Point const& point,\r
+ Operation const& ,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator& out)\r
+ {\r
+ // On leave, copy all segments from starting point, append the intersection point\r
+ // and add the output piece\r
+ detail::copy_segments::copy_segments_linestring\r
+ <\r
+ false, RemoveSpikes\r
+ >::apply(linestring, segment_id, index, robust_policy, current_piece);\r
+ detail::overlay::append_no_duplicates(current_piece, point);\r
+ if (::boost::size(current_piece) > 1)\r
+ {\r
+ *out++ = current_piece;\r
+ }\r
+\r
+ geometry::clear(current_piece);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OutputIterator,\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Point,\r
+ typename Operation\r
+ >\r
+ static inline void isolated_point(LineStringOut&,\r
+ LineString const&,\r
+ segment_identifier&,\r
+ signed_size_type, Point const& point,\r
+ Operation const& , OutputIterator& out)\r
+ {\r
+ LineStringOut isolated_point_ls;\r
+ geometry::append(isolated_point_ls, point);\r
+\r
+#ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS\r
+ geometry::append(isolated_point_ls, point);\r
+#endif // BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS\r
+\r
+ *out++ = isolated_point_ls;\r
+ }\r
+\r
+ static inline bool is_entered(bool entered)\r
+ {\r
+ return entered;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Point,\r
+ typename Geometry,\r
+ typename RobustPolicy\r
+ >\r
+ static inline bool included(Point const& point,\r
+ Geometry const& geometry,\r
+ RobustPolicy const& )\r
+ {\r
+ return geometry::covered_by(point, geometry);\r
+ }\r
+\r
+};\r
+\r
+// Specialization for difference, which reverses these actions\r
+template <bool RemoveSpikes>\r
+struct action_selector<overlay_difference, RemoveSpikes>\r
+{\r
+ typedef action_selector<overlay_intersection, RemoveSpikes> normal_action;\r
+\r
+ template\r
+ <\r
+ typename OutputIterator,\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Point,\r
+ typename Operation,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void enter(LineStringOut& current_piece,\r
+ LineString const& linestring,\r
+ segment_identifier& segment_id,\r
+ signed_size_type index, Point const& point,\r
+ Operation const& operation,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator& out)\r
+ {\r
+ normal_action::leave(current_piece, linestring, segment_id, index,\r
+ point, operation, robust_policy, out);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OutputIterator,\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Point,\r
+ typename Operation,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void leave(LineStringOut& current_piece,\r
+ LineString const& linestring,\r
+ segment_identifier& segment_id,\r
+ signed_size_type index, Point const& point,\r
+ Operation const& operation,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator& out)\r
+ {\r
+ normal_action::enter(current_piece, linestring, segment_id, index,\r
+ point, operation, robust_policy, out);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OutputIterator,\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Point,\r
+ typename Operation\r
+ >\r
+ static inline void isolated_point(LineStringOut&,\r
+ LineString const&,\r
+ segment_identifier&,\r
+ signed_size_type, Point const&,\r
+ Operation const&, OutputIterator&)\r
+ {\r
+ }\r
+\r
+ static inline bool is_entered(bool entered)\r
+ {\r
+ return ! normal_action::is_entered(entered);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Point,\r
+ typename Geometry,\r
+ typename RobustPolicy\r
+ >\r
+ static inline bool included(Point const& point,\r
+ Geometry const& geometry,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ return ! normal_action::included(point, geometry, robust_policy);\r
+ }\r
+\r
+};\r
+\r
+}\r
+\r
+/*!\r
+\brief Follows a linestring from intersection point to intersection point, outputting which\r
+ is inside, or outside, a ring or polygon\r
+\ingroup overlay\r
+ */\r
+template\r
+<\r
+ typename LineStringOut,\r
+ typename LineString,\r
+ typename Polygon,\r
+ overlay_type OverlayType,\r
+ bool RemoveSpikes = true\r
+>\r
+class follow\r
+{\r
+\r
+ template <typename Turn>\r
+ struct sort_on_segment\r
+ {\r
+ // In case of turn point at the same location, we want to have continue/blocked LAST\r
+ // because that should be followed (intersection) or skipped (difference).\r
+ inline int operation_order(Turn const& turn) const\r
+ {\r
+ operation_type const& operation = turn.operations[0].operation;\r
+ switch(operation)\r
+ {\r
+ case operation_opposite : return 0;\r
+ case operation_none : return 0;\r
+ case operation_union : return 1;\r
+ case operation_intersection : return 2;\r
+ case operation_blocked : return 3;\r
+ case operation_continue : return 4;\r
+ }\r
+ return -1;\r
+ };\r
+\r
+ inline bool use_operation(Turn const& left, Turn const& right) const\r
+ {\r
+ // If they are the same, OK.\r
+ return operation_order(left) < operation_order(right);\r
+ }\r
+\r
+ inline bool use_distance(Turn const& left, Turn const& right) const\r
+ {\r
+ return left.operations[0].fraction == right.operations[0].fraction\r
+ ? use_operation(left, right)\r
+ : left.operations[0].fraction < right.operations[0].fraction\r
+ ;\r
+ }\r
+\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ segment_identifier const& sl = left.operations[0].seg_id;\r
+ segment_identifier const& sr = right.operations[0].seg_id;\r
+\r
+ return sl == sr\r
+ ? use_distance(left, right)\r
+ : sl < sr\r
+ ;\r
+\r
+ }\r
+ };\r
+\r
+\r
+\r
+public :\r
+\r
+ template\r
+ <\r
+ typename Point,\r
+ typename Geometry,\r
+ typename RobustPolicy\r
+ >\r
+ static inline bool included(Point const& point,\r
+ Geometry const& geometry,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ return following::action_selector\r
+ <\r
+ OverlayType, RemoveSpikes\r
+ >::included(point, geometry, robust_policy);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Turns,\r
+ typename OutputIterator,\r
+ typename RobustPolicy\r
+ >\r
+ static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,\r
+ detail::overlay::operation_type , // TODO: this parameter might be redundant\r
+ Turns& turns,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out)\r
+ {\r
+ typedef typename boost::range_iterator<Turns>::type turn_iterator;\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename boost::range_iterator\r
+ <\r
+ typename turn_type::container_type\r
+ >::type turn_operation_iterator_type;\r
+\r
+ typedef following::action_selector<OverlayType, RemoveSpikes> action;\r
+\r
+ // Sort intersection points on segments-along-linestring, and distance\r
+ // (like in enrich is done for poly/poly)\r
+ std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());\r
+\r
+ LineStringOut current_piece;\r
+ geometry::segment_identifier current_segment_id(0, -1, -1, -1);\r
+\r
+ // Iterate through all intersection points (they are ordered along the line)\r
+ bool entered = false;\r
+ bool first = true;\r
+ for (turn_iterator it = boost::begin(turns); it != boost::end(turns); ++it)\r
+ {\r
+ turn_operation_iterator_type iit = boost::begin(it->operations);\r
+\r
+ if (following::was_entered(*it, *iit, first, linestring, polygon))\r
+ {\r
+ debug_traverse(*it, *iit, "-> Was entered");\r
+ entered = true;\r
+ }\r
+\r
+ if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon))\r
+ {\r
+ debug_traverse(*it, *iit, "-> Staying inside");\r
+\r
+ entered = true;\r
+ }\r
+ else if (following::is_entering(*it, *iit))\r
+ {\r
+ debug_traverse(*it, *iit, "-> Entering");\r
+\r
+ entered = true;\r
+ action::enter(current_piece, linestring, current_segment_id,\r
+ iit->seg_id.segment_index, it->point, *iit,\r
+ robust_policy,\r
+ out);\r
+ }\r
+ else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))\r
+ {\r
+ debug_traverse(*it, *iit, "-> Leaving");\r
+\r
+ entered = false;\r
+ action::leave(current_piece, linestring, current_segment_id,\r
+ iit->seg_id.segment_index, it->point, *iit,\r
+ robust_policy,\r
+ out);\r
+ }\r
+ first = false;\r
+ }\r
+\r
+ if (action::is_entered(entered))\r
+ {\r
+ detail::copy_segments::copy_segments_linestring\r
+ <\r
+ false, RemoveSpikes\r
+ >::apply(linestring,\r
+ current_segment_id,\r
+ static_cast<signed_size_type>(boost::size(linestring) - 1),\r
+ robust_policy,\r
+ current_piece);\r
+ }\r
+\r
+ // Output the last one, if applicable\r
+ if (::boost::size(current_piece) > 1)\r
+ {\r
+ *out++ = current_piece;\r
+ }\r
+ return out;\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <iterator>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/follow.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/turns/debug_turn.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+namespace following { namespace linear\r
+{\r
+\r
+\r
+\r
+\r
+// follower for linear/linear geometries set operations\r
+\r
+template <typename Turn, typename Operation>\r
+static inline bool is_entering(Turn const& turn,\r
+ Operation const& operation)\r
+{\r
+ if ( turn.method != method_touch && turn.method != method_touch_interior )\r
+ {\r
+ return false;\r
+ }\r
+ return operation.operation == operation_intersection;\r
+}\r
+\r
+\r
+\r
+template <typename Turn, typename Operation>\r
+static inline bool is_staying_inside(Turn const& turn,\r
+ Operation const& operation, \r
+ bool entered)\r
+{\r
+ if ( !entered )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( turn.method != method_equal && turn.method != method_collinear )\r
+ {\r
+ return false;\r
+ }\r
+ return operation.operation == operation_continue;\r
+}\r
+\r
+\r
+\r
+template <typename Turn, typename Operation>\r
+static inline bool is_leaving(Turn const& turn,\r
+ Operation const& operation,\r
+ bool entered)\r
+{\r
+ if ( !entered )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( turn.method != method_touch\r
+ && turn.method != method_touch_interior\r
+ && turn.method != method_equal\r
+ && turn.method != method_collinear )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( operation.operation == operation_blocked )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if ( operation.operation != operation_union )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return operation.is_collinear;\r
+}\r
+\r
+\r
+\r
+template <typename Turn, typename Operation>\r
+static inline bool is_isolated_point(Turn const& turn,\r
+ Operation const& operation,\r
+ bool entered)\r
+{\r
+ if ( entered )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( turn.method == method_none )\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( operation.operation == operation_continue );\r
+ return true;\r
+ }\r
+\r
+ if ( turn.method == method_crosses )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if ( turn.method != method_touch && turn.method != method_touch_interior )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( operation.operation == operation_blocked )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if ( operation.operation != operation_union )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return !operation.is_collinear;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename LinestringOut,\r
+ typename Linestring,\r
+ typename Linear,\r
+ overlay_type OverlayType,\r
+ bool FollowIsolatedPoints,\r
+ bool FollowContinueTurns\r
+>\r
+class follow_linestring_linear_linestring\r
+{\r
+protected:\r
+ // allow spikes (false indicates: do not remove spikes)\r
+ typedef following::action_selector<OverlayType, false> action;\r
+\r
+ template\r
+ <\r
+ typename TurnIterator,\r
+ typename TurnOperationIterator,\r
+ typename SegmentIdentifier,\r
+ typename OutputIterator\r
+ >\r
+ static inline OutputIterator\r
+ process_turn(TurnIterator it,\r
+ TurnOperationIterator op_it,\r
+ bool& entered,\r
+ std::size_t& enter_count,\r
+ Linestring const& linestring,\r
+ LinestringOut& current_piece,\r
+ SegmentIdentifier& current_segment_id,\r
+ OutputIterator oit)\r
+ {\r
+ // We don't rescale linear/linear\r
+ detail::no_rescale_policy robust_policy;\r
+\r
+ if ( is_entering(*it, *op_it) )\r
+ {\r
+ detail::turns::debug_turn(*it, *op_it, "-> Entering");\r
+\r
+ entered = true;\r
+ if ( enter_count == 0 )\r
+ {\r
+ action::enter(current_piece, linestring,\r
+ current_segment_id,\r
+ op_it->seg_id.segment_index,\r
+ it->point, *op_it, robust_policy, oit);\r
+ }\r
+ ++enter_count;\r
+ }\r
+ else if ( is_leaving(*it, *op_it, entered) )\r
+ {\r
+ detail::turns::debug_turn(*it, *op_it, "-> Leaving");\r
+\r
+ --enter_count;\r
+ if ( enter_count == 0 )\r
+ {\r
+ entered = false;\r
+ action::leave(current_piece, linestring,\r
+ current_segment_id,\r
+ op_it->seg_id.segment_index,\r
+ it->point, *op_it, robust_policy, oit);\r
+ }\r
+ }\r
+ else if ( FollowIsolatedPoints\r
+ && is_isolated_point(*it, *op_it, entered) )\r
+ {\r
+ detail::turns::debug_turn(*it, *op_it, "-> Isolated point");\r
+\r
+ action::isolated_point(current_piece, linestring,\r
+ current_segment_id,\r
+ op_it->seg_id.segment_index,\r
+ it->point, *op_it, oit);\r
+ }\r
+ else if ( FollowContinueTurns\r
+ && is_staying_inside(*it, *op_it, entered) )\r
+ {\r
+ detail::turns::debug_turn(*it, *op_it, "-> Staying inside");\r
+\r
+ entered = true;\r
+ }\r
+ return oit;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename SegmentIdentifier,\r
+ typename OutputIterator\r
+ >\r
+ static inline OutputIterator\r
+ process_end(bool entered,\r
+ Linestring const& linestring,\r
+ SegmentIdentifier const& current_segment_id,\r
+ LinestringOut& current_piece,\r
+ OutputIterator oit)\r
+ {\r
+ if ( action::is_entered(entered) )\r
+ {\r
+ // We don't rescale linear/linear\r
+ detail::no_rescale_policy robust_policy;\r
+\r
+ detail::copy_segments::copy_segments_linestring\r
+ <\r
+ false, false // do not reverse; do not remove spikes\r
+ >::apply(linestring,\r
+ current_segment_id,\r
+ static_cast<signed_size_type>(boost::size(linestring) - 1),\r
+ robust_policy,\r
+ current_piece);\r
+ }\r
+\r
+ // Output the last one, if applicable\r
+ if (::boost::size(current_piece) > 1)\r
+ {\r
+ *oit++ = current_piece;\r
+ }\r
+\r
+ return oit;\r
+ }\r
+\r
+public:\r
+ template <typename TurnIterator, typename OutputIterator>\r
+ static inline OutputIterator\r
+ apply(Linestring const& linestring, Linear const&,\r
+ TurnIterator first, TurnIterator beyond,\r
+ OutputIterator oit)\r
+ {\r
+ // Iterate through all intersection points (they are\r
+ // ordered along the each line)\r
+\r
+ LinestringOut current_piece;\r
+ geometry::segment_identifier current_segment_id(0, -1, -1, -1);\r
+\r
+ bool entered = false;\r
+ std::size_t enter_count = 0;\r
+\r
+ for (TurnIterator it = first; it != beyond; ++it)\r
+ {\r
+ oit = process_turn(it, boost::begin(it->operations),\r
+ entered, enter_count, \r
+ linestring,\r
+ current_piece, current_segment_id,\r
+ oit);\r
+ }\r
+\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+ if (enter_count != 0)\r
+ {\r
+ throw inconsistent_turns_exception();\r
+ }\r
+#else\r
+ BOOST_GEOMETRY_ASSERT(enter_count == 0);\r
+#endif\r
+\r
+ return process_end(entered, linestring,\r
+ current_segment_id, current_piece,\r
+ oit);\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename LinestringOut,\r
+ typename MultiLinestring,\r
+ typename Linear,\r
+ overlay_type OverlayType,\r
+ bool FollowIsolatedPoints,\r
+ bool FollowContinueTurns\r
+>\r
+class follow_multilinestring_linear_linestring\r
+ : follow_linestring_linear_linestring\r
+ <\r
+ LinestringOut,\r
+ typename boost::range_value<MultiLinestring>::type,\r
+ Linear,\r
+ OverlayType,\r
+ FollowIsolatedPoints,\r
+ FollowContinueTurns\r
+ >\r
+{\r
+protected:\r
+ typedef typename boost::range_value<MultiLinestring>::type Linestring;\r
+\r
+ typedef follow_linestring_linear_linestring\r
+ <\r
+ LinestringOut, Linestring, Linear,\r
+ OverlayType, FollowIsolatedPoints, FollowContinueTurns\r
+ > Base;\r
+\r
+ typedef following::action_selector<OverlayType> action;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiLinestring const\r
+ >::type linestring_iterator;\r
+\r
+\r
+ template <typename OutputIt, overlay_type OT>\r
+ struct copy_linestrings_in_range\r
+ {\r
+ static inline OutputIt\r
+ apply(linestring_iterator, linestring_iterator, OutputIt oit)\r
+ {\r
+ return oit;\r
+ }\r
+ };\r
+\r
+ template <typename OutputIt>\r
+ struct copy_linestrings_in_range<OutputIt, overlay_difference>\r
+ {\r
+ static inline OutputIt\r
+ apply(linestring_iterator first, linestring_iterator beyond,\r
+ OutputIt oit)\r
+ {\r
+ for (linestring_iterator ls_it = first; ls_it != beyond; ++ls_it)\r
+ {\r
+ LinestringOut line_out;\r
+ geometry::convert(*ls_it, line_out);\r
+ *oit++ = line_out;\r
+ }\r
+ return oit;\r
+ }\r
+ };\r
+\r
+ template <typename TurnIterator>\r
+ static inline signed_size_type get_multi_index(TurnIterator it)\r
+ {\r
+ return boost::begin(it->operations)->seg_id.multi_index;\r
+ }\r
+\r
+ class has_other_multi_id\r
+ {\r
+ private:\r
+ signed_size_type m_multi_id;\r
+\r
+ public:\r
+ has_other_multi_id(signed_size_type multi_id)\r
+ : m_multi_id(multi_id) {}\r
+\r
+ template <typename Turn>\r
+ bool operator()(Turn const& turn) const\r
+ {\r
+ return boost::begin(turn.operations)->seg_id.multi_index\r
+ != m_multi_id;\r
+ }\r
+ };\r
+\r
+public:\r
+ template <typename TurnIterator, typename OutputIterator>\r
+ static inline OutputIterator\r
+ apply(MultiLinestring const& multilinestring, Linear const& linear,\r
+ TurnIterator first, TurnIterator beyond,\r
+ OutputIterator oit)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( first != beyond );\r
+\r
+ typedef copy_linestrings_in_range\r
+ <\r
+ OutputIterator, OverlayType\r
+ > copy_linestrings;\r
+\r
+ linestring_iterator ls_first = boost::begin(multilinestring);\r
+ linestring_iterator ls_beyond = boost::end(multilinestring);\r
+\r
+ // Iterate through all intersection points (they are\r
+ // ordered along the each linestring)\r
+\r
+ signed_size_type current_multi_id = get_multi_index(first);\r
+\r
+ oit = copy_linestrings::apply(ls_first,\r
+ ls_first + current_multi_id,\r
+ oit);\r
+\r
+ TurnIterator per_ls_next = first;\r
+ do {\r
+ TurnIterator per_ls_current = per_ls_next;\r
+\r
+ // find turn with different multi-index\r
+ per_ls_next = std::find_if(per_ls_current, beyond,\r
+ has_other_multi_id(current_multi_id));\r
+\r
+ oit = Base::apply(*(ls_first + current_multi_id),\r
+ linear, per_ls_current, per_ls_next, oit);\r
+\r
+ signed_size_type next_multi_id = -1;\r
+ linestring_iterator ls_next = ls_beyond;\r
+ if ( per_ls_next != beyond )\r
+ {\r
+ next_multi_id = get_multi_index(per_ls_next);\r
+ ls_next = ls_first + next_multi_id;\r
+ }\r
+ oit = copy_linestrings::apply(ls_first + current_multi_id + 1,\r
+ ls_next,\r
+ oit);\r
+\r
+ current_multi_id = next_multi_id;\r
+ }\r
+ while ( per_ls_next != beyond );\r
+\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename LinestringOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ overlay_type OverlayType,\r
+ bool FollowIsolatedPoints,\r
+ bool FollowContinueTurns,\r
+ typename TagOut = typename tag<LinestringOut>::type,\r
+ typename TagIn1 = typename tag<Geometry1>::type\r
+>\r
+struct follow\r
+ : not_implemented<LinestringOut, Geometry1>\r
+{};\r
+\r
+\r
+\r
+template\r
+<\r
+ typename LinestringOut,\r
+ typename Linestring,\r
+ typename Linear,\r
+ overlay_type OverlayType,\r
+ bool FollowIsolatedPoints,\r
+ bool FollowContinueTurns\r
+>\r
+struct follow\r
+ <\r
+ LinestringOut, Linestring, Linear,\r
+ OverlayType, FollowIsolatedPoints, FollowContinueTurns,\r
+ linestring_tag, linestring_tag\r
+ > : follow_linestring_linear_linestring\r
+ <\r
+ LinestringOut, Linestring, Linear,\r
+ OverlayType, FollowIsolatedPoints, FollowContinueTurns\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename LinestringOut,\r
+ typename MultiLinestring,\r
+ typename Linear,\r
+ overlay_type OverlayType,\r
+ bool FollowIsolatedPoints,\r
+ bool FollowContinueTurns\r
+>\r
+struct follow\r
+ <\r
+ LinestringOut, MultiLinestring, Linear,\r
+ OverlayType, FollowIsolatedPoints, FollowContinueTurns,\r
+ linestring_tag, multi_linestring_tag\r
+ > : follow_multilinestring_linear_linestring\r
+ <\r
+ LinestringOut, MultiLinestring, Linear,\r
+ OverlayType, FollowIsolatedPoints, FollowContinueTurns\r
+ >\r
+{};\r
+\r
+\r
+\r
+}} // namespace following::linear\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace get_intersection_points\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo\r
+>\r
+struct get_turn_without_info\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator>\r
+ static inline OutputIterator apply(\r
+ Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/,\r
+ bool /*is_p_first*/, bool /*is_p_last*/,\r
+ bool /*is_q_first*/, bool /*is_q_last*/,\r
+ TurnInfo const& ,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out)\r
+ {\r
+ typedef intersection_strategies\r
+ <\r
+ typename cs_tag<typename TurnInfo::point_type>::type,\r
+ Point1,\r
+ Point2,\r
+ typename TurnInfo::point_type,\r
+ RobustPolicy\r
+ > si;\r
+\r
+ typedef typename si::segment_intersection_strategy_type strategy;\r
+\r
+ typedef model::referring_segment<Point1 const> segment_type1;\r
+ typedef model::referring_segment<Point1 const> segment_type2;\r
+ segment_type1 p1(pi, pj);\r
+ segment_type2 q1(qi, qj);\r
+\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ Point1, RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ robust_point_type pi_rob, pj_rob, qi_rob, qj_rob;\r
+ geometry::recalculate(pi_rob, pi, robust_policy);\r
+ geometry::recalculate(pj_rob, pj, robust_policy);\r
+ geometry::recalculate(qi_rob, qi, robust_policy);\r
+ geometry::recalculate(qj_rob, qj, robust_policy);\r
+ typename strategy::return_type result\r
+ = strategy::apply(p1, q1, robust_policy,\r
+ pi_rob, pj_rob, qi_rob, qj_rob);\r
+\r
+ for (std::size_t i = 0; i < result.template get<0>().count; i++)\r
+ {\r
+\r
+ TurnInfo tp;\r
+ geometry::convert(result.template get<0>().intersections[i], tp.point);\r
+ *out++ = tp;\r
+ }\r
+\r
+ return out;\r
+ }\r
+};\r
+\r
+}} // namespace detail::get_intersection_points\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename Turns\r
+>\r
+inline void get_intersection_points(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns)\r
+{\r
+ concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();\r
+\r
+ typedef detail::get_intersection_points::get_turn_without_info\r
+ <\r
+ typename point_type<Geometry1>::type,\r
+ typename point_type<Geometry2>::type,\r
+ typename boost::range_value<Turns>::type\r
+ > TurnPolicy;\r
+\r
+ detail::get_turns::no_interrupt_policy interrupt_policy;\r
+\r
+ boost::mpl::if_c\r
+ <\r
+ reverse_dispatch<Geometry1, Geometry2>::type::value,\r
+ dispatch::get_turns_reversed\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ Geometry1, Geometry2,\r
+ false, false,\r
+ TurnPolicy\r
+ >,\r
+ dispatch::get_turns\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ Geometry1, Geometry2,\r
+ false, false,\r
+ TurnPolicy\r
+ >\r
+ >::type::apply(\r
+ 0, geometry1,\r
+ 1, geometry2,\r
+ robust_policy,\r
+ turns, interrupt_policy);\r
+}\r
+\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP\r
+\r
+\r
+#include <boost/geometry/strategies/intersection_strategies.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+/*!\r
+ \brief Get relative order\r
+ \details Can indicate which of two segments R and S,\r
+ both crossing a common segment P, comes first.\r
+ If the two segments cross P very close (e.g. in a spike),\r
+ the distance between the intersection points can be zero,\r
+ but we still need to know which comes first.\r
+ Therefore, it is useful that using sides we are able to discover this.\r
+ */\r
+template <typename Point1>\r
+struct get_relative_order\r
+{\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point1>::type\r
+ >::type strategy;\r
+\r
+ template <typename Point>\r
+ static inline int value_via_product(Point const& ti, Point const& tj,\r
+ Point const& ui, Point const& uj, int factor)\r
+ {\r
+ int const side_ti_u = strategy::apply(ti, tj, ui);\r
+ int const side_tj_u = strategy::apply(ti, tj, uj);\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER\r
+ std::cout << (factor == 1 ? " r//s " : " s//r ")\r
+ << side_ti_u << " / " << side_tj_u;\r
+#endif\r
+\r
+ return side_ti_u * side_tj_u >= 0\r
+ ? factor * (side_ti_u != 0 ? side_ti_u : side_tj_u)\r
+ : 0;\r
+ }\r
+\r
+\r
+ static inline int apply(\r
+ Point1 const& pi, Point1 const& pj,\r
+ Point1 const& ri, Point1 const& rj,\r
+ Point1 const& si, Point1 const& sj)\r
+ {\r
+ int const side_ri_p = strategy::apply(pi, pj, ri);\r
+ int const side_si_p = strategy::apply(pi, pj, si);\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER\r
+ int const side_rj_p = strategy::apply(pi, pj, rj);\r
+ int const side_sj_p = strategy::apply(pi, pj, sj);\r
+ std::cout << "r//p: " << side_ri_p << " / " << side_rj_p;\r
+ std::cout << " s//p: " << side_si_p << " / " << side_sj_p;\r
+#endif\r
+\r
+ int value = value_via_product(si, sj, ri, rj, 1);\r
+ if (value == 0)\r
+ {\r
+ value = value_via_product(ri, rj, si, sj, -1);\r
+ }\r
+\r
+ int const order = side_ri_p * side_ri_p * side_si_p * value;\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER\r
+ std::cout\r
+ << " o: " << order\r
+ << std::endl << std::endl;\r
+#endif\r
+\r
+ return order;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template<typename Tag>\r
+struct get_ring\r
+{};\r
+\r
+// A range of rings (multi-ring but that does not exist)\r
+// gets the "void" tag and is dispatched here.\r
+template<>\r
+struct get_ring<void>\r
+{\r
+ template<typename Range>\r
+ static inline typename boost::range_value<Range>::type const&\r
+ apply(ring_identifier const& id, Range const& container)\r
+ {\r
+ return range::at(container, id.multi_index);\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template<>\r
+struct get_ring<ring_tag>\r
+{\r
+ template<typename Ring>\r
+ static inline Ring const& apply(ring_identifier const& , Ring const& ring)\r
+ {\r
+ return ring;\r
+ }\r
+};\r
+\r
+\r
+template<>\r
+struct get_ring<box_tag>\r
+{\r
+ template<typename Box>\r
+ static inline Box const& apply(ring_identifier const& ,\r
+ Box const& box)\r
+ {\r
+ return box;\r
+ }\r
+};\r
+\r
+\r
+template<>\r
+struct get_ring<polygon_tag>\r
+{\r
+ template<typename Polygon>\r
+ static inline typename ring_return_type<Polygon const>::type const apply(\r
+ ring_identifier const& id,\r
+ Polygon const& polygon)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ id.ring_index >= -1\r
+ && id.ring_index < int(boost::size(interior_rings(polygon)))\r
+ );\r
+ return id.ring_index < 0\r
+ ? exterior_ring(polygon)\r
+ : range::at(interior_rings(polygon), id.ring_index);\r
+ }\r
+};\r
+\r
+\r
+template<>\r
+struct get_ring<multi_polygon_tag>\r
+{\r
+ template<typename MultiPolygon>\r
+ static inline typename ring_type<MultiPolygon>::type const& apply(\r
+ ring_identifier const& id,\r
+ MultiPolygon const& multi_polygon)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ id.multi_index >= 0\r
+ && id.multi_index < int(boost::size(multi_polygon))\r
+ );\r
+ return get_ring<polygon_tag>::apply(id,\r
+ range::at(multi_polygon, id.multi_index));\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/strategies/intersection_strategies.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+class turn_info_exception : public geometry::exception\r
+{\r
+ std::string message;\r
+public:\r
+\r
+ // NOTE: "char" will be replaced by enum in future version\r
+ inline turn_info_exception(char const method)\r
+ {\r
+ message = "Boost.Geometry Turn exception: ";\r
+ message += method;\r
+ }\r
+\r
+ virtual ~turn_info_exception() throw()\r
+ {}\r
+\r
+ virtual char const* what() const throw()\r
+ {\r
+ return message.c_str();\r
+ }\r
+};\r
+#endif\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+struct base_turn_handler\r
+{\r
+ // Returns true if both sides are opposite\r
+ static inline bool opposite(int side1, int side2)\r
+ {\r
+ // We cannot state side1 == -side2, because 0 == -0\r
+ // So either side1*side2==-1 or side1==-side2 && side1 != 0\r
+ return side1 * side2 == -1;\r
+ }\r
+\r
+ // Same side of a segment (not being 0)\r
+ static inline bool same(int side1, int side2)\r
+ {\r
+ return side1 * side2 == 1;\r
+ }\r
+\r
+ // Both continue\r
+ template <typename TurnInfo>\r
+ static inline void both(TurnInfo& ti, operation_type const op)\r
+ {\r
+ ti.operations[0].operation = op;\r
+ ti.operations[1].operation = op;\r
+ }\r
+\r
+ // If condition, first union/second intersection, else vice versa\r
+ template <typename TurnInfo>\r
+ static inline void ui_else_iu(bool condition, TurnInfo& ti)\r
+ {\r
+ ti.operations[0].operation = condition\r
+ ? operation_union : operation_intersection;\r
+ ti.operations[1].operation = condition\r
+ ? operation_intersection : operation_union;\r
+ }\r
+\r
+ // If condition, both union, else both intersection\r
+ template <typename TurnInfo>\r
+ static inline void uu_else_ii(bool condition, TurnInfo& ti)\r
+ {\r
+ both(ti, condition ? operation_union : operation_intersection);\r
+ }\r
+\r
+ template <typename TurnInfo, typename IntersectionInfo>\r
+ static inline void assign_point(TurnInfo& ti,\r
+ method_type method,\r
+ IntersectionInfo const& info, unsigned int index)\r
+ {\r
+ ti.method = method;\r
+\r
+ BOOST_GEOMETRY_ASSERT(index < info.count);\r
+\r
+ geometry::convert(info.intersections[index], ti.point);\r
+ ti.operations[0].fraction = info.fractions[index].robust_ra;\r
+ ti.operations[1].fraction = info.fractions[index].robust_rb;\r
+ }\r
+\r
+ template <typename IntersectionInfo>\r
+ static inline unsigned int non_opposite_to_index(IntersectionInfo const& info)\r
+ {\r
+ return info.fractions[0].robust_rb < info.fractions[1].robust_rb\r
+ ? 1 : 0;\r
+ }\r
+\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename TurnInfo\r
+>\r
+struct touch_interior : public base_turn_handler\r
+{\r
+ // Index: 0, P is the interior, Q is touching and vice versa\r
+ template\r
+ <\r
+ unsigned int Index,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo,\r
+ typename DirInfo,\r
+ typename SidePolicy\r
+ >\r
+ static inline void apply(\r
+ Point1 const& , Point1 const& , Point1 const& ,\r
+ Point2 const& , Point2 const& , Point2 const& ,\r
+ TurnInfo& ti,\r
+ IntersectionInfo const& intersection_info,\r
+ DirInfo const& dir_info,\r
+ SidePolicy const& side)\r
+ {\r
+ assign_point(ti, method_touch_interior, intersection_info, 0);\r
+\r
+ // Both segments of q touch segment p somewhere in its interior\r
+ // 1) We know: if q comes from LEFT or RIGHT\r
+ // (i.e. dir_info.sides.get<Index,0>() == 1 or -1)\r
+ // 2) Important is: if q_k goes to LEFT, RIGHT, COLLINEAR\r
+ // and, if LEFT/COLL, if it is lying LEFT or RIGHT w.r.t. q_i\r
+\r
+ BOOST_STATIC_ASSERT(Index <= 1);\r
+ static unsigned int const index_p = Index;\r
+ static unsigned int const index_q = 1 - Index;\r
+\r
+ int const side_qi_p = dir_info.sides.template get<index_q, 0>();\r
+ int const side_qk_p = side.qk_wrt_p1();\r
+\r
+ if (side_qi_p == -side_qk_p)\r
+ {\r
+ // Q crosses P from left->right or from right->left (test "ML1")\r
+ // Union: folow P (left->right) or Q (right->left)\r
+ // Intersection: other turn\r
+ unsigned int index = side_qk_p == -1 ? index_p : index_q;\r
+ ti.operations[index].operation = operation_union;\r
+ ti.operations[1 - index].operation = operation_intersection;\r
+ return;\r
+ }\r
+\r
+ int const side_qk_q = side.qk_wrt_q1();\r
+\r
+ if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1)\r
+ {\r
+ // Q turns left on the right side of P (test "MR3")\r
+ // Both directions for "intersection"\r
+ both(ti, operation_intersection);\r
+ }\r
+ else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)\r
+ {\r
+ // Q turns right on the left side of P (test "ML3")\r
+ // Union: take both operation\r
+ // Intersection: skip\r
+ both(ti, operation_union);\r
+ }\r
+ else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)\r
+ {\r
+ // Q turns left on the left side of P (test "ML2")\r
+ // or Q turns right on the right side of P (test "MR2")\r
+ // Union: take left turn (Q if Q turns left, P if Q turns right)\r
+ // Intersection: other turn\r
+ unsigned int index = side_qk_q == 1 ? index_q : index_p;\r
+ ti.operations[index].operation = operation_union;\r
+ ti.operations[1 - index].operation = operation_intersection;\r
+ }\r
+ else if (side_qk_p == 0)\r
+ {\r
+ // Q intersects on interior of P and continues collinearly\r
+ if (side_qk_q == side_qi_p)\r
+ {\r
+ // Collinearly in the same direction\r
+ // (Q comes from left of P and turns left,\r
+ // OR Q comes from right of P and turns right)\r
+ // Omit intersection point.\r
+ // Union: just continue\r
+ // Intersection: just continue\r
+ both(ti, operation_continue);\r
+ }\r
+ else\r
+ {\r
+ // Opposite direction, which is never travelled.\r
+ // If Q turns left, P continues for intersection\r
+ // If Q turns right, P continues for union\r
+ ti.operations[index_p].operation = side_qk_q == 1\r
+ ? operation_intersection\r
+ : operation_union;\r
+ ti.operations[index_q].operation = operation_blocked;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Should not occur!\r
+ ti.method = method_error;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename TurnInfo\r
+>\r
+struct touch : public base_turn_handler\r
+{\r
+ static inline bool between(int side1, int side2, int turn)\r
+ {\r
+ return side1 == side2 && ! opposite(side1, turn);\r
+ }\r
+\r
+ /*static inline void block_second(bool block, TurnInfo& ti)\r
+ {\r
+ if (block)\r
+ {\r
+ ti.operations[1].operation = operation_blocked;\r
+ }\r
+ }*/\r
+\r
+\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo,\r
+ typename DirInfo,\r
+ typename SidePolicy\r
+ >\r
+ static inline void apply(\r
+ Point1 const& , Point1 const& , Point1 const& ,\r
+ Point2 const& , Point2 const& , Point2 const& ,\r
+ TurnInfo& ti,\r
+ IntersectionInfo const& intersection_info,\r
+ DirInfo const& dir_info,\r
+ SidePolicy const& side)\r
+ {\r
+ assign_point(ti, method_touch, intersection_info, 0);\r
+\r
+ int const side_qi_p1 = dir_info.sides.template get<1, 0>();\r
+ int const side_qk_p1 = side.qk_wrt_p1();\r
+\r
+\r
+ // If Qi and Qk are both at same side of Pi-Pj,\r
+ // or collinear (so: not opposite sides)\r
+ if (! opposite(side_qi_p1, side_qk_p1))\r
+ {\r
+ int const side_pk_q2 = side.pk_wrt_q2();\r
+ int const side_pk_p = side.pk_wrt_p1();\r
+ int const side_qk_q = side.qk_wrt_q1();\r
+\r
+ bool const q_turns_left = side_qk_q == 1;\r
+ bool const block_q = side_qk_p1 == 0\r
+ && ! same(side_qi_p1, side_qk_q)\r
+ ;\r
+\r
+ // If Pk at same side as Qi/Qk\r
+ // (the "or" is for collinear case)\r
+ // or Q is fully collinear && P turns not to left\r
+ if (side_pk_p == side_qi_p1\r
+ || side_pk_p == side_qk_p1\r
+ || (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1)\r
+ )\r
+ {\r
+ // Collinear -> lines join, continue\r
+ // (#BRL2)\r
+ if (side_pk_q2 == 0 && ! block_q)\r
+ {\r
+ both(ti, operation_continue);\r
+ return;\r
+ }\r
+\r
+ int const side_pk_q1 = side.pk_wrt_q1();\r
+\r
+\r
+ // Collinear opposite case -> block P\r
+ // (#BRL4, #BLR8)\r
+ if (side_pk_q1 == 0)\r
+ {\r
+ ti.operations[0].operation = operation_blocked;\r
+ // Q turns right -> union (both independent),\r
+ // Q turns left -> intersection\r
+ ti.operations[1].operation = block_q ? operation_blocked\r
+ : q_turns_left ? operation_intersection\r
+ : operation_union;\r
+ return;\r
+ }\r
+\r
+ // Pk between Qi and Qk\r
+ // (#BRL3, #BRL7)\r
+ if (between(side_pk_q1, side_pk_q2, side_qk_q))\r
+ {\r
+ ui_else_iu(q_turns_left, ti);\r
+ if (block_q)\r
+ {\r
+ ti.operations[1].operation = operation_blocked;\r
+ }\r
+ //block_second(block_q, ti);\r
+ return;\r
+ }\r
+\r
+ // Pk between Qk and P, so left of Qk (if Q turns right) and vv\r
+ // (#BRL1)\r
+ if (side_pk_q2 == -side_qk_q)\r
+ {\r
+ ui_else_iu(! q_turns_left, ti);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // (#BRL5, #BRL9)\r
+ if (side_pk_q1 == -side_qk_q)\r
+ {\r
+ uu_else_ii(! q_turns_left, ti);\r
+ if (block_q)\r
+ {\r
+ ti.operations[1].operation = operation_blocked;\r
+ }\r
+ //block_second(block_q, ti);\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Pk at other side than Qi/Pk\r
+ ti.operations[0].operation = q_turns_left\r
+ ? operation_intersection\r
+ : operation_union;\r
+ ti.operations[1].operation = block_q\r
+ ? operation_blocked\r
+ : side_qi_p1 == 1 || side_qk_p1 == 1\r
+ ? operation_union\r
+ : operation_intersection;\r
+\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // From left to right or from right to left\r
+ int const side_pk_p = side.pk_wrt_p1();\r
+ bool const right_to_left = side_qk_p1 == 1;\r
+\r
+ // If p turns into direction of qi (1,2)\r
+ if (side_pk_p == side_qi_p1)\r
+ {\r
+ int const side_pk_q1 = side.pk_wrt_q1();\r
+\r
+ // Collinear opposite case -> block P\r
+ if (side_pk_q1 == 0)\r
+ {\r
+ ti.operations[0].operation = operation_blocked;\r
+ ti.operations[1].operation = right_to_left\r
+ ? operation_union : operation_intersection;\r
+ return;\r
+ }\r
+\r
+ if (side_pk_q1 == side_qk_p1)\r
+ {\r
+ uu_else_ii(right_to_left, ti);\r
+ return;\r
+ }\r
+ }\r
+\r
+ // If p turns into direction of qk (4,5)\r
+ if (side_pk_p == side_qk_p1)\r
+ {\r
+ int const side_pk_q2 = side.pk_wrt_q2();\r
+\r
+ // Collinear case -> lines join, continue\r
+ if (side_pk_q2 == 0)\r
+ {\r
+ both(ti, operation_continue);\r
+ return;\r
+ }\r
+ if (side_pk_q2 == side_qk_p1)\r
+ {\r
+ ui_else_iu(right_to_left, ti);\r
+ return;\r
+ }\r
+ }\r
+ // otherwise (3)\r
+ ui_else_iu(! right_to_left, ti);\r
+ return;\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS\r
+ // Normally a robustness issue.\r
+ // TODO: more research if still occuring\r
+ std::cout << "Not yet handled" << std::endl\r
+ << "pi " << get<0>(pi) << " , " << get<1>(pi)\r
+ << " pj " << get<0>(pj) << " , " << get<1>(pj)\r
+ << " pk " << get<0>(pk) << " , " << get<1>(pk)\r
+ << std::endl\r
+ << "qi " << get<0>(qi) << " , " << get<1>(qi)\r
+ << " qj " << get<0>(qj) << " , " << get<1>(qj)\r
+ << " qk " << get<0>(qk) << " , " << get<1>(qk)\r
+ << std::endl;\r
+#endif\r
+\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename TurnInfo\r
+>\r
+struct equal : public base_turn_handler\r
+{\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo,\r
+ typename DirInfo,\r
+ typename SidePolicy\r
+ >\r
+ static inline void apply(\r
+ Point1 const& , Point1 const& , Point1 const& ,\r
+ Point2 const& , Point2 const& , Point2 const& ,\r
+ TurnInfo& ti,\r
+ IntersectionInfo const& info,\r
+ DirInfo const& ,\r
+ SidePolicy const& side)\r
+ {\r
+ // Copy the intersection point in TO direction\r
+ assign_point(ti, method_equal, info, non_opposite_to_index(info));\r
+\r
+ int const side_pk_q2 = side.pk_wrt_q2();\r
+ int const side_pk_p = side.pk_wrt_p1();\r
+ int const side_qk_p = side.qk_wrt_p1();\r
+\r
+\r
+ // If pk is collinear with qj-qk, they continue collinearly.\r
+ // This can be on either side of p1 (== q1), or collinear\r
+ // The second condition checks if they do not continue\r
+ // oppositely\r
+ if (side_pk_q2 == 0 && side_pk_p == side_qk_p)\r
+ {\r
+ both(ti, operation_continue);\r
+\r
+ return;\r
+ }\r
+\r
+\r
+ // If they turn to same side (not opposite sides)\r
+ if (! opposite(side_pk_p, side_qk_p))\r
+ {\r
+ // If pk is left of q2 or collinear: p: union, q: intersection\r
+ ui_else_iu(side_pk_q2 != -1, ti);\r
+ }\r
+ else\r
+ {\r
+ // They turn opposite sides. If p turns left (or collinear),\r
+ // p: union, q: intersection\r
+ ui_else_iu(side_pk_p != -1, ti);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename TurnInfo,\r
+ typename AssignPolicy\r
+>\r
+struct equal_opposite : public base_turn_handler\r
+{\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename OutputIterator,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline void apply(Point1 const& pi, Point2 const& qi,\r
+ /* by value: */ TurnInfo tp,\r
+ OutputIterator& out,\r
+ IntersectionInfo const& intersection_info)\r
+ {\r
+ // For equal-opposite segments, normally don't do anything.\r
+ if (AssignPolicy::include_opposite)\r
+ {\r
+ tp.method = method_equal;\r
+ for (unsigned int i = 0; i < 2; i++)\r
+ {\r
+ tp.operations[i].operation = operation_opposite;\r
+ }\r
+ for (unsigned int i = 0; i < intersection_info.i_info().count; i++)\r
+ {\r
+ assign_point(tp, method_none, intersection_info.i_info(), i);\r
+ AssignPolicy::apply(tp, pi, qi, intersection_info);\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename TurnInfo\r
+>\r
+struct collinear : public base_turn_handler\r
+{\r
+ /*\r
+ arrival P pk//p1 qk//q1 product* case result\r
+ 1 1 1 CLL1 ui\r
+ -1 1 -1 CLL2 iu\r
+ 1 1 1 CLR1 ui\r
+ -1 -1 1 CLR2 ui\r
+\r
+ 1 -1 -1 CRL1 iu\r
+ -1 1 -1 CRL2 iu\r
+ 1 -1 -1 CRR1 iu\r
+ -1 -1 1 CRR2 ui\r
+\r
+ 1 0 0 CC1 cc\r
+ -1 0 0 CC2 cc\r
+\r
+ *product = arrival * (pk//p1 or qk//q1)\r
+\r
+ Stated otherwise:\r
+ - if P arrives: look at turn P\r
+ - if Q arrives: look at turn Q\r
+ - if P arrives and P turns left: union for P\r
+ - if P arrives and P turns right: intersection for P\r
+ - if Q arrives and Q turns left: union for Q (=intersection for P)\r
+ - if Q arrives and Q turns right: intersection for Q (=union for P)\r
+\r
+ ROBUSTNESS: p and q are collinear, so you would expect\r
+ that side qk//p1 == pk//q1. But that is not always the case\r
+ in near-epsilon ranges. Then decision logic is different.\r
+ If p arrives, q is further, so the angle qk//p1 is (normally)\r
+ more precise than pk//p1\r
+\r
+ */\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo,\r
+ typename DirInfo,\r
+ typename SidePolicy\r
+ >\r
+ static inline void apply(\r
+ Point1 const& , Point1 const& pj, Point1 const& pk,\r
+ Point2 const& , Point2 const& qj, Point2 const& qk,\r
+ TurnInfo& ti,\r
+ IntersectionInfo const& info,\r
+ DirInfo const& dir_info,\r
+ SidePolicy const& side)\r
+ {\r
+ // Copy the intersection point in TO direction\r
+ assign_point(ti, method_collinear, info, non_opposite_to_index(info));\r
+\r
+ int const arrival = dir_info.arrival[0];\r
+ // Should not be 0, this is checked before\r
+ BOOST_GEOMETRY_ASSERT(arrival != 0);\r
+\r
+ int const side_p = side.pk_wrt_p1();\r
+ int const side_q = side.qk_wrt_q1();\r
+\r
+ // If p arrives, use p, else use q\r
+ int const side_p_or_q = arrival == 1\r
+ ? side_p\r
+ : side_q\r
+ ;\r
+\r
+ // See comments above,\r
+ // resulting in a strange sort of mathematic rule here:\r
+ // The arrival-info multiplied by the relevant side\r
+ // delivers a consistent result.\r
+\r
+ int const product = arrival * side_p_or_q;\r
+\r
+ if(product == 0)\r
+ {\r
+ both(ti, operation_continue);\r
+ }\r
+ else\r
+ {\r
+ ui_else_iu(product == 1, ti);\r
+ }\r
+\r
+ // Calculate remaining distance. If it continues collinearly it is\r
+ // measured until the end of the next segment\r
+ ti.operations[0].remaining_distance\r
+ = side_p == 0\r
+ ? distance_measure(ti.point, pk)\r
+ : distance_measure(ti.point, pj);\r
+ ti.operations[1].remaining_distance\r
+ = side_q == 0\r
+ ? distance_measure(ti.point, qk)\r
+ : distance_measure(ti.point, qj);\r
+ }\r
+\r
+ template <typename Point1, typename Point2>\r
+ static inline typename geometry::coordinate_type<Point1>::type\r
+ distance_measure(Point1 const& a, Point2 const& b)\r
+ {\r
+ // TODO: use comparable distance for point-point instead - but that\r
+ // causes currently cycling include problems\r
+ typedef typename geometry::coordinate_type<Point1>::type ctype;\r
+ ctype const dx = get<0>(a) - get<0>(b);\r
+ ctype const dy = get<1>(b) - get<1>(b);\r
+ return dx * dx + dy * dy;\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename TurnInfo,\r
+ typename AssignPolicy\r
+>\r
+struct collinear_opposite : public base_turn_handler\r
+{\r
+private :\r
+ /*\r
+ arrival P arrival Q pk//p1 qk//q1 case result2 result\r
+ --------------------------------------------------------------\r
+ 1 1 1 -1 CLO1 ix xu\r
+ 1 1 1 0 CLO2 ix (xx)\r
+ 1 1 1 1 CLO3 ix xi\r
+\r
+ 1 1 0 -1 CCO1 (xx) xu\r
+ 1 1 0 0 CCO2 (xx) (xx)\r
+ 1 1 0 1 CCO3 (xx) xi\r
+\r
+ 1 1 -1 -1 CRO1 ux xu\r
+ 1 1 -1 0 CRO2 ux (xx)\r
+ 1 1 -1 1 CRO3 ux xi\r
+\r
+ -1 1 -1 CXO1 xu\r
+ -1 1 0 CXO2 (xx)\r
+ -1 1 1 CXO3 xi\r
+\r
+ 1 -1 1 CXO1 ix\r
+ 1 -1 0 CXO2 (xx)\r
+ 1 -1 -1 CXO3 ux\r
+ */\r
+\r
+ template\r
+ <\r
+ unsigned int Index,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline bool set_tp(Point1 const& , Point1 const& , Point1 const& , int side_rk_r,\r
+ bool const handle_robustness,\r
+ Point2 const& , Point2 const& , int side_rk_s,\r
+ TurnInfo& tp, IntersectionInfo const& intersection_info)\r
+ {\r
+ BOOST_STATIC_ASSERT(Index <= 1);\r
+\r
+ boost::ignore_unused(handle_robustness, side_rk_s);\r
+\r
+ operation_type blocked = operation_blocked;\r
+ switch(side_rk_r)\r
+ {\r
+\r
+ case 1 :\r
+ // Turning left on opposite collinear: intersection\r
+ tp.operations[Index].operation = operation_intersection;\r
+ break;\r
+ case -1 :\r
+ // Turning right on opposite collinear: union\r
+ tp.operations[Index].operation = operation_union;\r
+ break;\r
+ case 0 :\r
+ // No turn on opposite collinear: block, do not traverse\r
+ // But this "xx" is usually ignored, it is useless to include\r
+ // two operations blocked, so the whole point does not need\r
+ // to be generated.\r
+ // So return false to indicate nothing is to be done.\r
+ if (AssignPolicy::include_opposite)\r
+ {\r
+ tp.operations[Index].operation = operation_opposite;\r
+ blocked = operation_opposite;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ }\r
+ break;\r
+ }\r
+\r
+ // The other direction is always blocked when collinear opposite\r
+ tp.operations[1 - Index].operation = blocked;\r
+\r
+ // If P arrives within Q, set info on P (which is done above, index=0),\r
+ // this turn-info belongs to the second intersection point, index=1\r
+ // (see e.g. figure CLO1)\r
+ assign_point(tp, method_collinear, intersection_info, 1 - Index);\r
+ return true;\r
+ }\r
+\r
+public:\r
+ static inline void empty_transformer(TurnInfo &) {}\r
+\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename OutputIterator,\r
+ typename IntersectionInfo,\r
+ typename SidePolicy\r
+ >\r
+ static inline void apply(\r
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+\r
+ // Opposite collinear can deliver 2 intersection points,\r
+ TurnInfo const& tp_model,\r
+ OutputIterator& out,\r
+\r
+ IntersectionInfo const& intersection_info,\r
+ SidePolicy const& side)\r
+ {\r
+ apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer);\r
+ }\r
+\r
+public:\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename OutputIterator,\r
+ typename IntersectionInfo,\r
+ typename SidePolicy,\r
+ typename TurnTransformer\r
+ >\r
+ static inline void apply(\r
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+\r
+ // Opposite collinear can deliver 2 intersection points,\r
+ TurnInfo const& tp_model,\r
+ OutputIterator& out,\r
+\r
+ IntersectionInfo const& info,\r
+ SidePolicy const& side,\r
+ TurnTransformer turn_transformer,\r
+ bool const is_pk_valid = true, bool const is_qk_valid = true)\r
+ {\r
+ TurnInfo tp = tp_model;\r
+\r
+ int const p_arrival = info.d_info().arrival[0];\r
+ int const q_arrival = info.d_info().arrival[1];\r
+\r
+ // If P arrives within Q, there is a turn dependent on P\r
+ if ( p_arrival == 1\r
+ && is_pk_valid\r
+ && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) )\r
+ {\r
+ turn_transformer(tp);\r
+\r
+ AssignPolicy::apply(tp, pi, qi, info);\r
+ *out++ = tp;\r
+ }\r
+\r
+ // If Q arrives within P, there is a turn dependent on Q\r
+ if ( q_arrival == 1\r
+ && is_qk_valid\r
+ && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) )\r
+ {\r
+ turn_transformer(tp);\r
+\r
+ AssignPolicy::apply(tp, pi, qi, info);\r
+ *out++ = tp;\r
+ }\r
+\r
+ if (AssignPolicy::include_opposite)\r
+ {\r
+ // Handle cases not yet handled above\r
+ if ((q_arrival == -1 && p_arrival == 0)\r
+ || (p_arrival == -1 && q_arrival == 0))\r
+ {\r
+ for (unsigned int i = 0; i < 2; i++)\r
+ {\r
+ tp.operations[i].operation = operation_opposite;\r
+ }\r
+ for (unsigned int i = 0; i < info.i_info().count; i++)\r
+ {\r
+ assign_point(tp, method_collinear, info.i_info(), i);\r
+ AssignPolicy::apply(tp, pi, qi, info);\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename TurnInfo\r
+>\r
+struct crosses : public base_turn_handler\r
+{\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo,\r
+ typename DirInfo\r
+ >\r
+ static inline void apply(\r
+ Point1 const& , Point1 const& , Point1 const& ,\r
+ Point2 const& , Point2 const& , Point2 const& ,\r
+ TurnInfo& ti,\r
+ IntersectionInfo const& intersection_info,\r
+ DirInfo const& dir_info)\r
+ {\r
+ assign_point(ti, method_crosses, intersection_info, 0);\r
+\r
+ // In all casees:\r
+ // If Q crosses P from left to right\r
+ // Union: take P\r
+ // Intersection: take Q\r
+ // Otherwise: vice versa\r
+ int const side_qi_p1 = dir_info.sides.template get<1, 0>();\r
+ unsigned int const index = side_qi_p1 == 1 ? 0 : 1;\r
+ ti.operations[index].operation = operation_union;\r
+ ti.operations[1 - index].operation = operation_intersection;\r
+ }\r
+};\r
+\r
+struct only_convert : public base_turn_handler\r
+{\r
+ template<typename TurnInfo, typename IntersectionInfo>\r
+ static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info)\r
+ {\r
+ assign_point(ti, method_none, intersection_info, 0); // was collinear\r
+ ti.operations[0].operation = operation_continue;\r
+ ti.operations[1].operation = operation_continue;\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Policy doing nothing\r
+\details get_turn_info can have an optional policy to get/assign some\r
+ extra information. By default it does not, and this class\r
+ is that default.\r
+ */\r
+struct assign_null_policy\r
+{\r
+ static bool const include_no_turn = false;\r
+ static bool const include_degenerate = false;\r
+ static bool const include_opposite = false;\r
+\r
+ template\r
+ <\r
+ typename Info,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&)\r
+ {}\r
+\r
+};\r
+\r
+\r
+/*!\r
+ \brief Turn information: intersection point, method, and turn information\r
+ \details Information necessary for traversal phase (a phase\r
+ of the overlay process). The information is gathered during the\r
+ get_turns (segment intersection) phase.\r
+ \tparam Point1 point type of first segment\r
+ \tparam Point2 point type of second segment\r
+ \tparam TurnInfo type of class getting intersection and turn info\r
+ \tparam AssignPolicy policy to assign extra info,\r
+ e.g. to calculate distance from segment's first points\r
+ to intersection points.\r
+ It also defines if a certain class of points\r
+ (degenerate, non-turns) should be included.\r
+ */\r
+template<typename AssignPolicy>\r
+struct get_turn_info\r
+{\r
+ // Intersect pi-pj with qi-qj\r
+ // The points pk and qk are used do determine more information\r
+ // about the turn (turn left/right)\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo,\r
+ typename RobustPolicy,\r
+ typename OutputIterator\r
+ >\r
+ static inline OutputIterator apply(\r
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ bool /*is_p_first*/, bool /*is_p_last*/,\r
+ bool /*is_q_first*/, bool /*is_q_last*/,\r
+ TurnInfo const& tp_model,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out)\r
+ {\r
+ typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>\r
+ inters_info;\r
+\r
+ inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);\r
+\r
+ char const method = inters.d_info().how;\r
+\r
+ // Copy, to copy possibly extended fields\r
+ TurnInfo tp = tp_model;\r
+\r
+ // Select method and apply\r
+ switch(method)\r
+ {\r
+ case 'a' : // collinear, "at"\r
+ case 'f' : // collinear, "from"\r
+ case 's' : // starts from the middle\r
+ if (AssignPolicy::include_no_turn\r
+ && inters.i_info().count > 0)\r
+ {\r
+ only_convert::apply(tp, inters.i_info());\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ break;\r
+\r
+ case 'd' : // disjoint: never do anything\r
+ break;\r
+\r
+ case 'm' :\r
+ {\r
+ typedef touch_interior\r
+ <\r
+ TurnInfo\r
+ > policy;\r
+\r
+ // If Q (1) arrives (1)\r
+ if ( inters.d_info().arrival[1] == 1 )\r
+ {\r
+ policy::template apply<0>(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(),\r
+ inters.sides());\r
+ }\r
+ else\r
+ {\r
+ // Swap p/q\r
+ side_calculator\r
+ <\r
+ typename inters_info::cs_tag,\r
+ typename inters_info::robust_point2_type,\r
+ typename inters_info::robust_point1_type\r
+ > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),\r
+ inters.rpi(), inters.rpj(), inters.rpk());\r
+ policy::template apply<1>(qi, qj, qk, pi, pj, pk,\r
+ tp, inters.i_info(), inters.d_info(),\r
+ swapped_side_calc);\r
+ }\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ break;\r
+ case 'i' :\r
+ {\r
+ crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info());\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ break;\r
+ case 't' :\r
+ {\r
+ // Both touch (both arrive there)\r
+ touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ break;\r
+ case 'e':\r
+ {\r
+ if ( ! inters.d_info().opposite )\r
+ {\r
+ // Both equal\r
+ // or collinear-and-ending at intersection point\r
+ equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ else\r
+ {\r
+ equal_opposite\r
+ <\r
+ TurnInfo,\r
+ AssignPolicy\r
+ >::apply(pi, qi,\r
+ tp, out, inters);\r
+ }\r
+ }\r
+ break;\r
+ case 'c' :\r
+ {\r
+ // Collinear\r
+ if ( ! inters.d_info().opposite )\r
+ {\r
+\r
+ if ( inters.d_info().arrival[0] == 0 )\r
+ {\r
+ // Collinear, but similar thus handled as equal\r
+ equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ // override assigned method\r
+ tp.method = method_collinear;\r
+ }\r
+ else\r
+ {\r
+ collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+ }\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ else\r
+ {\r
+ collinear_opposite\r
+ <\r
+ TurnInfo,\r
+ AssignPolicy\r
+ >::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, out, inters, inters.sides());\r
+ }\r
+ }\r
+ break;\r
+ case '0' :\r
+ {\r
+ // degenerate points\r
+ if (AssignPolicy::include_degenerate)\r
+ {\r
+ only_convert::apply(tp, inters.i_info());\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ break;\r
+ default :\r
+ {\r
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)\r
+ std::cout << "TURN: Unknown method: " << method << std::endl;\r
+#endif\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+ throw turn_info_exception(method);\r
+#endif\r
+ }\r
+ break;\r
+ }\r
+\r
+ return out;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay {\r
+\r
+// SEGMENT_INTERSECTION RESULT\r
+\r
+// C H0 H1 A0 A1 O IP1 IP2\r
+\r
+// D0 and D1 == 0\r
+\r
+// |--------> 2 0 0 0 0 F i/i x/x\r
+// |-------->\r
+//\r
+// |--------> 2 0 0 0 0 T i/x x/i\r
+// <--------|\r
+//\r
+// |-----> 1 0 0 0 0 T x/x\r
+// <-----|\r
+//\r
+\r
+// |---------> 2 0 0 0 1 T i/x x/i\r
+// <----|\r
+//\r
+// |---------> 2 0 0 0 0 F i/i x/x\r
+// |---->\r
+//\r
+// |---------> 2 0 0 -1 1 F i/i u/x\r
+// |---->\r
+//\r
+// |---------> 2 0 0 -1 0 T i/x u/i\r
+// <----|\r
+\r
+// |-------> 2 0 0 1 -1 F and i/i x/u\r
+// |-------> 2 0 0 -1 1 F symetric i/i u/x\r
+// |------->\r
+//\r
+// |-------> 2 0 0 -1 -1 T i/u u/i\r
+// <-------|\r
+//\r
+// |-------> 2 0 0 1 1 T i/x x/i\r
+// <-------|\r
+//\r
+// |--------> 2 0 0 -1 1 F i/i u/x\r
+// |---->\r
+//\r
+// |--------> 2 0 0 -1 1 T i/x u/i\r
+// <----|\r
+\r
+// |-----> 1 -1 -1 -1 -1 T u/u\r
+// <-----|\r
+//\r
+// |-----> 1 -1 0 -1 0 F and u/x\r
+// |-----> 1 0 -1 0 -1 F symetric x/u\r
+// |----->\r
+\r
+// D0 or D1 != 0\r
+\r
+// ^\r
+// |\r
+// + 1 -1 1 -1 1 F and u/x (P is vertical)\r
+// |--------> 1 1 -1 1 -1 F symetric x/u (P is horizontal)\r
+// ^\r
+// |\r
+// +\r
+//\r
+// +\r
+// |\r
+// v\r
+// |--------> 1 1 1 1 1 F x/x (P is vertical)\r
+//\r
+// ^\r
+// |\r
+// +\r
+// |--------> 1 -1 -1 -1 -1 F u/u (P is vertical)\r
+//\r
+// ^\r
+// |\r
+// +\r
+// |--------> 1 0 -1 0 -1 F u/u (P is vertical)\r
+//\r
+// +\r
+// |\r
+// v\r
+// |--------> 1 0 1 0 1 F u/x (P is vertical)\r
+//\r
+\r
+class linear_intersections\r
+{\r
+public:\r
+ template <typename Point1, typename Point2, typename IntersectionResult>\r
+ linear_intersections(Point1 const& pi,\r
+ Point2 const& qi,\r
+ IntersectionResult const& result,\r
+ bool is_p_last, bool is_q_last)\r
+ {\r
+ int arrival_a = result.template get<1>().arrival[0];\r
+ int arrival_b = result.template get<1>().arrival[1];\r
+ bool same_dirs = result.template get<1>().dir_a == 0\r
+ && result.template get<1>().dir_b == 0;\r
+\r
+ if ( same_dirs )\r
+ {\r
+ if ( result.template get<0>().count == 2 )\r
+ {\r
+ if ( ! result.template get<1>().opposite )\r
+ {\r
+ ips[0].p_operation = operation_intersection;\r
+ ips[0].q_operation = operation_intersection;\r
+ ips[1].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);\r
+ ips[1].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);\r
+\r
+ ips[0].is_pi\r
+ = equals::equals_point_point(\r
+ pi, result.template get<0>().intersections[0]);\r
+ ips[0].is_qi\r
+ = equals::equals_point_point(\r
+ qi, result.template get<0>().intersections[0]);\r
+ ips[1].is_pj = arrival_a != -1;\r
+ ips[1].is_qj = arrival_b != -1;\r
+ }\r
+ else\r
+ {\r
+ ips[0].p_operation = operation_intersection;\r
+ ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);\r
+ ips[1].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);\r
+ ips[1].q_operation = operation_intersection;\r
+\r
+ ips[0].is_pi = arrival_b != 1;\r
+ ips[0].is_qj = arrival_b != -1;\r
+ ips[1].is_pj = arrival_a != -1;\r
+ ips[1].is_qi = arrival_a != 1;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(result.template get<0>().count == 1);\r
+ ips[0].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last);\r
+ ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last);\r
+\r
+ ips[0].is_pi = arrival_a == -1;\r
+ ips[0].is_qi = arrival_b == -1;\r
+ ips[0].is_pj = arrival_a == 0;\r
+ ips[0].is_qj = arrival_b == 0;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ips[0].p_operation = union_or_blocked_different_dirs(arrival_a, is_p_last);\r
+ ips[0].q_operation = union_or_blocked_different_dirs(arrival_b, is_q_last);\r
+\r
+ ips[0].is_pi = arrival_a == -1;\r
+ ips[0].is_qi = arrival_b == -1;\r
+ ips[0].is_pj = arrival_a == 1;\r
+ ips[0].is_qj = arrival_b == 1;\r
+ }\r
+ }\r
+\r
+ struct ip_info\r
+ {\r
+ inline ip_info()\r
+ : p_operation(operation_none), q_operation(operation_none)\r
+ , is_pi(false), is_pj(false), is_qi(false), is_qj(false)\r
+ {}\r
+\r
+ operation_type p_operation, q_operation;\r
+ bool is_pi, is_pj, is_qi, is_qj;\r
+ };\r
+\r
+ template <std::size_t I>\r
+ ip_info const& get() const\r
+ {\r
+ BOOST_STATIC_ASSERT(I < 2);\r
+ return ips[I];\r
+ }\r
+ \r
+private:\r
+\r
+ // only if collinear (same_dirs)\r
+ static inline operation_type union_or_blocked_same_dirs(int arrival, bool is_last)\r
+ {\r
+ if ( arrival == 1 )\r
+ return operation_blocked;\r
+ else if ( arrival == -1 )\r
+ return operation_union;\r
+ else\r
+ return is_last ? operation_blocked : operation_union;\r
+ //return operation_blocked;\r
+ }\r
+\r
+ // only if not collinear (!same_dirs)\r
+ static inline operation_type union_or_blocked_different_dirs(int arrival, bool is_last)\r
+ {\r
+ if ( arrival == 1 )\r
+ //return operation_blocked;\r
+ return is_last ? operation_blocked : operation_union;\r
+ else\r
+ return operation_union;\r
+ }\r
+\r
+ ip_info ips[2];\r
+};\r
+\r
+template <typename AssignPolicy, bool EnableFirst, bool EnableLast>\r
+struct get_turn_info_for_endpoint\r
+{\r
+ BOOST_STATIC_ASSERT(EnableFirst || EnableLast);\r
+\r
+ template<typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutputIterator\r
+ >\r
+ static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ bool is_p_first, bool is_p_last,\r
+ bool is_q_first, bool is_q_last,\r
+ TurnInfo const& tp_model,\r
+ IntersectionInfo const& inters,\r
+ method_type /*method*/,\r
+ OutputIterator out)\r
+ {\r
+ std::size_t ip_count = inters.i_info().count;\r
+ // no intersection points\r
+ if ( ip_count == 0 )\r
+ return false;\r
+\r
+ if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last )\r
+ return false;\r
+\r
+ linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);\r
+\r
+ bool append0_last\r
+ = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ intersections.template get<0>(),\r
+ tp_model, inters, 0, out);\r
+\r
+ // NOTE: opposite && ip_count == 1 may be true!\r
+ bool opposite = inters.d_info().opposite;\r
+\r
+ // don't ignore only for collinear opposite\r
+ bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite );\r
+\r
+ if ( intersections.template get<1>().p_operation == operation_none )\r
+ return result_ignore_ip0;\r
+ \r
+ bool append1_last\r
+ = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ intersections.template get<1>(),\r
+ tp_model, inters, 1, out);\r
+\r
+ // don't ignore only for collinear opposite\r
+ bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/;\r
+\r
+ return result_ignore_ip0 || result_ignore_ip1;\r
+ }\r
+\r
+ template <typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutputIterator>\r
+ static inline\r
+ bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ bool is_p_first, bool is_p_last,\r
+ bool is_q_first, bool is_q_last,\r
+ linear_intersections::ip_info const& ip_info,\r
+ TurnInfo const& tp_model,\r
+ IntersectionInfo const& inters,\r
+ unsigned int ip_index,\r
+ OutputIterator out)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR\r
+ // may this give false positives for INTs?\r
+ typename IntersectionResult::point_type const&\r
+ inters_pt = result.template get<0>().intersections[ip_index];\r
+ BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt));\r
+ BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt));\r
+ BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt));\r
+ BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt));\r
+#endif\r
+\r
+ // TODO - calculate first/last only if needed\r
+ bool is_p_first_ip = is_p_first && ip_info.is_pi;\r
+ bool is_p_last_ip = is_p_last && ip_info.is_pj;\r
+ bool is_q_first_ip = is_q_first && ip_info.is_qi;\r
+ bool is_q_last_ip = is_q_last && ip_info.is_qj;\r
+ bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip);\r
+ bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip);\r
+\r
+ operation_type p_operation = ip_info.p_operation;\r
+ operation_type q_operation = ip_info.q_operation;\r
+\r
+ if ( append_first || append_last )\r
+ {\r
+ bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk,\r
+ inters.rpi(), inters.rpj(), inters.rpk(),\r
+ inters.rqi(), inters.rqj(), inters.rqk(),\r
+ is_p_first_ip, is_p_last_ip,\r
+ is_q_first_ip, is_q_last_ip,\r
+ ip_info.is_qi, ip_info.is_qj,\r
+ tp_model, inters, ip_index,\r
+ p_operation, q_operation);\r
+ if ( !handled )\r
+ {\r
+ handle_internal<1>(qi, qj, qk, pi, pj, pk,\r
+ inters.rqi(), inters.rqj(), inters.rqk(),\r
+ inters.rpi(), inters.rpj(), inters.rpk(),\r
+ is_q_first_ip, is_q_last_ip,\r
+ is_p_first_ip, is_p_last_ip,\r
+ ip_info.is_pi, ip_info.is_pj,\r
+ tp_model, inters, ip_index,\r
+ q_operation, p_operation);\r
+ }\r
+\r
+ if ( p_operation != operation_none )\r
+ {\r
+ method_type method = endpoint_ip_method(ip_info.is_pi, ip_info.is_pj,\r
+ ip_info.is_qi, ip_info.is_qj);\r
+ turn_position p_pos = ip_position(is_p_first_ip, is_p_last_ip);\r
+ turn_position q_pos = ip_position(is_q_first_ip, is_q_last_ip);\r
+\r
+ // handle spikes\r
+\r
+ // P is spike and should be handled\r
+ if ( !is_p_last\r
+ && ip_info.is_pj // this check is redundant (also in is_spike_p) but faster\r
+ && inters.i_info().count == 2\r
+ && inters.is_spike_p() )\r
+ {\r
+ assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation,\r
+ p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out);\r
+ assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation,\r
+ p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out);\r
+ }\r
+ // Q is spike and should be handled\r
+ else if ( !is_q_last\r
+ && ip_info.is_qj // this check is redundant (also in is_spike_q) but faster\r
+ && inters.i_info().count == 2\r
+ && inters.is_spike_q() )\r
+ {\r
+ assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked,\r
+ p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out);\r
+ assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection,\r
+ p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out);\r
+ }\r
+ // no spikes\r
+ else\r
+ {\r
+ assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation,\r
+ p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, false, tp_model, out);\r
+ }\r
+ }\r
+ }\r
+\r
+ return append_last;\r
+ }\r
+\r
+ // TODO: IT'S ALSO PROBABLE THAT ALL THIS FUNCTION COULD BE INTEGRATED WITH handle_segment\r
+ // however now it's lazily calculated and then it would be always calculated\r
+\r
+ template<std::size_t G1Index,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename RobustPoint1,\r
+ typename RobustPoint2,\r
+ typename TurnInfo,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/,\r
+ Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/,\r
+ RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/,\r
+ RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2,\r
+ bool first1, bool last1, bool first2, bool last2,\r
+ bool ip_i2, bool ip_j2, TurnInfo const& tp_model,\r
+ IntersectionInfo const& inters, unsigned int ip_index,\r
+ operation_type & op1, operation_type & op2)\r
+ {\r
+ typedef typename cs_tag<typename TurnInfo::point_type>::type cs_tag;\r
+\r
+ boost::ignore_unused_variable_warning(i2);\r
+ boost::ignore_unused_variable_warning(j2);\r
+ boost::ignore_unused_variable_warning(ip_index);\r
+ boost::ignore_unused_variable_warning(tp_model);\r
+\r
+ if ( !first2 && !last2 )\r
+ {\r
+ if ( first1 )\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR\r
+ // may this give false positives for INTs?\r
+ typename IntersectionResult::point_type const&\r
+ inters_pt = inters.i_info().intersections[ip_index];\r
+ BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));\r
+ BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));\r
+#endif\r
+ if ( ip_i2 )\r
+ {\r
+ // don't output this IP - for the first point of other geometry segment\r
+ op1 = operation_none;\r
+ op2 = operation_none;\r
+ return true;\r
+ }\r
+ else if ( ip_j2 )\r
+ {\r
+ side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2>\r
+ side_calc(ri2, ri1, rj1, ri2, rj2, rk2);\r
+\r
+ std::pair<operation_type, operation_type>\r
+ operations = operations_of_equal(side_calc);\r
+\r
+// TODO: must the above be calculated?\r
+// wouldn't it be enough to check if segments are collinear?\r
+\r
+ if ( operations_both(operations, operation_continue) )\r
+ {\r
+ if ( op1 != operation_union \r
+ || op2 != operation_union\r
+ || ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) )\r
+ {\r
+ // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE!\r
+ bool opposite = inters.d_info().opposite;\r
+\r
+ op1 = operation_intersection;\r
+ op2 = opposite ? operation_union : operation_intersection;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union));\r
+ //op1 = operation_union;\r
+ //op2 = operation_union;\r
+ }\r
+\r
+ return true;\r
+ }\r
+ // else do nothing - shouldn't be handled this way\r
+ }\r
+ else if ( last1 )\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR\r
+ // may this give false positives for INTs?\r
+ typename IntersectionResult::point_type const&\r
+ inters_pt = inters.i_info().intersections[ip_index];\r
+ BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt));\r
+ BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt));\r
+#endif\r
+ if ( ip_i2 )\r
+ {\r
+ // don't output this IP - for the first point of other geometry segment\r
+ op1 = operation_none;\r
+ op2 = operation_none;\r
+ return true;\r
+ }\r
+ else if ( ip_j2 )\r
+ {\r
+ side_calculator<cs_tag, RobustPoint1, RobustPoint2, RobustPoint2>\r
+ side_calc(ri2, rj1, ri1, ri2, rj2, rk2);\r
+ \r
+ std::pair<operation_type, operation_type>\r
+ operations = operations_of_equal(side_calc);\r
+\r
+// TODO: must the above be calculated?\r
+// wouldn't it be enough to check if segments are collinear?\r
+\r
+ if ( operations_both(operations, operation_continue) )\r
+ {\r
+ if ( op1 != operation_blocked\r
+ || op2 != operation_union\r
+ || ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) )\r
+ {\r
+ // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE!\r
+ bool second_going_out = inters.i_info().count > 1;\r
+\r
+ op1 = operation_blocked;\r
+ op2 = second_going_out ? operation_union : operation_intersection;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union));\r
+ //op1 = operation_blocked;\r
+ //op2 = operation_union;\r
+ }\r
+\r
+ return true;\r
+ }\r
+ // else do nothing - shouldn't be handled this way\r
+ }\r
+ // else do nothing - shouldn't be handled this way\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ static inline method_type endpoint_ip_method(bool ip_pi, bool ip_pj, bool ip_qi, bool ip_qj)\r
+ {\r
+ if ( (ip_pi || ip_pj) && (ip_qi || ip_qj) )\r
+ return method_touch;\r
+ else\r
+ return method_touch_interior;\r
+ }\r
+\r
+ static inline turn_position ip_position(bool is_ip_first_i, bool is_ip_last_j)\r
+ {\r
+ return is_ip_first_i ? position_front :\r
+ ( is_ip_last_j ? position_back : position_middle );\r
+ }\r
+\r
+ template <typename Point1,\r
+ typename Point2,\r
+ typename IntersectionResult,\r
+ typename TurnInfo,\r
+ typename OutputIterator>\r
+ static inline void assign(Point1 const& pi, Point2 const& qi,\r
+ IntersectionResult const& result,\r
+ unsigned int ip_index,\r
+ method_type method,\r
+ operation_type op0, operation_type op1,\r
+ turn_position pos0, turn_position pos1,\r
+ bool is_p_first_ip, bool is_q_first_ip,\r
+ bool is_p_spike, bool is_q_spike,\r
+ TurnInfo const& tp_model,\r
+ OutputIterator out)\r
+ {\r
+ TurnInfo tp = tp_model;\r
+ \r
+ //geometry::convert(ip, tp.point);\r
+ //tp.method = method;\r
+ base_turn_handler::assign_point(tp, method, result.template get<0>(), ip_index);\r
+\r
+ tp.operations[0].operation = op0;\r
+ tp.operations[1].operation = op1;\r
+ tp.operations[0].position = pos0;\r
+ tp.operations[1].position = pos1;\r
+\r
+ if ( result.template get<0>().count > 1 )\r
+ {\r
+ // NOTE: is_collinear is NOT set for the first endpoint\r
+ // for which there is no preceding segment\r
+\r
+ //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );\r
+ if ( ! is_p_first_ip )\r
+ {\r
+ tp.operations[0].is_collinear = op0 != operation_intersection\r
+ || is_p_spike;\r
+ }\r
+\r
+ if ( ! is_q_first_ip )\r
+ {\r
+ tp.operations[1].is_collinear = op1 != operation_intersection\r
+ || is_q_spike;\r
+ }\r
+ }\r
+ else //if ( result.template get<0>().count == 1 )\r
+ {\r
+ if ( op0 == operation_blocked && op1 == operation_intersection )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+ else if ( op0 == operation_intersection && op1 == operation_blocked )\r
+ {\r
+ tp.operations[1].is_collinear = true;\r
+ }\r
+ }\r
+\r
+ // TODO: this should get an intersection_info, which is unavailable here\r
+ // Because the assign_null policy accepts any structure, we pass the result instead for now\r
+ AssignPolicy::apply(tp, pi, qi, result);\r
+ *out++ = tp;\r
+ }\r
+\r
+ template <typename SidePolicy>\r
+ static inline std::pair<operation_type, operation_type> operations_of_equal(SidePolicy const& side)\r
+ {\r
+ int const side_pk_q2 = side.pk_wrt_q2();\r
+ int const side_pk_p = side.pk_wrt_p1();\r
+ int const side_qk_p = side.qk_wrt_p1();\r
+\r
+ // If pk is collinear with qj-qk, they continue collinearly.\r
+ // This can be on either side of p1 (== q1), or collinear\r
+ // The second condition checks if they do not continue\r
+ // oppositely\r
+ if ( side_pk_q2 == 0 && side_pk_p == side_qk_p )\r
+ {\r
+ return std::make_pair(operation_continue, operation_continue);\r
+ }\r
+\r
+ // If they turn to same side (not opposite sides)\r
+ if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) )\r
+ {\r
+ // If pk is left of q2 or collinear: p: union, q: intersection\r
+ if ( side_pk_q2 != -1 )\r
+ {\r
+ return std::make_pair(operation_union, operation_intersection);\r
+ }\r
+ else\r
+ {\r
+ return std::make_pair(operation_intersection, operation_union);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // They turn opposite sides. If p turns left (or collinear),\r
+ // p: union, q: intersection\r
+ if ( side_pk_p != -1 )\r
+ {\r
+ return std::make_pair(operation_union, operation_intersection);\r
+ }\r
+ else\r
+ {\r
+ return std::make_pair(operation_intersection, operation_union);\r
+ }\r
+ }\r
+ }\r
+\r
+ static inline bool operations_both(\r
+ std::pair<operation_type, operation_type> const& operations,\r
+ operation_type const op)\r
+ {\r
+ return operations.first == op && operations.second == op;\r
+ }\r
+\r
+ static inline bool operations_combination(\r
+ std::pair<operation_type, operation_type> const& operations,\r
+ operation_type const op1, operation_type const op2)\r
+ {\r
+ return ( operations.first == op1 && operations.second == op2 )\r
+ || ( operations.first == op2 && operations.second == op1 );\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP\r
+\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay {\r
+\r
+enum turn_position { position_middle, position_front, position_back };\r
+\r
+template <typename Point, typename SegmentRatio>\r
+struct turn_operation_linear\r
+ : public turn_operation<Point, SegmentRatio>\r
+{\r
+ turn_operation_linear()\r
+ : position(position_middle)\r
+ , is_collinear(false)\r
+ {}\r
+\r
+ turn_position position;\r
+ bool is_collinear; // valid only for Linear geometry\r
+};\r
+\r
+template <typename TurnPointCSTag, typename PointP, typename PointQ,\r
+ typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,\r
+ typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ\r
+>\r
+struct side_calculator\r
+{\r
+ // This strategy should be the same as side strategy defined in\r
+ // intersection_strategies<> which is used in various places\r
+ // of the library\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ TurnPointCSTag\r
+ >::type side;\r
+\r
+ inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,\r
+ Qi const& qi, Qj const& qj, Qk const& qk)\r
+ : m_pi(pi), m_pj(pj), m_pk(pk)\r
+ , m_qi(qi), m_qj(qj), m_qk(qk)\r
+ {}\r
+\r
+ inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); }\r
+ inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); }\r
+ inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); }\r
+ inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); }\r
+\r
+ inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); }\r
+ inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); }\r
+\r
+ Pi const& m_pi;\r
+ Pj const& m_pj;\r
+ Pk const& m_pk;\r
+ Qi const& m_qi;\r
+ Qj const& m_qj;\r
+ Qk const& m_qk;\r
+};\r
+\r
+template <typename Point1, typename Point2, typename RobustPolicy>\r
+struct robust_points\r
+{\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ Point1, RobustPolicy\r
+ >::type robust_point1_type;\r
+\r
+ // TODO: define robust_point2_type using Point2?\r
+ typedef robust_point1_type robust_point2_type;\r
+\r
+ inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ geometry::recalculate(m_rpi, pi, robust_policy);\r
+ geometry::recalculate(m_rpj, pj, robust_policy);\r
+ geometry::recalculate(m_rpk, pk, robust_policy);\r
+ geometry::recalculate(m_rqi, qi, robust_policy);\r
+ geometry::recalculate(m_rqj, qj, robust_policy);\r
+ geometry::recalculate(m_rqk, qk, robust_policy);\r
+ }\r
+\r
+ robust_point1_type m_rpi, m_rpj, m_rpk;\r
+ robust_point2_type m_rqi, m_rqj, m_rqk;\r
+};\r
+\r
+template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>\r
+class intersection_info_base\r
+ : private robust_points<Point1, Point2, RobustPolicy>\r
+{\r
+ typedef robust_points<Point1, Point2, RobustPolicy> base;\r
+\r
+public:\r
+ typedef Point1 point1_type;\r
+ typedef Point2 point2_type;\r
+\r
+ typedef typename base::robust_point1_type robust_point1_type;\r
+ typedef typename base::robust_point2_type robust_point2_type;\r
+\r
+ typedef typename cs_tag<TurnPoint>::type cs_tag;\r
+\r
+ typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type> side_calculator_type;\r
+ \r
+ intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ RobustPolicy const& robust_policy)\r
+ : base(pi, pj, pk, qi, qj, qk, robust_policy)\r
+ , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk,\r
+ base::m_rqi, base::m_rqj, base::m_rqk)\r
+ , m_pi(pi), m_pj(pj), m_pk(pk)\r
+ , m_qi(qi), m_qj(qj), m_qk(qk)\r
+ {}\r
+\r
+ inline Point1 const& pi() const { return m_pi; }\r
+ inline Point1 const& pj() const { return m_pj; }\r
+ inline Point1 const& pk() const { return m_pk; }\r
+\r
+ inline Point2 const& qi() const { return m_qi; }\r
+ inline Point2 const& qj() const { return m_qj; }\r
+ inline Point2 const& qk() const { return m_qk; }\r
+\r
+ inline robust_point1_type const& rpi() const { return base::m_rpi; }\r
+ inline robust_point1_type const& rpj() const { return base::m_rpj; }\r
+ inline robust_point1_type const& rpk() const { return base::m_rpk; }\r
+\r
+ inline robust_point2_type const& rqi() const { return base::m_rqi; }\r
+ inline robust_point2_type const& rqj() const { return base::m_rqj; }\r
+ inline robust_point2_type const& rqk() const { return base::m_rqk; }\r
+\r
+ inline side_calculator_type const& sides() const { return m_side_calc; }\r
+ \r
+private:\r
+ side_calculator_type m_side_calc;\r
+\r
+ point1_type const& m_pi;\r
+ point1_type const& m_pj;\r
+ point1_type const& m_pk;\r
+ point2_type const& m_qi;\r
+ point2_type const& m_qj;\r
+ point2_type const& m_qk;\r
+};\r
+\r
+template <typename Point1, typename Point2, typename TurnPoint>\r
+class intersection_info_base<Point1, Point2, TurnPoint, detail::no_rescale_policy>\r
+{\r
+public:\r
+ typedef Point1 point1_type;\r
+ typedef Point2 point2_type;\r
+\r
+ typedef Point1 robust_point1_type;\r
+ typedef Point2 robust_point2_type;\r
+\r
+ typedef typename cs_tag<TurnPoint>::type cs_tag;\r
+\r
+ typedef side_calculator<cs_tag, Point1, Point2> side_calculator_type;\r
+ \r
+ intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ no_rescale_policy const& /*robust_policy*/)\r
+ : m_side_calc(pi, pj, pk, qi, qj, qk)\r
+ {}\r
+\r
+ inline Point1 const& pi() const { return m_side_calc.m_pi; }\r
+ inline Point1 const& pj() const { return m_side_calc.m_pj; }\r
+ inline Point1 const& pk() const { return m_side_calc.m_pk; }\r
+\r
+ inline Point2 const& qi() const { return m_side_calc.m_qi; }\r
+ inline Point2 const& qj() const { return m_side_calc.m_qj; }\r
+ inline Point2 const& qk() const { return m_side_calc.m_qk; }\r
+\r
+ inline Point1 const& rpi() const { return pi(); }\r
+ inline Point1 const& rpj() const { return pj(); }\r
+ inline Point1 const& rpk() const { return pk(); }\r
+\r
+ inline Point2 const& rqi() const { return qi(); }\r
+ inline Point2 const& rqj() const { return qj(); }\r
+ inline Point2 const& rqk() const { return qk(); }\r
+\r
+ inline side_calculator_type const& sides() const { return m_side_calc; }\r
+ \r
+private:\r
+ side_calculator_type m_side_calc;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point1,\r
+ typename Point2,\r
+ typename TurnPoint,\r
+ typename RobustPolicy\r
+>\r
+class intersection_info\r
+ : public intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy>\r
+{\r
+ typedef intersection_info_base<Point1, Point2, TurnPoint, RobustPolicy> base;\r
+\r
+ typedef typename intersection_strategies\r
+ <\r
+ typename base::cs_tag,\r
+ Point1,\r
+ Point2,\r
+ TurnPoint,\r
+ RobustPolicy\r
+ >::segment_intersection_strategy_type strategy;\r
+\r
+public:\r
+ typedef model::referring_segment<Point1 const> segment_type1;\r
+ typedef model::referring_segment<Point2 const> segment_type2;\r
+ typedef typename base::side_calculator_type side_calculator_type;\r
+ \r
+ typedef typename strategy::return_type result_type;\r
+ typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info\r
+ typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info\r
+\r
+ intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ RobustPolicy const& robust_policy)\r
+ : base(pi, pj, pk, qi, qj, qk, robust_policy)\r
+ , m_result(strategy::apply(segment_type1(pi, pj),\r
+ segment_type2(qi, qj),\r
+ robust_policy,\r
+ base::rpi(), base::rpj(),\r
+ base::rqi(), base::rqj()))\r
+ , m_robust_policy(robust_policy)\r
+ {}\r
+\r
+ inline result_type const& result() const { return m_result; }\r
+ inline i_info_type const& i_info() const { return m_result.template get<0>(); }\r
+ inline d_info_type const& d_info() const { return m_result.template get<1>(); }\r
+\r
+ // TODO: it's more like is_spike_ip_p\r
+ inline bool is_spike_p() const\r
+ {\r
+ if (base::sides().pk_wrt_p1() == 0)\r
+ {\r
+ if (! is_ip_j<0>())\r
+ {\r
+ return false;\r
+ }\r
+\r
+ int const qk_p1 = base::sides().qk_wrt_p1();\r
+ int const qk_p2 = base::sides().qk_wrt_p2();\r
+ \r
+ if (qk_p1 == -qk_p2)\r
+ {\r
+ if (qk_p1 == 0)\r
+ {\r
+ return is_spike_of_collinear(base::pi(), base::pj(),\r
+ base::pk());\r
+ }\r
+ \r
+ return true;\r
+ }\r
+ }\r
+ \r
+ return false;\r
+ }\r
+\r
+ // TODO: it's more like is_spike_ip_q\r
+ inline bool is_spike_q() const\r
+ {\r
+ if (base::sides().qk_wrt_q1() == 0)\r
+ {\r
+ if (! is_ip_j<1>())\r
+ {\r
+ return false;\r
+ }\r
+\r
+ int const pk_q1 = base::sides().pk_wrt_q1();\r
+ int const pk_q2 = base::sides().pk_wrt_q2();\r
+ \r
+ if (pk_q1 == -pk_q2)\r
+ {\r
+ if (pk_q1 == 0)\r
+ {\r
+ return is_spike_of_collinear(base::qi(), base::qj(),\r
+ base::qk());\r
+ }\r
+ \r
+ return true;\r
+ }\r
+ }\r
+ \r
+ return false;\r
+ }\r
+\r
+private:\r
+ template <typename Point>\r
+ inline bool is_spike_of_collinear(Point const& i, Point const& j,\r
+ Point const& k) const\r
+ {\r
+ typedef model::referring_segment<Point const> seg;\r
+\r
+ typedef intersection_strategies\r
+ <\r
+ typename base::cs_tag, Point, Point, Point, RobustPolicy\r
+ > si;\r
+ \r
+ typedef typename si::segment_intersection_strategy_type strategy;\r
+ \r
+ typename strategy::return_type result\r
+ = strategy::apply(seg(i, j), seg(j, k), m_robust_policy);\r
+ \r
+ return result.template get<0>().count == 2;\r
+ }\r
+\r
+ template <std::size_t OpId>\r
+ bool is_ip_j() const\r
+ {\r
+ int arrival = d_info().arrival[OpId];\r
+ bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0;\r
+\r
+ if (same_dirs)\r
+ {\r
+ if (i_info().count == 2)\r
+ {\r
+ return arrival != -1;\r
+ }\r
+ else\r
+ {\r
+ return arrival == 0;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return arrival == 1;\r
+ }\r
+ }\r
+\r
+ result_type m_result;\r
+ RobustPolicy const& m_robust_policy;\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>\r
+\r
+// TEMP, for spikes detector\r
+//#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay {\r
+\r
+template<typename AssignPolicy>\r
+struct get_turn_info_linear_areal\r
+{\r
+ // Currently only Linear spikes are handled\r
+ // Areal spikes are ignored\r
+ static const bool handle_spikes = true;\r
+\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo,\r
+ typename RobustPolicy,\r
+ typename OutputIterator\r
+ >\r
+ static inline OutputIterator apply(\r
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ bool is_p_first, bool is_p_last,\r
+ bool is_q_first, bool is_q_last,\r
+ TurnInfo const& tp_model,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out)\r
+ {\r
+ typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>\r
+ inters_info;\r
+\r
+ inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);\r
+\r
+ char const method = inters.d_info().how;\r
+\r
+ // Copy, to copy possibly extended fields\r
+ TurnInfo tp = tp_model;\r
+\r
+ // Select method and apply\r
+ switch(method)\r
+ {\r
+ case 'a' : // collinear, "at"\r
+ case 'f' : // collinear, "from"\r
+ case 's' : // starts from the middle\r
+ get_turn_info_for_endpoint<true, true>(\r
+ pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_none, out);\r
+ break;\r
+\r
+ case 'd' : // disjoint: never do anything\r
+ break;\r
+\r
+ case 'm' :\r
+ {\r
+ if ( get_turn_info_for_endpoint<false, true>(\r
+ pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_touch_interior, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ {\r
+ typedef touch_interior\r
+ <\r
+ TurnInfo\r
+ > policy;\r
+\r
+ // If Q (1) arrives (1)\r
+ if ( inters.d_info().arrival[1] == 1 )\r
+ {\r
+ policy::template apply<0>(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(),\r
+ inters.sides());\r
+ }\r
+ else\r
+ {\r
+ // Swap p/q\r
+ side_calculator\r
+ <\r
+ typename inters_info::cs_tag,\r
+ typename inters_info::robust_point2_type,\r
+ typename inters_info::robust_point1_type\r
+ > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),\r
+ inters.rpi(), inters.rpj(), inters.rpk());\r
+ policy::template apply<1>(qi, qj, qk, pi, pj, pk,\r
+ tp, inters.i_info(), inters.d_info(),\r
+ swapped_side_calc);\r
+ }\r
+\r
+ if ( tp.operations[1].operation == operation_blocked )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+\r
+ replace_method_and_operations_tm(tp.method,\r
+ tp.operations[0].operation,\r
+ tp.operations[1].operation);\r
+ \r
+ // this function assumes that 'u' must be set for a spike\r
+ calculate_spike_operation(tp.operations[0].operation,\r
+ inters, is_p_last);\r
+ \r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ break;\r
+ case 'i' :\r
+ {\r
+ crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info());\r
+\r
+ replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ break;\r
+ case 't' :\r
+ {\r
+ // Both touch (both arrive there)\r
+ if ( get_turn_info_for_endpoint<false, true>(\r
+ pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_touch, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else \r
+ {\r
+ touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ if ( tp.operations[1].operation == operation_blocked )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+\r
+ // workarounds for touch<> not taking spikes into account starts here\r
+ // those was discovered empirically\r
+ // touch<> is not symmetrical!\r
+ // P spikes and Q spikes may produce various operations!\r
+ // Only P spikes are valid for L/A\r
+ // TODO: this is not optimal solution - think about rewriting touch<>\r
+\r
+ if ( tp.operations[0].operation == operation_blocked )\r
+ {\r
+ // a spike on P on the same line with Q1\r
+ if ( inters.is_spike_p() )\r
+ {\r
+ if ( inters.sides().qk_wrt_p1() == 0 )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].operation = operation_union; \r
+ }\r
+ }\r
+ }\r
+ else if ( tp.operations[0].operation == operation_continue\r
+ && tp.operations[1].operation == operation_continue )\r
+ {\r
+ // P spike on the same line with Q2 (opposite)\r
+ if ( inters.sides().pk_wrt_q1() == -inters.sides().qk_wrt_q1()\r
+ && inters.is_spike_p() )\r
+ {\r
+ tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_union;\r
+ }\r
+ }\r
+ else if ( tp.operations[0].operation == operation_none\r
+ && tp.operations[1].operation == operation_none )\r
+ {\r
+ // spike not handled by touch<>\r
+ if ( inters.is_spike_p() )\r
+ {\r
+ tp.operations[0].operation = operation_intersection;\r
+ tp.operations[1].operation = operation_union;\r
+\r
+ if ( inters.sides().pk_wrt_q2() == 0 )\r
+ {\r
+ tp.operations[0].operation = operation_continue; // will be converted to i\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ // workarounds for touch<> not taking spikes into account ends here\r
+\r
+ replace_method_and_operations_tm(tp.method,\r
+ tp.operations[0].operation,\r
+ tp.operations[1].operation);\r
+\r
+ bool ignore_spike\r
+ = calculate_spike_operation(tp.operations[0].operation,\r
+ inters, is_p_last);\r
+\r
+// TODO: move this into the append_xxx and call for each turn?\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+\r
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)\r
+ || ignore_spike\r
+ || ! append_opposite_spikes<append_touches>( // for 'i' or 'c' i???\r
+ tp, inters, is_p_last, is_q_last, out) )\r
+ {\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 'e':\r
+ {\r
+ if ( get_turn_info_for_endpoint<true, true>(\r
+ pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_equal, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+\r
+ if ( ! inters.d_info().opposite )\r
+ {\r
+ // Both equal\r
+ // or collinear-and-ending at intersection point\r
+ equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ turn_transformer_ec<false> transformer(method_touch);\r
+ transformer(tp);\r
+ \r
+// TODO: move this into the append_xxx and call for each turn?\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ \r
+ // conditionally handle spikes\r
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)\r
+ || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,\r
+ method_touch, append_equal, out) )\r
+ {\r
+ *out++ = tp; // no spikes\r
+ }\r
+ }\r
+ else\r
+ {\r
+ equal_opposite\r
+ <\r
+ TurnInfo,\r
+ AssignPolicy\r
+ >::apply(pi, qi,\r
+ tp, out, inters);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 'c' :\r
+ {\r
+ // Collinear\r
+ if ( get_turn_info_for_endpoint<true, true>(\r
+ pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_collinear, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+\r
+ if ( ! inters.d_info().opposite )\r
+ {\r
+ method_type method_replace = method_touch_interior;\r
+ append_version_c version = append_collinear;\r
+\r
+ if ( inters.d_info().arrival[0] == 0 )\r
+ {\r
+ // Collinear, but similar thus handled as equal\r
+ equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ method_replace = method_touch;\r
+ version = append_equal;\r
+ }\r
+ else\r
+ {\r
+ collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ //method_replace = method_touch_interior;\r
+ //version = append_collinear;\r
+ }\r
+\r
+ turn_transformer_ec<false> transformer(method_replace);\r
+ transformer(tp);\r
+\r
+// TODO: move this into the append_xxx and call for each turn?\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ \r
+ // conditionally handle spikes\r
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)\r
+ || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,\r
+ method_replace, version, out) )\r
+ {\r
+ // no spikes\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Is this always 'm' ?\r
+ turn_transformer_ec<false> transformer(method_touch_interior);\r
+\r
+ // conditionally handle spikes\r
+ if ( BOOST_GEOMETRY_CONDITION(handle_spikes) )\r
+ {\r
+ append_opposite_spikes<append_collinear_opposite>(\r
+ tp, inters, is_p_last, is_q_last, out);\r
+ }\r
+\r
+ // TODO: ignore for spikes?\r
+ // E.g. pass is_p_valid = !is_p_last && !is_pj_spike,\r
+ // the same with is_q_valid\r
+\r
+ collinear_opposite\r
+ <\r
+ TurnInfo,\r
+ AssignPolicy\r
+ >::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, out, inters,\r
+ inters.sides(), transformer,\r
+ !is_p_last, true); // qk is always valid\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case '0' :\r
+ {\r
+ // degenerate points\r
+ if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) )\r
+ {\r
+ only_convert::apply(tp, inters.i_info());\r
+\r
+ if ( is_p_first\r
+ && equals::equals_point_point(pi, tp.point) )\r
+ {\r
+ tp.operations[0].position = position_front;\r
+ }\r
+ else if ( is_p_last\r
+ && equals::equals_point_point(pj, tp.point) )\r
+ {\r
+ tp.operations[0].position = position_back;\r
+ }\r
+ // tp.operations[1].position = position_middle;\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ break;\r
+ default :\r
+ {\r
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)\r
+ std::cout << "TURN: Unknown method: " << method << std::endl;\r
+#endif\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+ throw turn_info_exception(method);\r
+#endif\r
+ }\r
+ break;\r
+ }\r
+\r
+ return out;\r
+ }\r
+\r
+ template <typename Operation,\r
+ typename IntersectionInfo>\r
+ static inline bool calculate_spike_operation(Operation & op,\r
+ IntersectionInfo const& inters,\r
+ bool is_p_last)\r
+ {\r
+ bool is_p_spike = ( op == operation_union || op == operation_intersection )\r
+ && ! is_p_last\r
+ && inters.is_spike_p();\r
+\r
+ if ( is_p_spike )\r
+ {\r
+ int const pk_q1 = inters.sides().pk_wrt_q1();\r
+ \r
+ bool going_in = pk_q1 < 0; // Pk on the right\r
+ bool going_out = pk_q1 > 0; // Pk on the left\r
+\r
+ int const qk_q1 = inters.sides().qk_wrt_q1();\r
+\r
+ // special cases\r
+ if ( qk_q1 < 0 ) // Q turning R\r
+ { \r
+ // spike on the edge point\r
+ // if it's already known that the spike is going out this musn't be checked\r
+ if ( ! going_out\r
+ && equals::equals_point_point(inters.rpj(), inters.rqj()) )\r
+ {\r
+ int const pk_q2 = inters.sides().pk_wrt_q2();\r
+ going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both\r
+ going_out = pk_q1 > 0 || pk_q2 > 0; // Pk on the left of one of them\r
+ }\r
+ }\r
+ else if ( qk_q1 > 0 ) // Q turning L\r
+ {\r
+ // spike on the edge point\r
+ // if it's already known that the spike is going in this musn't be checked\r
+ if ( ! going_in\r
+ && equals::equals_point_point(inters.rpj(), inters.rqj()) )\r
+ {\r
+ int const pk_q2 = inters.sides().pk_wrt_q2();\r
+ going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them\r
+ going_out = pk_q1 > 0 && pk_q2 > 0; // Pk on the left of both\r
+ }\r
+ }\r
+\r
+ if ( going_in )\r
+ {\r
+ op = operation_intersection;\r
+ return true;\r
+ }\r
+ else if ( going_out )\r
+ {\r
+ op = operation_union;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ enum append_version_c { append_equal, append_collinear };\r
+\r
+ template <typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutIt>\r
+ static inline bool append_collinear_spikes(TurnInfo & tp,\r
+ IntersectionInfo const& inters,\r
+ bool is_p_last, bool /*is_q_last*/,\r
+ method_type method, append_version_c version,\r
+ OutIt out)\r
+ {\r
+ // method == touch || touch_interior\r
+ // both position == middle\r
+\r
+ bool is_p_spike = ( version == append_equal ?\r
+ ( tp.operations[0].operation == operation_union\r
+ || tp.operations[0].operation == operation_intersection ) :\r
+ tp.operations[0].operation == operation_continue )\r
+ && ! is_p_last\r
+ && inters.is_spike_p();\r
+\r
+ // TODO: throw an exception for spike in Areal?\r
+ /*bool is_q_spike = tp.operations[1].operation == operation_continue\r
+ && inters.is_spike_q();\r
+\r
+ // both are collinear spikes on the same IP, we can just follow both\r
+ if ( is_p_spike && is_q_spike )\r
+ {\r
+ return false;\r
+ }\r
+ // spike on Linear - it's turning back on the boundary of Areal\r
+ else*/\r
+ if ( is_p_spike )\r
+ {\r
+ tp.method = method;\r
+ tp.operations[0].operation = operation_blocked;\r
+ tp.operations[1].operation = operation_union;\r
+ *out++ = tp;\r
+ tp.operations[0].operation = operation_continue; // boundary\r
+ //tp.operations[1].operation = operation_union;\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }\r
+ // spike on Areal - Linear is going outside\r
+ /*else if ( is_q_spike )\r
+ {\r
+ tp.method = method;\r
+ tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_continue;\r
+ *out++ = tp;\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }*/\r
+\r
+ return false;\r
+ }\r
+\r
+ enum append_version_o { append_touches, append_collinear_opposite };\r
+\r
+ template <append_version_o Version,\r
+ typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutIt>\r
+ static inline bool append_opposite_spikes(TurnInfo & tp,\r
+ IntersectionInfo const& inters,\r
+ bool is_p_last, bool /*is_q_last*/,\r
+ OutIt out)\r
+ {\r
+ static const bool is_version_touches = (Version == append_touches);\r
+\r
+ bool is_p_spike = ( is_version_touches ?\r
+ ( tp.operations[0].operation == operation_continue\r
+ || tp.operations[0].operation == operation_intersection ) : // i ???\r
+ true )\r
+ && ! is_p_last\r
+ && inters.is_spike_p();\r
+ \r
+ // TODO: throw an exception for spike in Areal?\r
+ /*bool is_q_spike = ( ( Version == append_touches\r
+ && tp.operations[1].operation == operation_continue )\r
+ || ( Version == append_collinear_opposite\r
+ && tp.operations[1].operation == operation_none ) )\r
+ && inters.is_spike_q();\r
+\r
+ if ( is_p_spike && is_q_spike )\r
+ {\r
+ // u/u or nothing?\r
+ return false;\r
+ }\r
+ else*/\r
+ if ( is_p_spike )\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches)\r
+ || inters.d_info().arrival[0] == 1 )\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches) )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ //tp.operations[1].is_collinear = false;\r
+ tp.method = method_touch;\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ //tp.operations[1].is_collinear = false;\r
+\r
+ BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1);\r
+ base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1);\r
+\r
+ AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);\r
+ }\r
+\r
+ tp.operations[0].operation = operation_blocked;\r
+ tp.operations[1].operation = operation_continue; // boundary\r
+ *out++ = tp;\r
+ tp.operations[0].operation = operation_continue; // boundary\r
+ //tp.operations[1].operation = operation_continue; // boundary\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }\r
+ }\r
+ /*else if ( is_q_spike )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ tp.method = is_version_touches ? method_touch : method_touch_interior;\r
+ tp.operations[0].operation = operation_continue;\r
+ tp.operations[1].operation = operation_continue; // boundary\r
+ *out++ = tp;\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }*/\r
+\r
+ return false;\r
+ }\r
+\r
+ static inline void replace_method_and_operations_tm(method_type & method,\r
+ operation_type & op0,\r
+ operation_type & op1)\r
+ {\r
+ if ( op0 == operation_blocked && op1 == operation_blocked )\r
+ {\r
+ // NOTE: probably only if methods are WRT IPs, not segments!\r
+ method = (method == method_touch ? method_equal : method_collinear);\r
+ }\r
+\r
+ // Assuming G1 is always Linear\r
+ if ( op0 == operation_blocked )\r
+ {\r
+ op0 = operation_continue;\r
+ }\r
+\r
+ if ( op1 == operation_blocked )\r
+ {\r
+ op1 = operation_continue;\r
+ }\r
+ else if ( op1 == operation_intersection )\r
+ {\r
+ op1 = operation_union;\r
+ }\r
+\r
+ // spikes in 'm'\r
+ if ( method == method_error )\r
+ {\r
+ method = method_touch_interior;\r
+ op0 = operation_union;\r
+ op1 = operation_union;\r
+ }\r
+ }\r
+\r
+ template <bool IsFront>\r
+ class turn_transformer_ec\r
+ {\r
+ public:\r
+ explicit turn_transformer_ec(method_type method_t_or_m)\r
+ : m_method(method_t_or_m)\r
+ {}\r
+\r
+ template <typename Turn>\r
+ void operator()(Turn & turn) const\r
+ {\r
+ operation_type & op0 = turn.operations[0].operation;\r
+ operation_type & op1 = turn.operations[1].operation;\r
+\r
+ // NOTE: probably only if methods are WRT IPs, not segments!\r
+ if ( BOOST_GEOMETRY_CONDITION(IsFront)\r
+ || op0 == operation_intersection || op0 == operation_union\r
+ || op1 == operation_intersection || op1 == operation_union )\r
+ {\r
+ turn.method = m_method;\r
+ }\r
+\r
+ turn.operations[0].is_collinear = op0 != operation_blocked;\r
+\r
+ // Assuming G1 is always Linear\r
+ if ( op0 == operation_blocked )\r
+ {\r
+ op0 = operation_continue;\r
+ }\r
+\r
+ if ( op1 == operation_blocked )\r
+ {\r
+ op1 = operation_continue;\r
+ }\r
+ else if ( op1 == operation_intersection )\r
+ {\r
+ op1 = operation_union;\r
+ }\r
+ }\r
+\r
+ private:\r
+ method_type m_method;\r
+ };\r
+\r
+ static inline void replace_operations_i(operation_type & /*op0*/, operation_type & op1)\r
+ {\r
+ // assuming Linear is always the first one\r
+ op1 = operation_union;\r
+ }\r
+\r
+ // NOTE: Spikes may NOT be handled for Linear endpoints because it's not\r
+ // possible to define a spike on an endpoint. Areal geometries must\r
+ // NOT have spikes at all. One thing that could be done is to throw\r
+ // an exception when spike is detected in Areal geometry.\r
+ \r
+ template <bool EnableFirst,\r
+ bool EnableLast,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutputIterator>\r
+ static inline bool get_turn_info_for_endpoint(\r
+ Point1 const& pi, Point1 const& /*pj*/, Point1 const& /*pk*/,\r
+ Point2 const& qi, Point2 const& /*qj*/, Point2 const& /*qk*/,\r
+ bool is_p_first, bool is_p_last,\r
+ bool /*is_q_first*/, bool is_q_last,\r
+ TurnInfo const& tp_model,\r
+ IntersectionInfo const& inters,\r
+ method_type /*method*/,\r
+ OutputIterator out)\r
+ {\r
+ namespace ov = overlay;\r
+ typedef ov::get_turn_info_for_endpoint<AssignPolicy, EnableFirst, EnableLast> get_info_e;\r
+\r
+ const std::size_t ip_count = inters.i_info().count;\r
+ // no intersection points\r
+ if ( ip_count == 0 )\r
+ return false;\r
+\r
+ if ( !is_p_first && !is_p_last )\r
+ return false;\r
+\r
+// TODO: is_q_last could probably be replaced by false and removed from parameters\r
+\r
+ linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);\r
+ linear_intersections::ip_info const& ip0 = intersections.template get<0>();\r
+ linear_intersections::ip_info const& ip1 = intersections.template get<1>();\r
+\r
+ const bool opposite = inters.d_info().opposite;\r
+\r
+ // ANALYSE AND ASSIGN FIRST\r
+\r
+ // IP on the first point of Linear Geometry\r
+ bool was_first_point_handled = false;\r
+ if ( BOOST_GEOMETRY_CONDITION(EnableFirst)\r
+ && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication\r
+ {\r
+ TurnInfo tp = tp_model;\r
+ tp.operations[0].position = position_front;\r
+ tp.operations[1].position = position_middle;\r
+\r
+ if ( opposite ) // opposite -> collinear\r
+ {\r
+ tp.operations[0].operation = operation_continue;\r
+ tp.operations[1].operation = operation_union;\r
+ tp.method = ip0.is_qj ? method_touch : method_touch_interior;\r
+ }\r
+ else\r
+ {\r
+ method_type replaced_method = method_touch_interior;\r
+\r
+ if ( ip0.is_qj )\r
+ {\r
+ side_calculator\r
+ <\r
+ typename IntersectionInfo::cs_tag,\r
+ typename IntersectionInfo::robust_point1_type,\r
+ typename IntersectionInfo::robust_point2_type,\r
+ typename IntersectionInfo::robust_point2_type\r
+ > side_calc(inters.rqi(), inters.rpi(), inters.rpj(),\r
+ inters.rqi(), inters.rqj(), inters.rqk());\r
+\r
+ std::pair<operation_type, operation_type>\r
+ operations = get_info_e::operations_of_equal(side_calc);\r
+\r
+ tp.operations[0].operation = operations.first;\r
+ tp.operations[1].operation = operations.second;\r
+\r
+ replaced_method = method_touch;\r
+ }\r
+ else\r
+ {\r
+ side_calculator\r
+ <\r
+ typename IntersectionInfo::cs_tag,\r
+ typename IntersectionInfo::robust_point1_type,\r
+ typename IntersectionInfo::robust_point2_type,\r
+ typename IntersectionInfo::robust_point2_type,\r
+ typename IntersectionInfo::robust_point1_type,\r
+ typename IntersectionInfo::robust_point1_type,\r
+ typename IntersectionInfo::robust_point2_type,\r
+ typename IntersectionInfo::robust_point1_type,\r
+ typename IntersectionInfo::robust_point2_type\r
+ > side_calc(inters.rqi(), inters.rpi(), inters.rpj(),\r
+ inters.rqi(), inters.rpi(), inters.rqj());\r
+\r
+ std::pair<operation_type, operation_type>\r
+ operations = get_info_e::operations_of_equal(side_calc);\r
+\r
+ tp.operations[0].operation = operations.first;\r
+ tp.operations[1].operation = operations.second;\r
+ }\r
+\r
+ turn_transformer_ec<true> transformer(replaced_method);\r
+ transformer(tp);\r
+ }\r
+\r
+ // equals<> or collinear<> will assign the second point,\r
+ // we'd like to assign the first one\r
+ base_turn_handler::assign_point(tp, tp.method, inters.i_info(), 0);\r
+\r
+ // NOTE: is_collinear is not set for the first endpoint of L\r
+ // for which there is no preceding segment\r
+ // here is_p_first_ip == true\r
+ tp.operations[0].is_collinear = false;\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+\r
+ was_first_point_handled = true;\r
+ }\r
+\r
+ // ANALYSE AND ASSIGN LAST\r
+\r
+ // IP on the last point of Linear Geometry\r
+ if ( BOOST_GEOMETRY_CONDITION(EnableLast)\r
+ && is_p_last\r
+ && ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication\r
+ {\r
+ TurnInfo tp = tp_model;\r
+ \r
+ if ( inters.i_info().count > 1 )\r
+ {\r
+ //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );\r
+ tp.operations[0].is_collinear = true;\r
+ tp.operations[1].operation = opposite ? operation_continue : operation_union;\r
+ }\r
+ else //if ( result.template get<0>().count == 1 )\r
+ {\r
+ side_calculator\r
+ <\r
+ typename IntersectionInfo::cs_tag,\r
+ typename IntersectionInfo::robust_point1_type,\r
+ typename IntersectionInfo::robust_point2_type,\r
+ typename IntersectionInfo::robust_point2_type\r
+ > side_calc(inters.rqi(), inters.rpj(), inters.rpi(),\r
+ inters.rqi(), inters.rqj(), inters.rqk());\r
+\r
+ std::pair<operation_type, operation_type>\r
+ operations = get_info_e::operations_of_equal(side_calc);\r
+\r
+ tp.operations[0].operation = operations.first;\r
+ tp.operations[1].operation = operations.second;\r
+\r
+ turn_transformer_ec<false> transformer(method_none);\r
+ transformer(tp);\r
+\r
+ tp.operations[0].is_collinear = tp.both(operation_continue);\r
+ }\r
+\r
+ tp.method = ( ip_count > 1 ? ip1.is_qj : ip0.is_qj ) ? method_touch : method_touch_interior;\r
+ tp.operations[0].operation = operation_blocked;\r
+ tp.operations[0].position = position_back;\r
+ tp.operations[1].position = position_middle;\r
+ \r
+ // equals<> or collinear<> will assign the second point,\r
+ // we'd like to assign the first one\r
+ unsigned int ip_index = ip_count > 1 ? 1 : 0;\r
+ base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index);\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+\r
+ // don't ignore the first IP if the segment is opposite\r
+ return !( opposite && ip_count > 1 ) || was_first_point_handled;\r
+ }\r
+\r
+ // don't ignore anything for now\r
+ return false;\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay {\r
+\r
+template<typename AssignPolicy>\r
+struct get_turn_info_linear_linear\r
+{\r
+ static const bool handle_spikes = true;\r
+\r
+ template\r
+ <\r
+ typename Point1,\r
+ typename Point2,\r
+ typename TurnInfo,\r
+ typename RobustPolicy,\r
+ typename OutputIterator\r
+ >\r
+ static inline OutputIterator apply(\r
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,\r
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,\r
+ bool is_p_first, bool is_p_last,\r
+ bool is_q_first, bool is_q_last,\r
+ TurnInfo const& tp_model,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out)\r
+ {\r
+ typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>\r
+ inters_info;\r
+\r
+ inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);\r
+\r
+ char const method = inters.d_info().how;\r
+\r
+ // Copy, to copy possibly extended fields\r
+ TurnInfo tp = tp_model;\r
+\r
+ // Select method and apply\r
+ switch(method)\r
+ {\r
+ case 'a' : // collinear, "at"\r
+ case 'f' : // collinear, "from"\r
+ case 's' : // starts from the middle\r
+ get_turn_info_for_endpoint<AssignPolicy, true, true>\r
+ ::apply(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_none, out);\r
+ break;\r
+\r
+ case 'd' : // disjoint: never do anything\r
+ break;\r
+\r
+ case 'm' :\r
+ {\r
+ if ( get_turn_info_for_endpoint<AssignPolicy, false, true>\r
+ ::apply(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_touch_interior, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ {\r
+ typedef touch_interior\r
+ <\r
+ TurnInfo\r
+ > policy;\r
+\r
+ // If Q (1) arrives (1)\r
+ if ( inters.d_info().arrival[1] == 1)\r
+ {\r
+ policy::template apply<0>(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(),\r
+ inters.sides());\r
+ }\r
+ else\r
+ {\r
+ // Swap p/q\r
+ side_calculator\r
+ <\r
+ typename inters_info::cs_tag,\r
+ typename inters_info::robust_point2_type,\r
+ typename inters_info::robust_point1_type\r
+ > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),\r
+ inters.rpi(), inters.rpj(), inters.rpk());\r
+\r
+ policy::template apply<1>(qi, qj, qk, pi, pj, pk,\r
+ tp, inters.i_info(), inters.d_info(),\r
+ swapped_side_calc);\r
+ }\r
+ \r
+ if ( tp.operations[0].operation == operation_blocked )\r
+ {\r
+ tp.operations[1].is_collinear = true;\r
+ }\r
+ if ( tp.operations[1].operation == operation_blocked )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+\r
+ replace_method_and_operations_tm(tp.method,\r
+ tp.operations[0].operation,\r
+ tp.operations[1].operation);\r
+ \r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ break;\r
+ case 'i' :\r
+ {\r
+ crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info());\r
+\r
+ replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ break;\r
+ case 't' :\r
+ {\r
+ // Both touch (both arrive there)\r
+ if ( get_turn_info_for_endpoint<AssignPolicy, false, true>\r
+ ::apply(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_touch, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else \r
+ {\r
+ touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ // workarounds for touch<> not taking spikes into account starts here\r
+ // those was discovered empirically\r
+ // touch<> is not symmetrical!\r
+ // P spikes and Q spikes may produce various operations!\r
+ // TODO: this is not optimal solution - think about rewriting touch<>\r
+\r
+ if ( tp.operations[0].operation == operation_blocked\r
+ && tp.operations[1].operation == operation_blocked )\r
+ {\r
+ // two touching spikes on the same line\r
+ if ( inters.is_spike_p() && inters.is_spike_q() )\r
+ {\r
+ tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_union; \r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ tp.operations[1].is_collinear = true;\r
+ }\r
+ }\r
+ else if ( tp.operations[0].operation == operation_blocked )\r
+ {\r
+ // a spike on P on the same line with Q1\r
+ if ( inters.is_spike_p() )\r
+ {\r
+ if ( inters.sides().qk_wrt_p1() == 0 )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].operation = operation_union; \r
+ }\r
+ }\r
+ else\r
+ {\r
+ tp.operations[1].is_collinear = true;\r
+ }\r
+ }\r
+ else if ( tp.operations[1].operation == operation_blocked )\r
+ {\r
+ // a spike on Q on the same line with P1\r
+ if ( inters.is_spike_q() )\r
+ {\r
+ if ( inters.sides().pk_wrt_q1() == 0 )\r
+ {\r
+ tp.operations[1].is_collinear = true;\r
+ }\r
+ else\r
+ {\r
+ tp.operations[1].operation = operation_union; \r
+ }\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+ }\r
+ else if ( tp.operations[0].operation == operation_continue\r
+ && tp.operations[1].operation == operation_continue )\r
+ {\r
+ // P spike on the same line with Q2 (opposite)\r
+ if ( inters.sides().pk_wrt_q1() == -inters.sides().qk_wrt_q1()\r
+ && inters.is_spike_p() )\r
+ {\r
+ tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_union; \r
+ }\r
+ }\r
+ else if ( tp.operations[0].operation == operation_none\r
+ && tp.operations[1].operation == operation_none )\r
+ {\r
+ // spike not handled by touch<>\r
+ bool const is_p = inters.is_spike_p();\r
+ bool const is_q = inters.is_spike_q();\r
+\r
+ if ( is_p || is_q )\r
+ {\r
+ tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_union;\r
+\r
+ if ( inters.sides().pk_wrt_q2() == 0 )\r
+ {\r
+ tp.operations[0].operation = operation_continue; // will be converted to i\r
+ if ( is_p )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ }\r
+ }\r
+\r
+ if ( inters.sides().qk_wrt_p2() == 0 )\r
+ {\r
+ tp.operations[1].operation = operation_continue; // will be converted to i\r
+ if ( is_q )\r
+ {\r
+ tp.operations[1].is_collinear = true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // workarounds for touch<> not taking spikes into account ends here\r
+\r
+ replace_method_and_operations_tm(tp.method,\r
+ tp.operations[0].operation,\r
+ tp.operations[1].operation);\r
+\r
+// TODO: move this into the append_xxx and call for each turn?\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+\r
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)\r
+ || ! append_opposite_spikes<append_touches>(tp, inters,\r
+ is_p_last, is_q_last,\r
+ out) )\r
+ {\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 'e':\r
+ {\r
+ if ( get_turn_info_for_endpoint<AssignPolicy, true, true>\r
+ ::apply(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_equal, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ tp.operations[1].is_collinear = true;\r
+\r
+ if ( ! inters.d_info().opposite )\r
+ {\r
+ // Both equal\r
+ // or collinear-and-ending at intersection point\r
+ equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ operation_type spike_op\r
+ = ( tp.operations[0].operation != operation_continue\r
+ || tp.operations[1].operation != operation_continue ) ?\r
+ operation_union :\r
+ operation_continue;\r
+\r
+ // transform turn\r
+ turn_transformer_ec transformer(method_touch);\r
+ transformer(tp);\r
+\r
+// TODO: move this into the append_xxx and call for each turn?\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+\r
+ // conditionally handle spikes\r
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)\r
+ || ! append_collinear_spikes(tp, inters,\r
+ is_p_last, is_q_last,\r
+ method_touch, spike_op,\r
+ out) )\r
+ {\r
+ *out++ = tp; // no spikes\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // TODO: ignore for spikes or generate something else than opposite?\r
+\r
+ equal_opposite\r
+ <\r
+ TurnInfo,\r
+ AssignPolicy\r
+ >::apply(pi, qi, tp, out, inters);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case 'c' :\r
+ {\r
+ // Collinear\r
+ if ( get_turn_info_for_endpoint<AssignPolicy, true, true>\r
+ ::apply(pi, pj, pk, qi, qj, qk,\r
+ is_p_first, is_p_last, is_q_first, is_q_last,\r
+ tp_model, inters, method_collinear, out) )\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ {\r
+ // NOTE: this is for spikes since those are set in the turn_transformer_ec\r
+ tp.operations[0].is_collinear = true;\r
+ tp.operations[1].is_collinear = true;\r
+\r
+ if ( ! inters.d_info().opposite )\r
+ {\r
+ method_type method_replace = method_touch_interior;\r
+ operation_type spike_op = operation_continue;\r
+\r
+ if ( inters.d_info().arrival[0] == 0 )\r
+ {\r
+ // Collinear, but similar thus handled as equal\r
+ equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ method_replace = method_touch;\r
+ if ( tp.operations[0].operation != operation_continue\r
+ || tp.operations[1].operation != operation_continue )\r
+ {\r
+ spike_op = operation_union;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, inters.i_info(), inters.d_info(), inters.sides());\r
+\r
+ //method_replace = method_touch_interior;\r
+ //spike_op = operation_continue;\r
+ }\r
+\r
+ // transform turn\r
+ turn_transformer_ec transformer(method_replace);\r
+ transformer(tp);\r
+ \r
+// TODO: move this into the append_xxx and call for each turn?\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+\r
+ // conditionally handle spikes\r
+ if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)\r
+ || ! append_collinear_spikes(tp, inters,\r
+ is_p_last, is_q_last,\r
+ method_replace, spike_op,\r
+ out) )\r
+ {\r
+ // no spikes\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // If this always 'm' ?\r
+ turn_transformer_ec transformer(method_touch_interior);\r
+\r
+ // conditionally handle spikes\r
+ if ( BOOST_GEOMETRY_CONDITION(handle_spikes) )\r
+ {\r
+ append_opposite_spikes<append_collinear_opposite>(tp, inters,\r
+ is_p_last, is_q_last,\r
+ out);\r
+ }\r
+\r
+ // TODO: ignore for spikes?\r
+ // E.g. pass is_p_valid = !is_p_last && !is_pj_spike,\r
+ // the same with is_q_valid\r
+\r
+ collinear_opposite\r
+ <\r
+ TurnInfo,\r
+ AssignPolicy\r
+ >::apply(pi, pj, pk, qi, qj, qk,\r
+ tp, out, inters, inters.sides(),\r
+ transformer, !is_p_last, !is_q_last);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case '0' :\r
+ {\r
+ // degenerate points\r
+ if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) )\r
+ {\r
+ only_convert::apply(tp, inters.i_info());\r
+\r
+ // if any, only one of those should be true\r
+ if ( is_p_first\r
+ && equals::equals_point_point(pi, tp.point) )\r
+ {\r
+ tp.operations[0].position = position_front;\r
+ }\r
+ else if ( is_p_last\r
+ && equals::equals_point_point(pj, tp.point) )\r
+ {\r
+ tp.operations[0].position = position_back;\r
+ }\r
+ else if ( is_q_first\r
+ && equals::equals_point_point(qi, tp.point) )\r
+ {\r
+ tp.operations[1].position = position_front;\r
+ }\r
+ else if ( is_q_last\r
+ && equals::equals_point_point(qj, tp.point) )\r
+ {\r
+ tp.operations[1].position = position_back;\r
+ }\r
+\r
+ AssignPolicy::apply(tp, pi, qi, inters);\r
+ *out++ = tp;\r
+ }\r
+ }\r
+ break;\r
+ default :\r
+ {\r
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)\r
+ std::cout << "TURN: Unknown method: " << method << std::endl;\r
+#endif\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+ throw turn_info_exception(method);\r
+#endif\r
+ }\r
+ break;\r
+ }\r
+\r
+ return out;\r
+ }\r
+\r
+ template <typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutIt>\r
+ static inline bool append_collinear_spikes(TurnInfo & tp,\r
+ IntersectionInfo const& inters_info,\r
+ bool is_p_last, bool is_q_last,\r
+ method_type method, operation_type spike_op,\r
+ OutIt out)\r
+ {\r
+ // method == touch || touch_interior\r
+ // both position == middle\r
+\r
+ bool is_p_spike = tp.operations[0].operation == spike_op\r
+ && ! is_p_last\r
+ && inters_info.is_spike_p();\r
+ bool is_q_spike = tp.operations[1].operation == spike_op\r
+ && ! is_q_last\r
+ && inters_info.is_spike_q();\r
+\r
+ if ( is_p_spike && is_q_spike )\r
+ {\r
+ if ( tp.method == method_equal\r
+ && tp.operations[0].operation == operation_continue\r
+ && tp.operations[1].operation == operation_continue )\r
+ {\r
+ // treat both non-opposite collinear spikes as no-spikes\r
+ return false;\r
+ }\r
+\r
+ tp.method = method;\r
+ tp.operations[0].operation = operation_blocked;\r
+ tp.operations[1].operation = operation_blocked;\r
+ *out++ = tp;\r
+ tp.operations[0].operation = operation_intersection;\r
+ tp.operations[1].operation = operation_intersection;\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }\r
+ else if ( is_p_spike )\r
+ {\r
+ tp.method = method;\r
+ tp.operations[0].operation = operation_blocked;\r
+ tp.operations[1].operation = operation_union;\r
+ *out++ = tp;\r
+ tp.operations[0].operation = operation_intersection;\r
+ //tp.operations[1].operation = operation_union;\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }\r
+ else if ( is_q_spike )\r
+ {\r
+ tp.method = method;\r
+ tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_blocked;\r
+ *out++ = tp;\r
+ //tp.operations[0].operation = operation_union;\r
+ tp.operations[1].operation = operation_intersection;\r
+ *out++ = tp;\r
+\r
+ return true;\r
+ }\r
+ \r
+ return false;\r
+ }\r
+\r
+ enum append_version { append_touches, append_collinear_opposite };\r
+\r
+ template <append_version Version,\r
+ typename TurnInfo,\r
+ typename IntersectionInfo,\r
+ typename OutIt>\r
+ static inline bool append_opposite_spikes(TurnInfo & tp,\r
+ IntersectionInfo const& inters,\r
+ bool is_p_last, bool is_q_last,\r
+ OutIt out)\r
+ {\r
+ static const bool is_version_touches = (Version == append_touches);\r
+\r
+ bool is_p_spike = ( is_version_touches ?\r
+ ( tp.operations[0].operation == operation_continue\r
+ || tp.operations[0].operation == operation_intersection ) :\r
+ true )\r
+ && ! is_p_last\r
+ && inters.is_spike_p();\r
+ bool is_q_spike = ( is_version_touches ?\r
+ ( tp.operations[1].operation == operation_continue\r
+ || tp.operations[1].operation == operation_intersection ) :\r
+ true )\r
+ && ! is_q_last\r
+ && inters.is_spike_q();\r
+\r
+ bool res = false;\r
+\r
+ if ( is_p_spike\r
+ && ( BOOST_GEOMETRY_CONDITION(is_version_touches)\r
+ || inters.d_info().arrival[0] == 1 ) )\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches) )\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ tp.operations[1].is_collinear = false;\r
+ tp.method = method_touch;\r
+ }\r
+ else // Version == append_collinear_opposite\r
+ {\r
+ tp.operations[0].is_collinear = true;\r
+ tp.operations[1].is_collinear = false;\r
+ \r
+ BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1);\r
+ \r
+ base_turn_handler::assign_point(tp, method_touch_interior,\r
+ inters.i_info(), 1);\r
+\r
+ AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);\r
+ }\r
+\r
+ tp.operations[0].operation = operation_blocked;\r
+ tp.operations[1].operation = operation_intersection;\r
+ *out++ = tp;\r
+ tp.operations[0].operation = operation_intersection;\r
+ //tp.operations[1].operation = operation_intersection;\r
+ *out++ = tp;\r
+\r
+ res = true;\r
+ }\r
+\r
+ if ( is_q_spike\r
+ && ( BOOST_GEOMETRY_CONDITION(is_version_touches)\r
+ || inters.d_info().arrival[1] == 1 ) )\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION(is_version_touches) )\r
+ {\r
+ tp.operations[0].is_collinear = false;\r
+ tp.operations[1].is_collinear = true;\r
+ tp.method = method_touch;\r
+ }\r
+ else // Version == append_collinear_opposite\r
+ {\r
+ tp.operations[0].is_collinear = false;\r
+ tp.operations[1].is_collinear = true;\r
+ \r
+ BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0);\r
+\r
+ base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);\r
+\r
+ AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters);\r
+ }\r
+\r
+ tp.operations[0].operation = operation_intersection;\r
+ tp.operations[1].operation = operation_blocked;\r
+ *out++ = tp;\r
+ //tp.operations[0].operation = operation_intersection;\r
+ tp.operations[1].operation = operation_intersection;\r
+ *out++ = tp;\r
+\r
+ res = true;\r
+ }\r
+ \r
+ return res;\r
+ }\r
+\r
+ static inline void replace_method_and_operations_tm(method_type & method,\r
+ operation_type & op0,\r
+ operation_type & op1)\r
+ {\r
+ if ( op0 == operation_blocked && op1 == operation_blocked )\r
+ {\r
+ // NOTE: probably only if methods are WRT IPs, not segments!\r
+ method = (method == method_touch ? method_equal : method_collinear);\r
+ op0 = operation_continue;\r
+ op1 = operation_continue;\r
+ }\r
+ else\r
+ {\r
+ if ( op0 == operation_continue || op0 == operation_blocked )\r
+ {\r
+ op0 = operation_intersection;\r
+ }\r
+ else if ( op0 == operation_intersection )\r
+ {\r
+ op0 = operation_union;\r
+ }\r
+\r
+ if ( op1 == operation_continue || op1 == operation_blocked )\r
+ {\r
+ op1 = operation_intersection;\r
+ }\r
+ else if ( op1 == operation_intersection )\r
+ {\r
+ op1 = operation_union;\r
+ }\r
+\r
+ // spikes in 'm'\r
+ if ( method == method_error )\r
+ {\r
+ method = method_touch_interior;\r
+ op0 = operation_union;\r
+ op1 = operation_union;\r
+ }\r
+ }\r
+ }\r
+\r
+ class turn_transformer_ec\r
+ {\r
+ public:\r
+ explicit turn_transformer_ec(method_type method_t_or_m)\r
+ : m_method(method_t_or_m)\r
+ {}\r
+\r
+ template <typename Turn>\r
+ void operator()(Turn & turn) const\r
+ {\r
+ operation_type & op0 = turn.operations[0].operation;\r
+ operation_type & op1 = turn.operations[1].operation;\r
+\r
+ BOOST_GEOMETRY_ASSERT(op0 != operation_blocked || op1 != operation_blocked );\r
+\r
+ if ( op0 == operation_blocked )\r
+ {\r
+ op0 = operation_intersection;\r
+ }\r
+ else if ( op0 == operation_intersection )\r
+ {\r
+ op0 = operation_union;\r
+ }\r
+\r
+ if ( op1 == operation_blocked )\r
+ {\r
+ op1 = operation_intersection;\r
+ }\r
+ else if ( op1 == operation_intersection )\r
+ {\r
+ op1 = operation_union;\r
+ }\r
+\r
+ if ( op0 == operation_intersection || op0 == operation_union\r
+ || op1 == operation_intersection || op1 == operation_union )\r
+ {\r
+ turn.method = m_method;\r
+ }\r
+\r
+// TODO: is this correct?\r
+// it's equivalent to comparing to operation_blocked at the beginning of the function\r
+ turn.operations[0].is_collinear = op0 != operation_intersection;\r
+ turn.operations[1].is_collinear = op1 != operation_intersection;\r
+ }\r
+\r
+ private:\r
+ method_type m_method;\r
+ };\r
+\r
+ static inline void replace_operations_i(operation_type & op0, operation_type & op1)\r
+ {\r
+ if ( op0 == operation_intersection )\r
+ {\r
+ op0 = operation_union;\r
+ }\r
+\r
+ if ( op1 == operation_intersection )\r
+ {\r
+ op1 = operation_union;\r
+ }\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014, 2016.\r
+// Modifications copyright (c) 2014, 2016 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP\r
+\r
+\r
+#include <cstddef>\r
+#include <map>\r
+\r
+#include <boost/array.hpp>\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/vector_c.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+#include <boost/geometry/views/detail/range_type.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+\r
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>\r
+#include <boost/geometry/strategies/intersection_strategies.hpp>\r
+#include <boost/geometry/strategies/intersection_result.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION\r
+# include <sstream>\r
+# include <boost/geometry/io/dsv/write.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace get_turns\r
+{\r
+\r
+\r
+struct no_interrupt_policy\r
+{\r
+ static bool const enabled = false;\r
+\r
+ template <typename Range>\r
+ static inline bool apply(Range const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ bool Reverse1, bool Reverse2,\r
+ typename Section1, typename Section2,\r
+ typename TurnPolicy\r
+>\r
+class get_turns_in_sections\r
+{\r
+ typedef typename closeable_view\r
+ <\r
+ typename range_type<Geometry1>::type const,\r
+ closure<Geometry1>::value\r
+ >::type cview_type1;\r
+ typedef typename closeable_view\r
+ <\r
+ typename range_type<Geometry2>::type const,\r
+ closure<Geometry2>::value\r
+ >::type cview_type2;\r
+\r
+ typedef typename reversible_view\r
+ <\r
+ cview_type1 const,\r
+ Reverse1 ? iterate_reverse : iterate_forward\r
+ >::type view_type1;\r
+ typedef typename reversible_view\r
+ <\r
+ cview_type2 const,\r
+ Reverse2 ? iterate_reverse : iterate_forward\r
+ >::type view_type2;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ view_type1 const\r
+ >::type range1_iterator;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ view_type2 const\r
+ >::type range2_iterator;\r
+\r
+\r
+ template <typename Geometry, typename Section>\r
+ static inline bool neighbouring(Section const& section,\r
+ signed_size_type index1, signed_size_type index2)\r
+ {\r
+ // About n-2:\r
+ // (square: range_count=5, indices 0,1,2,3\r
+ // -> 0-3 are adjacent, don't check on intersections)\r
+ // Also tested for open polygons, and/or duplicates\r
+ // About first condition: will be optimized by compiler (static)\r
+ // It checks if it is areal (box,ring,(multi)polygon\r
+ signed_size_type const n = static_cast<signed_size_type>(section.range_count);\r
+\r
+ boost::ignore_unused_variable_warning(n);\r
+ boost::ignore_unused_variable_warning(index1);\r
+ boost::ignore_unused_variable_warning(index2);\r
+\r
+ return boost::is_same\r
+ <\r
+ typename tag_cast\r
+ <\r
+ typename geometry::tag<Geometry>::type,\r
+ areal_tag\r
+ >::type,\r
+ areal_tag\r
+ >::value\r
+ && index1 == 0\r
+ && index2 >= n - 2\r
+ ;\r
+ }\r
+\r
+\r
+public :\r
+ // Returns true if terminated, false if interrupted\r
+ template <typename Turns, typename RobustPolicy, typename InterruptPolicy>\r
+ static inline bool apply(\r
+ int source_id1, Geometry1 const& geometry1, Section1 const& sec1,\r
+ int source_id2, Geometry2 const& geometry2, Section2 const& sec2,\r
+ bool skip_larger,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy)\r
+ {\r
+ boost::ignore_unused_variable_warning(interrupt_policy);\r
+\r
+ if ((sec1.duplicate && (sec1.count + 1) < sec1.range_count)\r
+ || (sec2.duplicate && (sec2.count + 1) < sec2.range_count))\r
+ {\r
+ // Skip sections containig only duplicates.\r
+ // They are still important (can indicate non-disjointness)\r
+ // but they will be found processing adjacent sections.\r
+ // Do NOT skip if they are the ONLY section\r
+ return true;\r
+ }\r
+\r
+ cview_type1 cview1(range_by_section(geometry1, sec1));\r
+ cview_type2 cview2(range_by_section(geometry2, sec2));\r
+ view_type1 view1(cview1);\r
+ view_type2 view2(cview2);\r
+\r
+ range1_iterator begin_range_1 = boost::begin(view1);\r
+ range1_iterator end_range_1 = boost::end(view1);\r
+\r
+ range2_iterator begin_range_2 = boost::begin(view2);\r
+ range2_iterator end_range_2 = boost::end(view2);\r
+\r
+ int const dir1 = sec1.directions[0];\r
+ int const dir2 = sec2.directions[0];\r
+ signed_size_type index1 = sec1.begin_index;\r
+ signed_size_type ndi1 = sec1.non_duplicate_index;\r
+\r
+ bool const same_source =\r
+ source_id1 == source_id2\r
+ && sec1.ring_id.multi_index == sec2.ring_id.multi_index\r
+ && sec1.ring_id.ring_index == sec2.ring_id.ring_index;\r
+\r
+ range1_iterator prev1, it1, end1;\r
+\r
+ get_start_point_iterator(sec1, view1, prev1, it1, end1,\r
+ index1, ndi1, dir1, sec2.bounding_box, robust_policy);\r
+\r
+ // We need a circular iterator because it might run through the closing point.\r
+ // One circle is actually enough but this one is just convenient.\r
+ ever_circling_iterator<range1_iterator> next1(begin_range_1, end_range_1, it1, true);\r
+ next1++;\r
+\r
+ // Walk through section and stop if we exceed the other box\r
+ // section 2: [--------------]\r
+ // section 1: |----|---|---|---|---|\r
+ for (prev1 = it1++, next1++;\r
+ it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);\r
+ ++prev1, ++it1, ++index1, ++next1, ++ndi1)\r
+ {\r
+ ever_circling_iterator<range1_iterator> nd_next1(\r
+ begin_range_1, end_range_1, next1, true);\r
+ advance_to_non_duplicate_next(nd_next1, it1, sec1, robust_policy);\r
+\r
+ signed_size_type index2 = sec2.begin_index;\r
+ signed_size_type ndi2 = sec2.non_duplicate_index;\r
+\r
+ range2_iterator prev2, it2, end2;\r
+\r
+ get_start_point_iterator(sec2, view2, prev2, it2, end2,\r
+ index2, ndi2, dir2, sec1.bounding_box, robust_policy);\r
+ ever_circling_iterator<range2_iterator> next2(begin_range_2, end_range_2, it2, true);\r
+ next2++;\r
+\r
+ for (prev2 = it2++, next2++;\r
+ it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);\r
+ ++prev2, ++it2, ++index2, ++next2, ++ndi2)\r
+ {\r
+ bool skip = same_source;\r
+ if (skip)\r
+ {\r
+ // If sources are the same (possibly self-intersecting):\r
+ // skip if it is a neighbouring segment.\r
+ // (including first-last segment\r
+ // and two segments with one or more degenerate/duplicate\r
+ // (zero-length) segments in between)\r
+\r
+ // Also skip if index1 < index2 to avoid getting all\r
+ // intersections twice (only do this on same source!)\r
+\r
+ skip = (skip_larger && index1 >= index2)\r
+ || ndi2 == ndi1 + 1\r
+ || neighbouring<Geometry1>(sec1, index1, index2)\r
+ ;\r
+ }\r
+\r
+ if (! skip)\r
+ {\r
+ // Move to the "non duplicate next"\r
+ ever_circling_iterator<range2_iterator> nd_next2(\r
+ begin_range_2, end_range_2, next2, true);\r
+ advance_to_non_duplicate_next(nd_next2, it2, sec2, robust_policy);\r
+\r
+ typedef typename boost::range_value<Turns>::type turn_info;\r
+\r
+ turn_info ti;\r
+ ti.operations[0].seg_id\r
+ = segment_identifier(source_id1, sec1.ring_id.multi_index,\r
+ sec1.ring_id.ring_index, index1);\r
+ ti.operations[1].seg_id\r
+ = segment_identifier(source_id2, sec2.ring_id.multi_index,\r
+ sec2.ring_id.ring_index, index2);\r
+\r
+ std::size_t const size_before = boost::size(turns);\r
+\r
+ bool const is_1_first = sec1.is_non_duplicate_first && index1 == sec1.begin_index;\r
+ bool const is_1_last = sec1.is_non_duplicate_last && index1+1 >= sec1.end_index;\r
+ bool const is_2_first = sec2.is_non_duplicate_first && index2 == sec2.begin_index;\r
+ bool const is_2_last = sec2.is_non_duplicate_last && index2+1 >= sec2.end_index;\r
+\r
+ TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,\r
+ is_1_first, is_1_last, is_2_first, is_2_last,\r
+ ti, robust_policy, std::back_inserter(turns));\r
+\r
+ if (InterruptPolicy::enabled)\r
+ {\r
+ if (interrupt_policy.apply(\r
+ std::make_pair(range::pos(turns, size_before),\r
+ boost::end(turns))))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+\r
+private :\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+ typedef typename model::referring_segment<point1_type const> segment1_type;\r
+ typedef typename model::referring_segment<point2_type const> segment2_type;\r
+\r
+ template <typename Iterator, typename RangeIterator, typename Section, typename RobustPolicy>\r
+ static inline void advance_to_non_duplicate_next(Iterator& next,\r
+ RangeIterator const& it, Section const& section, RobustPolicy const& robust_policy)\r
+ {\r
+ typedef typename robust_point_type<point1_type, RobustPolicy>::type robust_point_type;\r
+ robust_point_type robust_point_from_it;\r
+ robust_point_type robust_point_from_next;\r
+ geometry::recalculate(robust_point_from_it, *it, robust_policy);\r
+ geometry::recalculate(robust_point_from_next, *next, robust_policy);\r
+\r
+ // To see where the next segments bend to, in case of touch/intersections\r
+ // on end points, we need (in case of degenerate/duplicate points) an extra\r
+ // iterator which moves to the REAL next point, so non duplicate.\r
+ // This needs an extra comparison (disjoint).\r
+ // (Note that within sections, non duplicate points are already asserted,\r
+ // by the sectionalize process).\r
+\r
+ // So advance to the "non duplicate next"\r
+ // (the check is defensive, to avoid endless loops)\r
+ std::size_t check = 0;\r
+ while(! detail::disjoint::disjoint_point_point\r
+ (\r
+ robust_point_from_it, robust_point_from_next\r
+ )\r
+ && check++ < section.range_count)\r
+ {\r
+ next++;\r
+ geometry::recalculate(robust_point_from_next, *next, robust_policy);\r
+ }\r
+ }\r
+\r
+ // It is NOT possible to have section-iterators here\r
+ // because of the logistics of "index" (the section-iterator automatically\r
+ // skips to the begin-point, we loose the index or have to recalculate it)\r
+ // So we mimic it here\r
+ template <typename Range, typename Section, typename Box, typename RobustPolicy>\r
+ static inline void get_start_point_iterator(Section & section,\r
+ Range const& range,\r
+ typename boost::range_iterator<Range const>::type& it,\r
+ typename boost::range_iterator<Range const>::type& prev,\r
+ typename boost::range_iterator<Range const>::type& end,\r
+ signed_size_type& index, signed_size_type& ndi,\r
+ int dir, Box const& other_bounding_box, RobustPolicy const& robust_policy)\r
+ {\r
+ it = boost::begin(range) + section.begin_index;\r
+ end = boost::begin(range) + section.end_index + 1;\r
+\r
+ // Mimic section-iterator:\r
+ // Skip to point such that section interects other box\r
+ prev = it++;\r
+ for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy);\r
+ prev = it++, index++, ndi++)\r
+ {}\r
+ // Go back one step because we want to start completely preceding\r
+ it = prev;\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ bool Reverse1, bool Reverse2,\r
+ typename Turns,\r
+ typename TurnPolicy,\r
+ typename RobustPolicy,\r
+ typename InterruptPolicy\r
+>\r
+struct section_visitor\r
+{\r
+ int m_source_id1;\r
+ Geometry1 const& m_geometry1;\r
+ int m_source_id2;\r
+ Geometry2 const& m_geometry2;\r
+ RobustPolicy const& m_rescale_policy;\r
+ Turns& m_turns;\r
+ InterruptPolicy& m_interrupt_policy;\r
+\r
+ section_visitor(int id1, Geometry1 const& g1,\r
+ int id2, Geometry2 const& g2,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns, InterruptPolicy& ip)\r
+ : m_source_id1(id1), m_geometry1(g1)\r
+ , m_source_id2(id2), m_geometry2(g2)\r
+ , m_rescale_policy(robust_policy)\r
+ , m_turns(turns)\r
+ , m_interrupt_policy(ip)\r
+ {}\r
+\r
+ template <typename Section>\r
+ inline bool apply(Section const& sec1, Section const& sec2)\r
+ {\r
+ if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box))\r
+ {\r
+ return get_turns_in_sections\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ Reverse1, Reverse2,\r
+ Section, Section,\r
+ TurnPolicy\r
+ >::apply(\r
+ m_source_id1, m_geometry1, sec1,\r
+ m_source_id2, m_geometry2, sec2,\r
+ false,\r
+ m_rescale_policy,\r
+ m_turns, m_interrupt_policy);\r
+ }\r
+ return true;\r
+ }\r
+\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ bool Reverse1, bool Reverse2,\r
+ typename TurnPolicy\r
+>\r
+class get_turns_generic\r
+{\r
+\r
+public:\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline void apply(\r
+ int source_id1, Geometry1 const& geometry1,\r
+ int source_id2, Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy)\r
+ {\r
+ // First create monotonic sections...\r
+ typedef typename boost::range_value<Turns>::type ip_type;\r
+ typedef typename ip_type::point_type point_type;\r
+\r
+ typedef model::box\r
+ <\r
+ typename geometry::robust_point_type\r
+ <\r
+ point_type, RobustPolicy\r
+ >::type\r
+ > box_type;\r
+ typedef geometry::sections<box_type, 2> sections_type;\r
+\r
+ sections_type sec1, sec2;\r
+ typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;\r
+\r
+ geometry::sectionalize<Reverse1, dimensions>(geometry1, robust_policy,\r
+ sec1, 0);\r
+ geometry::sectionalize<Reverse2, dimensions>(geometry2, robust_policy,\r
+ sec2, 1);\r
+\r
+ // ... and then partition them, intersecting overlapping sections in visitor method\r
+ section_visitor\r
+ <\r
+ Geometry1, Geometry2,\r
+ Reverse1, Reverse2,\r
+ Turns, TurnPolicy, RobustPolicy, InterruptPolicy\r
+ > visitor(source_id1, geometry1, source_id2, geometry2, robust_policy, turns, interrupt_policy);\r
+\r
+ geometry::partition\r
+ <\r
+ box_type,\r
+ detail::section::get_section_box,\r
+ detail::section::overlaps_section_box\r
+ >::apply(sec1, sec2, visitor);\r
+ }\r
+};\r
+\r
+\r
+// Get turns for a range with a box, following Cohen-Sutherland (cs) approach\r
+template\r
+<\r
+ typename Range, typename Box,\r
+ bool ReverseRange, bool ReverseBox,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns_cs\r
+{\r
+ typedef typename geometry::point_type<Range>::type point_type;\r
+ typedef typename geometry::point_type<Box>::type box_point_type;\r
+\r
+ typedef typename closeable_view\r
+ <\r
+ Range const,\r
+ closure<Range>::value\r
+ >::type cview_type;\r
+\r
+ typedef typename reversible_view\r
+ <\r
+ cview_type const,\r
+ ReverseRange ? iterate_reverse : iterate_forward\r
+ >::type view_type;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ view_type const\r
+ >::type iterator_type;\r
+\r
+\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline void apply(\r
+ int source_id1, Range const& range,\r
+ int source_id2, Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy,\r
+ signed_size_type multi_index = -1,\r
+ signed_size_type ring_index = -1)\r
+ {\r
+ if ( boost::size(range) <= 1)\r
+ {\r
+ return;\r
+ }\r
+\r
+ boost::array<box_point_type,4> bp;\r
+ assign_box_corners_oriented<ReverseBox>(box, bp);\r
+\r
+ cview_type cview(range);\r
+ view_type view(cview);\r
+\r
+ typedef typename boost::range_size<view_type>::type size_type;\r
+ size_type segments_count1 = boost::size(view) - 1;\r
+\r
+ iterator_type it = boost::begin(view);\r
+\r
+ ever_circling_iterator<iterator_type> next(\r
+ boost::begin(view), boost::end(view), it, true);\r
+ next++;\r
+ next++;\r
+\r
+ //bool first = true;\r
+\r
+ //char previous_side[2] = {0, 0};\r
+\r
+ signed_size_type index = 0;\r
+\r
+ for (iterator_type prev = it++;\r
+ it != boost::end(view);\r
+ prev = it++, next++, index++)\r
+ {\r
+ segment_identifier seg_id(source_id1,\r
+ multi_index, ring_index, index);\r
+\r
+ /*if (first)\r
+ {\r
+ previous_side[0] = get_side<0>(box, *prev);\r
+ previous_side[1] = get_side<1>(box, *prev);\r
+ }\r
+\r
+ char current_side[2];\r
+ current_side[0] = get_side<0>(box, *it);\r
+ current_side[1] = get_side<1>(box, *it);\r
+\r
+ // There can NOT be intersections if\r
+ // 1) EITHER the two points are lying on one side of the box (! 0 && the same)\r
+ // 2) OR same in Y-direction\r
+ // 3) OR all points are inside the box (0)\r
+ if (! (\r
+ (current_side[0] != 0 && current_side[0] == previous_side[0])\r
+ || (current_side[1] != 0 && current_side[1] == previous_side[1])\r
+ || (current_side[0] == 0\r
+ && current_side[1] == 0\r
+ && previous_side[0] == 0\r
+ && previous_side[1] == 0)\r
+ )\r
+ )*/\r
+ if (true)\r
+ {\r
+ get_turns_with_box(seg_id, source_id2,\r
+ *prev, *it, *next,\r
+ bp[0], bp[1], bp[2], bp[3],\r
+ // NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes\r
+ index == 0,\r
+ size_type(index) == segments_count1,\r
+ robust_policy,\r
+ turns, interrupt_policy);\r
+ // Future performance enhancement:\r
+ // return if told by the interrupt policy\r
+ }\r
+ }\r
+ }\r
+\r
+private:\r
+ template<std::size_t Index, typename Point>\r
+ static inline int get_side(Box const& box, Point const& point)\r
+ {\r
+ // Inside -> 0\r
+ // Outside -> -1 (left/below) or 1 (right/above)\r
+ // On border -> -2 (left/lower) or 2 (right/upper)\r
+ // The only purpose of the value is to not be the same,\r
+ // and to denote if it is inside (0)\r
+\r
+ typename coordinate_type<Point>::type const& c = get<Index>(point);\r
+ typename coordinate_type<Box>::type const& left = get<min_corner, Index>(box);\r
+ typename coordinate_type<Box>::type const& right = get<max_corner, Index>(box);\r
+\r
+ if (geometry::math::equals(c, left)) return -2;\r
+ else if (geometry::math::equals(c, right)) return 2;\r
+ else if (c < left) return -1;\r
+ else if (c > right) return 1;\r
+ else return 0;\r
+ }\r
+\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2,\r
+ // Points from a range:\r
+ point_type const& rp0,\r
+ point_type const& rp1,\r
+ point_type const& rp2,\r
+ // Points from the box\r
+ box_point_type const& bp0,\r
+ box_point_type const& bp1,\r
+ box_point_type const& bp2,\r
+ box_point_type const& bp3,\r
+ bool const is_range_first,\r
+ bool const is_range_last,\r
+ RobustPolicy const& robust_policy,\r
+ // Output\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy)\r
+ {\r
+ boost::ignore_unused_variable_warning(interrupt_policy);\r
+\r
+ // Depending on code some relations can be left out\r
+\r
+ typedef typename boost::range_value<Turns>::type turn_info;\r
+\r
+ turn_info ti;\r
+ ti.operations[0].seg_id = seg_id;\r
+\r
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0);\r
+ TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2,\r
+ is_range_first, is_range_last,\r
+ true, false,\r
+ ti, robust_policy, std::back_inserter(turns));\r
+\r
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);\r
+ TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3,\r
+ is_range_first, is_range_last,\r
+ false, false,\r
+ ti, robust_policy, std::back_inserter(turns));\r
+\r
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);\r
+ TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0,\r
+ is_range_first, is_range_last,\r
+ false, false,\r
+ ti, robust_policy, std::back_inserter(turns));\r
+\r
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);\r
+ TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,\r
+ is_range_first, is_range_last,\r
+ false, true,\r
+ ti, robust_policy, std::back_inserter(turns));\r
+\r
+ if (InterruptPolicy::enabled)\r
+ {\r
+ interrupt_policy.apply(turns);\r
+ }\r
+\r
+ }\r
+\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Polygon, typename Box,\r
+ bool Reverse, bool ReverseBox,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns_polygon_cs\r
+{\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline void apply(\r
+ int source_id1, Polygon const& polygon,\r
+ int source_id2, Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns, InterruptPolicy& interrupt_policy,\r
+ signed_size_type multi_index = -1)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+\r
+ typedef detail::get_turns::get_turns_cs\r
+ <\r
+ ring_type, Box,\r
+ Reverse, ReverseBox,\r
+ TurnPolicy\r
+ > intersector_type;\r
+\r
+ intersector_type::apply(\r
+ source_id1, geometry::exterior_ring(polygon),\r
+ source_id2, box,\r
+ robust_policy,\r
+ turns, interrupt_policy,\r
+ multi_index, -1);\r
+\r
+ signed_size_type i = 0;\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it, ++i)\r
+ {\r
+ intersector_type::apply(\r
+ source_id1, *it,\r
+ source_id2, box,\r
+ robust_policy,\r
+ turns, interrupt_policy,\r
+ multi_index, i);\r
+ }\r
+\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Multi, typename Box,\r
+ bool Reverse, bool ReverseBox,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns_multi_polygon_cs\r
+{\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline void apply(\r
+ int source_id1, Multi const& multi,\r
+ int source_id2, Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns, InterruptPolicy& interrupt_policy)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ Multi const\r
+ >::type iterator_type;\r
+\r
+ signed_size_type i = 0;\r
+ for (iterator_type it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it, ++i)\r
+ {\r
+ // Call its single version\r
+ get_turns_polygon_cs\r
+ <\r
+ typename boost::range_value<Multi>::type, Box,\r
+ Reverse, ReverseBox,\r
+ TurnPolicy\r
+ >::apply(source_id1, *it, source_id2, box,\r
+ robust_policy, turns, interrupt_policy, i);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+// GET_TURN_INFO_TYPE\r
+\r
+template <typename Geometry>\r
+struct topological_tag_base\r
+{\r
+ typedef typename tag_cast<typename tag<Geometry>::type, pointlike_tag, linear_tag, areal_tag>::type type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename AssignPolicy,\r
+ typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,\r
+ typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>\r
+struct get_turn_info_type\r
+ : overlay::get_turn_info<AssignPolicy>\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2, typename AssignPolicy, typename Tag1, typename Tag2>\r
+struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear_tag, linear_tag>\r
+ : overlay::get_turn_info_linear_linear<AssignPolicy>\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2, typename AssignPolicy, typename Tag1, typename Tag2>\r
+struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear_tag, areal_tag>\r
+ : overlay::get_turn_info_linear_areal<AssignPolicy>\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2, typename SegmentRatio,\r
+ typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,\r
+ typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>\r
+struct turn_operation_type\r
+{\r
+ typedef overlay::turn_operation<typename point_type<Geometry1>::type, SegmentRatio> type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>\r
+struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>\r
+{\r
+ typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>\r
+struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>\r
+{\r
+ typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;\r
+};\r
+\r
+}} // namespace detail::get_turns\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+// Because this is "detail" method, and most implementations will use "generic",\r
+// we take the freedom to derive it from "generic".\r
+template\r
+<\r
+ typename GeometryTag1, typename GeometryTag2,\r
+ typename Geometry1, typename Geometry2,\r
+ bool Reverse1, bool Reverse2,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns\r
+ : detail::get_turns::get_turns_generic\r
+ <\r
+ Geometry1, Geometry2,\r
+ Reverse1, Reverse2,\r
+ TurnPolicy\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Polygon, typename Box,\r
+ bool ReversePolygon, bool ReverseBox,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns\r
+ <\r
+ polygon_tag, box_tag,\r
+ Polygon, Box,\r
+ ReversePolygon, ReverseBox,\r
+ TurnPolicy\r
+ > : detail::get_turns::get_turns_polygon_cs\r
+ <\r
+ Polygon, Box,\r
+ ReversePolygon, ReverseBox,\r
+ TurnPolicy\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Ring, typename Box,\r
+ bool ReverseRing, bool ReverseBox,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns\r
+ <\r
+ ring_tag, box_tag,\r
+ Ring, Box,\r
+ ReverseRing, ReverseBox,\r
+ TurnPolicy\r
+ > : detail::get_turns::get_turns_cs\r
+ <\r
+ Ring, Box, ReverseRing, ReverseBox,\r
+ TurnPolicy\r
+ >\r
+\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPolygon,\r
+ typename Box,\r
+ bool ReverseMultiPolygon, bool ReverseBox,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns\r
+ <\r
+ multi_polygon_tag, box_tag,\r
+ MultiPolygon, Box,\r
+ ReverseMultiPolygon, ReverseBox,\r
+ TurnPolicy\r
+ >\r
+ : detail::get_turns::get_turns_multi_polygon_cs\r
+ <\r
+ MultiPolygon, Box,\r
+ ReverseMultiPolygon, ReverseBox,\r
+ TurnPolicy\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename GeometryTag1, typename GeometryTag2,\r
+ typename Geometry1, typename Geometry2,\r
+ bool Reverse1, bool Reverse2,\r
+ typename TurnPolicy\r
+>\r
+struct get_turns_reversed\r
+{\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline void apply(\r
+ int source_id1, Geometry1 const& g1,\r
+ int source_id2, Geometry2 const& g2,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy)\r
+ {\r
+ get_turns\r
+ <\r
+ GeometryTag2, GeometryTag1,\r
+ Geometry2, Geometry1,\r
+ Reverse2, Reverse1,\r
+ TurnPolicy\r
+ >::apply(source_id2, g2, source_id1, g1, robust_policy,\r
+ turns, interrupt_policy);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{turn points}\r
+\ingroup overlay\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Turns type of turn-container (e.g. vector of "intersection/turn point"'s)\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param robust_policy policy to handle robustness issues\r
+\param turns container which will contain turn points\r
+\param interrupt_policy policy determining if process is stopped\r
+ when intersection is found\r
+ */\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename AssignPolicy,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename Turns,\r
+ typename InterruptPolicy\r
+>\r
+inline void get_turns(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy)\r
+{\r
+ concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();\r
+\r
+ typedef detail::overlay::get_turn_info<AssignPolicy> TurnPolicy;\r
+ //typedef detail::get_turns::get_turn_info_type<Geometry1, Geometry2, AssignPolicy> TurnPolicy;\r
+\r
+ boost::mpl::if_c\r
+ <\r
+ reverse_dispatch<Geometry1, Geometry2>::type::value,\r
+ dispatch::get_turns_reversed\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ Geometry1, Geometry2,\r
+ Reverse1, Reverse2,\r
+ TurnPolicy\r
+ >,\r
+ dispatch::get_turns\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ Geometry1, Geometry2,\r
+ Reverse1, Reverse2,\r
+ TurnPolicy\r
+ >\r
+ >::type::apply(\r
+ 0, geometry1,\r
+ 1, geometry2,\r
+ robust_policy,\r
+ turns, interrupt_policy);\r
+}\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_COLOCATIONS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_COLOCATIONS_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <map>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)\r
+# include <iostream>\r
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+# include <boost/geometry/io/wkt/wkt.hpp>\r
+# define BOOST_GEOMETRY_DEBUG_IDENTIFIER\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template <typename SegmentRatio>\r
+struct segment_fraction\r
+{\r
+ segment_identifier seg_id;\r
+ SegmentRatio fraction;\r
+\r
+ segment_fraction(segment_identifier const& id, SegmentRatio const& fr)\r
+ : seg_id(id)\r
+ , fraction(fr)\r
+ {}\r
+\r
+ segment_fraction()\r
+ {}\r
+\r
+ bool operator<(segment_fraction<SegmentRatio> const& other) const\r
+ {\r
+ return seg_id == other.seg_id\r
+ ? fraction < other.fraction\r
+ : seg_id < other.seg_id;\r
+ }\r
+\r
+};\r
+\r
+struct turn_operation_index\r
+{\r
+ turn_operation_index(signed_size_type ti = -1,\r
+ signed_size_type oi = -1)\r
+ : turn_index(ti)\r
+ , op_index(oi)\r
+ {}\r
+\r
+ signed_size_type turn_index;\r
+ signed_size_type op_index; // only 0,1\r
+};\r
+\r
+\r
+template <typename Turns>\r
+struct less_by_fraction_and_type\r
+{\r
+ inline less_by_fraction_and_type(Turns const& turns)\r
+ : m_turns(turns)\r
+ {\r
+ }\r
+\r
+ inline bool operator()(turn_operation_index const& left,\r
+ turn_operation_index const& right) const\r
+ {\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ turn_type const& left_turn = m_turns[left.turn_index];\r
+ turn_type const& right_turn = m_turns[right.turn_index];\r
+ turn_operation_type const& left_op\r
+ = left_turn.operations[left.op_index];\r
+\r
+ turn_operation_type const& right_op\r
+ = right_turn.operations[right.op_index];\r
+\r
+ if (! (left_op.fraction == right_op.fraction))\r
+ {\r
+ return left_op.fraction < right_op.fraction;\r
+ }\r
+\r
+ // Order xx first - used to discard any following colocated turn\r
+ bool const left_both_xx = left_turn.both(operation_blocked);\r
+ bool const right_both_xx = right_turn.both(operation_blocked);\r
+ if (left_both_xx && ! right_both_xx)\r
+ {\r
+ return true;\r
+ }\r
+ if (! left_both_xx && right_both_xx)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ bool const left_both_uu = left_turn.both(operation_union);\r
+ bool const right_both_uu = right_turn.both(operation_union);\r
+ if (left_both_uu && ! right_both_uu)\r
+ {\r
+ return true;\r
+ }\r
+ if (! left_both_uu && right_both_uu)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ turn_operation_type const& left_other_op\r
+ = left_turn.operations[1 - left.op_index];\r
+\r
+ turn_operation_type const& right_other_op\r
+ = right_turn.operations[1 - right.op_index];\r
+\r
+ // Fraction is the same, now sort on ring id, first outer ring,\r
+ // then interior rings\r
+ return left_other_op.seg_id < right_other_op.seg_id;\r
+ }\r
+\r
+private:\r
+ Turns const& m_turns;\r
+};\r
+\r
+template <typename Operation, typename ClusterPerSegment>\r
+inline signed_size_type get_cluster_id(Operation const& op, ClusterPerSegment const& cluster_per_segment)\r
+{\r
+ typedef typename ClusterPerSegment::key_type segment_fraction_type;\r
+\r
+ segment_fraction_type seg_frac(op.seg_id, op.fraction);\r
+ typename ClusterPerSegment::const_iterator it\r
+ = cluster_per_segment.find(seg_frac);\r
+\r
+ if (it == cluster_per_segment.end())\r
+ {\r
+ return -1;\r
+ }\r
+ return it->second;\r
+}\r
+\r
+template <typename Operation, typename ClusterPerSegment>\r
+inline void add_cluster_id(Operation const& op,\r
+ ClusterPerSegment& cluster_per_segment, signed_size_type id)\r
+{\r
+ typedef typename ClusterPerSegment::key_type segment_fraction_type;\r
+\r
+ segment_fraction_type seg_frac(op.seg_id, op.fraction);\r
+\r
+ cluster_per_segment[seg_frac] = id;\r
+}\r
+\r
+template <typename Turn, typename ClusterPerSegment>\r
+inline signed_size_type add_turn_to_cluster(Turn const& turn,\r
+ ClusterPerSegment& cluster_per_segment, signed_size_type& cluster_id)\r
+{\r
+ signed_size_type cid0 = get_cluster_id(turn.operations[0], cluster_per_segment);\r
+ signed_size_type cid1 = get_cluster_id(turn.operations[1], cluster_per_segment);\r
+\r
+ if (cid0 == -1 && cid1 == -1)\r
+ {\r
+ ++cluster_id;\r
+ add_cluster_id(turn.operations[0], cluster_per_segment, cluster_id);\r
+ add_cluster_id(turn.operations[1], cluster_per_segment, cluster_id);\r
+ return cluster_id;\r
+ }\r
+ else if (cid0 == -1 && cid1 != -1)\r
+ {\r
+ add_cluster_id(turn.operations[0], cluster_per_segment, cid1);\r
+ return cid1;\r
+ }\r
+ else if (cid0 != -1 && cid1 == -1)\r
+ {\r
+ add_cluster_id(turn.operations[1], cluster_per_segment, cid0);\r
+ return cid0;\r
+ }\r
+ else if (cid0 == cid1)\r
+ {\r
+ // Both already added to same cluster, no action\r
+ return cid0;\r
+ }\r
+\r
+ // Both operations.seg_id/fraction were already part of any cluster, and\r
+ // these clusters are not the same. Merge of two clusters is necessary\r
+ std::cout << " TODO: merge " << cid0 << " and " << cid1 << std::endl;\r
+ return cid0;\r
+}\r
+\r
+template\r
+<\r
+ typename Turns,\r
+ typename ClusterPerSegment,\r
+ typename Operations,\r
+ typename Geometry1,\r
+ typename Geometry2\r
+>\r
+inline void handle_colocation_cluster(Turns& turns,\r
+ signed_size_type& cluster_id,\r
+ ClusterPerSegment& cluster_per_segment,\r
+ Operations const& operations,\r
+ Geometry1 const& /*geometry1*/, Geometry2 const& /*geometry2*/)\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ std::vector<turn_operation_index>::const_iterator vit = operations.begin();\r
+\r
+ turn_operation_index ref_toi = *vit;\r
+ signed_size_type ref_id = -1;\r
+\r
+ for (++vit; vit != operations.end(); ++vit)\r
+ {\r
+ turn_type& ref_turn = turns[ref_toi.turn_index];\r
+ turn_operation_type const& ref_op\r
+ = ref_turn.operations[ref_toi.op_index];\r
+\r
+ turn_operation_index const& toi = *vit;\r
+ turn_type& turn = turns[toi.turn_index];\r
+ turn_operation_type const& op = turn.operations[toi.op_index];\r
+\r
+ BOOST_ASSERT(ref_op.seg_id == op.seg_id);\r
+\r
+ if (ref_op.fraction == op.fraction)\r
+ {\r
+ turn_operation_type const& other_op = turn.operations[1 - toi.op_index];\r
+\r
+ if (ref_id == -1)\r
+ {\r
+ ref_id = add_turn_to_cluster(ref_turn, cluster_per_segment, cluster_id);\r
+ }\r
+ BOOST_ASSERT(ref_id != -1);\r
+\r
+ // ref_turn (both operations) are already added to cluster,\r
+ // so also "op" is already added to cluster,\r
+ // We only need to add other_op\r
+ signed_size_type id = get_cluster_id(other_op, cluster_per_segment);\r
+ if (id != -1 && id != ref_id)\r
+ {\r
+ }\r
+ else if (id == -1)\r
+ {\r
+ // Add to same cluster\r
+ add_cluster_id(other_op, cluster_per_segment, ref_id);\r
+ id = ref_id;\r
+ }\r
+\r
+ // In case of colocated xx turns, all other turns may NOT be\r
+ // followed at all. xx cannot be discarded (otherwise colocated\r
+ // turns are followed).\r
+ if (ref_turn.both(operation_blocked))\r
+ {\r
+ turn.discarded = true;\r
+ // We can either set or not set colocated because it is not effective on blocked turns\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Not on same fraction on this segment\r
+ // assign for next\r
+ ref_toi = toi;\r
+ ref_id = -1;\r
+ }\r
+ }\r
+}\r
+\r
+template\r
+<\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename ClusterPerSegment\r
+>\r
+inline void assign_cluster_to_turns(Turns& turns,\r
+ Clusters& clusters,\r
+ ClusterPerSegment const& cluster_per_segment)\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+ typedef typename ClusterPerSegment::key_type segment_fraction_type;\r
+\r
+ signed_size_type turn_index = 0;\r
+ for (typename boost::range_iterator<Turns>::type it = turns.begin();\r
+ it != turns.end(); ++it, ++turn_index)\r
+ {\r
+ turn_type& turn = *it;\r
+\r
+ if (turn.discarded)\r
+ {\r
+ // They were processed (to create proper map) but will not be added\r
+ // This might leave a cluster with only 1 turn, which will be fixed\r
+ // afterwards\r
+ continue;\r
+ }\r
+\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type const& op = turn.operations[i];\r
+ segment_fraction_type seg_frac(op.seg_id, op.fraction);\r
+ typename ClusterPerSegment::const_iterator it = cluster_per_segment.find(seg_frac);\r
+ if (it != cluster_per_segment.end())\r
+ {\r
+ if (turn.cluster_id != -1\r
+ && turn.cluster_id != it->second)\r
+ {\r
+ std::cout << " CONFLICT " << std::endl;\r
+ }\r
+ turn.cluster_id = it->second;\r
+ clusters[turn.cluster_id].turn_indices.insert(turn_index);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+template\r
+<\r
+ typename Turns,\r
+ typename Clusters\r
+>\r
+inline void remove_clusters(Turns& turns, Clusters& clusters)\r
+{\r
+ typename Clusters::iterator it = clusters.begin();\r
+ while (it != clusters.end())\r
+ {\r
+ // Hold iterator and increase. We can erase cit, this keeps the\r
+ // iterator valid (cf The standard associative-container erase idiom)\r
+ typename Clusters::iterator current_it = it;\r
+ ++it;\r
+\r
+ std::set<signed_size_type> const& turn_indices\r
+ = current_it->second.turn_indices;\r
+ if (turn_indices.size() == 1)\r
+ {\r
+ signed_size_type turn_index = *turn_indices.begin();\r
+ turns[turn_index].cluster_id = -1;\r
+ clusters.erase(current_it);\r
+ }\r
+ }\r
+}\r
+\r
+template <typename Turn, typename IdSet>\r
+inline void discard_ie_turn(Turn& turn, IdSet& ids, signed_size_type id)\r
+{\r
+ turn.discarded = true;\r
+ turn.cluster_id = -1;\r
+ // To remove it later from clusters\r
+ ids.insert(id);\r
+}\r
+\r
+template <bool Reverse>\r
+inline bool is_interior(segment_identifier const& seg_id)\r
+{\r
+ return Reverse ? seg_id.ring_index == -1 : seg_id.ring_index >= 0;\r
+}\r
+\r
+template <bool Reverse0, bool Reverse1>\r
+inline bool is_ie_turn(segment_identifier const& ext_seg_0,\r
+ segment_identifier const& ext_seg_1,\r
+ segment_identifier const& int_seg_0,\r
+ segment_identifier const& other_seg_1)\r
+{\r
+ // Compares two segment identifiers from two turns (external / one internal)\r
+\r
+ // From first turn [0], both are from same polygon (multi_index),\r
+ // one is exterior (-1), the other is interior (>= 0),\r
+ // and the second turn [1] handles the same ring\r
+\r
+ // For difference, where the rings are processed in reversal, all interior\r
+ // rings become exterior and vice versa. But also the multi property changes:\r
+ // rings originally from the same multi should now be considered as from\r
+ // different multi polygons.\r
+ // But this is not always the case, and at this point hard to figure out\r
+ // (not yet implemented, TODO)\r
+\r
+ bool const same_multi0 = ! Reverse0\r
+ && ext_seg_0.multi_index == int_seg_0.multi_index;\r
+\r
+ bool const same_multi1 = ! Reverse1\r
+ && ext_seg_1.multi_index == other_seg_1.multi_index;\r
+\r
+ return same_multi0\r
+ && same_multi1\r
+ && ! is_interior<Reverse0>(ext_seg_0)\r
+ && is_interior<Reverse0>(int_seg_0)\r
+ && ext_seg_1.ring_index == other_seg_1.ring_index;\r
+\r
+ // The other way round is tested in another call\r
+}\r
+\r
+template\r
+<\r
+ bool Reverse0, bool Reverse1, // Reverse interpretation interior/exterior\r
+ typename Turns,\r
+ typename Clusters\r
+>\r
+inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)\r
+{\r
+ typedef std::set<signed_size_type>::const_iterator set_iterator;\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+\r
+ std::set<signed_size_type> ids_to_remove;\r
+\r
+ for (typename Clusters::iterator cit = clusters.begin();\r
+ cit != clusters.end(); ++cit)\r
+ {\r
+ cluster_info& cinfo = cit->second;\r
+ std::set<signed_size_type>& ids = cinfo.turn_indices;\r
+\r
+ ids_to_remove.clear();\r
+\r
+ for (set_iterator it = ids.begin(); it != ids.end(); ++it)\r
+ {\r
+ turn_type& turn = turns[*it];\r
+ segment_identifier const& seg_0 = turn.operations[0].seg_id;\r
+ segment_identifier const& seg_1 = turn.operations[1].seg_id;\r
+\r
+ if (turn.both(operation_intersection)\r
+ && Reverse0 == Reverse1)\r
+ {\r
+ if ( is_interior<Reverse0>(seg_0)\r
+ && is_interior<Reverse1>(seg_1))\r
+ {\r
+ // ii touch with, two interior rings\r
+ discard_ie_turn(turn, ids_to_remove, *it);\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ if (! (turn.both(operation_union)\r
+ || turn.combination(operation_union, operation_blocked)))\r
+ {\r
+ // Not a uu/ux, so cannot be colocated with a iu turn\r
+ continue;\r
+ }\r
+\r
+ for (set_iterator int_it = ids.begin(); int_it != ids.end(); ++int_it)\r
+ {\r
+ if (*it == *int_it)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // Turn with, possibly, an interior ring involved\r
+ turn_type& int_turn = turns[*int_it];\r
+ segment_identifier const& int_seg_0 = int_turn.operations[0].seg_id;\r
+ segment_identifier const& int_seg_1 = int_turn.operations[1].seg_id;\r
+\r
+ if (is_ie_turn<Reverse0, Reverse1>(seg_0, seg_1, int_seg_0, int_seg_1))\r
+ {\r
+ discard_ie_turn(int_turn, ids_to_remove, *int_it);\r
+ }\r
+ if (is_ie_turn<Reverse1, Reverse0>(seg_1, seg_0, int_seg_1, int_seg_0))\r
+ {\r
+ discard_ie_turn(int_turn, ids_to_remove, *int_it);\r
+ }\r
+ }\r
+ }\r
+\r
+ // Erase from the ids (which cannot be done above)\r
+ for (set_iterator sit = ids_to_remove.begin();\r
+ sit != ids_to_remove.end(); ++sit)\r
+ {\r
+ ids.erase(*sit);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+// Checks colocated turns and flags combinations of uu/other, possibly a\r
+// combination of a ring touching another geometry's interior ring which is\r
+// tangential to the exterior ring\r
+\r
+// This function can be extended to replace handle_tangencies: at each\r
+// colocation incoming and outgoing vectors should be inspected\r
+\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename Geometry1,\r
+ typename Geometry2\r
+>\r
+inline bool handle_colocations(Turns& turns, Clusters& clusters,\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ typedef std::map\r
+ <\r
+ segment_identifier,\r
+ std::vector<turn_operation_index>\r
+ > map_type;\r
+\r
+ // Create and fill map on segment-identifier Map is sorted on seg_id,\r
+ // meaning it is sorted on ring_identifier too. This means that exterior\r
+ // rings are handled first. If there is a colocation on the exterior ring,\r
+ // that information can be used for the interior ring too\r
+ map_type map;\r
+\r
+ int index = 0;\r
+ for (typename boost::range_iterator<Turns>::type\r
+ it = boost::begin(turns);\r
+ it != boost::end(turns);\r
+ ++it, ++index)\r
+ {\r
+ map[it->operations[0].seg_id].push_back(turn_operation_index(index, 0));\r
+ map[it->operations[1].seg_id].push_back(turn_operation_index(index, 1));\r
+ }\r
+\r
+ // Check if there are multiple turns on one or more segments,\r
+ // if not then nothing is to be done\r
+ bool colocations = 0;\r
+ for (typename map_type::const_iterator it = map.begin();\r
+ it != map.end();\r
+ ++it)\r
+ {\r
+ if (it->second.size() > 1u)\r
+ {\r
+ colocations = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (! colocations)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Sort all vectors, per same segment\r
+ less_by_fraction_and_type<Turns> less(turns);\r
+ for (typename map_type::iterator it = map.begin();\r
+ it != map.end(); ++it)\r
+ {\r
+ std::sort(it->second.begin(), it->second.end(), less);\r
+ }\r
+\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::segment_ratio_type segment_ratio_type;\r
+\r
+ typedef std::map\r
+ <\r
+ segment_fraction<segment_ratio_type>,\r
+ signed_size_type\r
+ > cluster_per_segment_type;\r
+\r
+ cluster_per_segment_type cluster_per_segment;\r
+ signed_size_type cluster_id = 0;\r
+\r
+ for (typename map_type::const_iterator it = map.begin();\r
+ it != map.end(); ++it)\r
+ {\r
+ if (it->second.size() > 1u)\r
+ {\r
+ handle_colocation_cluster(turns, cluster_id, cluster_per_segment,\r
+ it->second, geometry1, geometry2);\r
+ }\r
+ }\r
+\r
+ assign_cluster_to_turns(turns, clusters, cluster_per_segment);\r
+ discard_interior_exterior_turns\r
+ <\r
+ do_reverse<geometry::point_order<Geometry1>::value>::value != Reverse1,\r
+ do_reverse<geometry::point_order<Geometry2>::value>::value != Reverse2\r
+ >(turns, clusters);\r
+ remove_clusters(turns, clusters);\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)\r
+ std::cout << "*** Colocations " << map.size() << std::endl;\r
+ for (typename map_type::const_iterator it = map.begin();\r
+ it != map.end(); ++it)\r
+ {\r
+ std::cout << it->first << std::endl;\r
+ for (std::vector<turn_operation_index>::const_iterator vit\r
+ = it->second.begin(); vit != it->second.end(); ++vit)\r
+ {\r
+ turn_operation_index const& toi = *vit;\r
+ std::cout << geometry::wkt(turns[toi.turn_index].point)\r
+ << std::boolalpha\r
+ << " discarded=" << turns[toi.turn_index].discarded\r
+ << " colocated=" << turns[toi.turn_index].colocated\r
+ << " " << operation_char(turns[toi.turn_index].operations[0].operation)\r
+ << " " << turns[toi.turn_index].operations[0].seg_id\r
+ << " " << turns[toi.turn_index].operations[0].fraction\r
+ << " // " << operation_char(turns[toi.turn_index].operations[1].operation)\r
+ << " " << turns[toi.turn_index].operations[1].seg_id\r
+ << " " << turns[toi.turn_index].operations[1].fraction\r
+ << std::endl;\r
+ }\r
+ }\r
+#endif // DEBUG\r
+\r
+ return true;\r
+}\r
+\r
+\r
+struct is_turn_index\r
+{\r
+ is_turn_index(signed_size_type index)\r
+ : m_index(index)\r
+ {}\r
+\r
+ template <typename Indexed>\r
+ inline bool operator()(Indexed const& indexed) const\r
+ {\r
+ // Indexed is a indexed_turn_operation<Operation>\r
+ return indexed.turn_index == m_index;\r
+ }\r
+\r
+ std::size_t m_index;\r
+};\r
+\r
+\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename Geometry1,\r
+ typename Geometry2\r
+>\r
+inline void gather_cluster_properties(Clusters& clusters, Turns& turns,\r
+ operation_type for_operation,\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::point_type point_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ // Define sorter, sorting counter-clockwise such that polygons are on the\r
+ // right side\r
+ typedef sort_by_side::side_sorter\r
+ <\r
+ Reverse1, Reverse2, point_type, std::less<int>\r
+ > sbs_type;\r
+\r
+ for (typename Clusters::iterator mit = clusters.begin();\r
+ mit != clusters.end(); ++mit)\r
+ {\r
+ cluster_info& cinfo = mit->second;\r
+ std::set<signed_size_type> const& ids = cinfo.turn_indices;\r
+ if (ids.empty())\r
+ {\r
+ continue;\r
+ }\r
+\r
+ sbs_type sbs;\r
+ point_type turn_point; // should be all the same for all turns in cluster\r
+\r
+ bool first = true;\r
+ for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();\r
+ sit != ids.end(); ++sit)\r
+ {\r
+ signed_size_type turn_index = *sit;\r
+ turn_type const& turn = turns[turn_index];\r
+ if (first)\r
+ {\r
+ turn_point = turn.point;\r
+ }\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type const& op = turn.operations[i];\r
+ sbs.add(op, turn_index, i, geometry1, geometry2, first);\r
+ first = false;\r
+ }\r
+ }\r
+ sbs.apply(turn_point);\r
+\r
+ sbs.find_open();\r
+\r
+ // Unset the startable flag for all 'closed' zones\r
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)\r
+ {\r
+ const typename sbs_type::rp& ranked = sbs.m_ranked_points[i];\r
+ turn_type& turn = turns[ranked.turn_index];\r
+ turn_operation_type& op = turn.operations[ranked.operation_index];\r
+\r
+ if (ranked.direction != sort_by_side::dir_to)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ op.enriched.count_left = ranked.count_left;\r
+ op.enriched.count_right = ranked.count_right;\r
+ op.enriched.zone = ranked.zone;\r
+\r
+ if ((for_operation == operation_union\r
+ && ranked.count_left != 0)\r
+ || (for_operation == operation_intersection\r
+ && ranked.count_right != 2))\r
+ {\r
+ op.enriched.startable = false;\r
+ }\r
+ }\r
+\r
+ cinfo.open_count = sbs.open_count(turns);\r
+ }\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_COLOCATIONS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP\r
+\r
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)\r
+#include <boost/geometry/core/exception.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+class inconsistent_turns_exception : public geometry::exception\r
+{\r
+public:\r
+\r
+ inline inconsistent_turns_exception() {}\r
+\r
+ virtual ~inconsistent_turns_exception() throw()\r
+ {}\r
+\r
+ virtual char const* what() const throw()\r
+ {\r
+ return "Boost.Geometry Inconsistent Turns exception";\r
+ }\r
+};\r
+\r
+}} // boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_OVERLAY_NO_THROW\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_BOX_BOX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_BOX_BOX_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace intersection\r
+{\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct intersection_box_box\r
+{\r
+ template\r
+ <\r
+ typename Box1, typename Box2,\r
+ typename RobustPolicy,\r
+ typename BoxOut,\r
+ typename Strategy\r
+ >\r
+ static inline bool apply(Box1 const& box1,\r
+ Box2 const& box2,\r
+ RobustPolicy const& robust_policy,\r
+ BoxOut& box_out,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename coordinate_type<BoxOut>::type ct;\r
+\r
+ ct max1 = get<max_corner, Dimension>(box1);\r
+ ct min2 = get<min_corner, Dimension>(box2);\r
+\r
+ if (max1 < min2)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ ct max2 = get<max_corner, Dimension>(box2);\r
+ ct min1 = get<min_corner, Dimension>(box1);\r
+\r
+ if (max2 < min1)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Set dimensions of output coordinate\r
+ set<min_corner, Dimension>(box_out, min1 < min2 ? min2 : min1);\r
+ set<max_corner, Dimension>(box_out, max1 > max2 ? max2 : max1);\r
+ \r
+ return intersection_box_box<Dimension + 1, DimensionCount>\r
+ ::apply(box1, box2, robust_policy, box_out, strategy);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct intersection_box_box<DimensionCount, DimensionCount>\r
+{\r
+ template\r
+ <\r
+ typename Box1, typename Box2,\r
+ typename RobustPolicy,\r
+ typename BoxOut,\r
+ typename Strategy\r
+ >\r
+ static inline bool apply(Box1 const&, Box2 const&,\r
+ RobustPolicy const&, BoxOut&, Strategy const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::intersection\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_BOX_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+\r
+#include <boost/geometry/core/is_areal.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/follow.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+\r
+#include <boost/geometry/views/segment_view.hpp>\r
+#include <boost/geometry/views/detail/boundary_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)\r
+#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+#include <boost/geometry/io/wkt/wkt.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace intersection\r
+{\r
+\r
+template <typename PointOut>\r
+struct intersection_segment_segment_point\r
+{\r
+ template\r
+ <\r
+ typename Segment1, typename Segment2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Segment1 const& segment1,\r
+ Segment2 const& segment2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& )\r
+ {\r
+ typedef typename point_type<PointOut>::type point_type;\r
+\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ typename geometry::point_type<Segment1>::type,\r
+ RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ // TODO: rescale segment -> robust points\r
+ robust_point_type pi_rob, pj_rob, qi_rob, qj_rob;\r
+ {\r
+ // Workaround:\r
+ point_type pi, pj, qi, qj;\r
+ assign_point_from_index<0>(segment1, pi);\r
+ assign_point_from_index<1>(segment1, pj);\r
+ assign_point_from_index<0>(segment2, qi);\r
+ assign_point_from_index<1>(segment2, qj);\r
+ geometry::recalculate(pi_rob, pi, robust_policy);\r
+ geometry::recalculate(pj_rob, pj, robust_policy);\r
+ geometry::recalculate(qi_rob, qi, robust_policy);\r
+ geometry::recalculate(qj_rob, qj, robust_policy);\r
+ }\r
+\r
+ // Get the intersection point (or two points)\r
+ typedef segment_intersection_points\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type\r
+ <\r
+ point_type, RobustPolicy\r
+ >::type\r
+ > intersection_return_type;\r
+\r
+ typedef strategy::intersection::relate_cartesian_segments\r
+ <\r
+ policies::relate::segments_intersection_points\r
+ <\r
+ intersection_return_type\r
+ >\r
+ > policy;\r
+\r
+ intersection_return_type is = policy::apply(segment1, segment2,\r
+ robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);\r
+\r
+ for (std::size_t i = 0; i < is.count; i++)\r
+ {\r
+ PointOut p;\r
+ geometry::convert(is.intersections[i], p);\r
+ *out++ = p;\r
+ }\r
+ return out;\r
+ }\r
+};\r
+\r
+template <typename PointOut>\r
+struct intersection_linestring_linestring_point\r
+{\r
+ template\r
+ <\r
+ typename Linestring1, typename Linestring2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Linestring1 const& linestring1,\r
+ Linestring2 const& linestring2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& )\r
+ {\r
+ typedef typename point_type<PointOut>::type point_type;\r
+\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type<point_type, RobustPolicy>::type\r
+ > turn_info;\r
+ std::deque<turn_info> turns;\r
+\r
+ geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns);\r
+\r
+ for (typename boost::range_iterator<std::deque<turn_info> const>::type\r
+ it = boost::begin(turns); it != boost::end(turns); ++it)\r
+ {\r
+ PointOut p;\r
+ geometry::convert(it->point, p);\r
+ *out++ = p;\r
+ }\r
+ return out;\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Version of linestring with an areal feature (polygon or multipolygon)\r
+*/\r
+template\r
+<\r
+ bool ReverseAreal,\r
+ typename LineStringOut,\r
+ overlay_type OverlayType\r
+>\r
+struct intersection_of_linestring_with_areal\r
+{\r
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)\r
+ template <typename Turn, typename Operation>\r
+ static inline void debug_follow(Turn const& turn, Operation op,\r
+ int index)\r
+ {\r
+ std::cout << index\r
+ << " at " << op.seg_id\r
+ << " meth: " << method_char(turn.method)\r
+ << " op: " << operation_char(op.operation)\r
+ << " vis: " << visited_char(op.visited)\r
+ << " of: " << operation_char(turn.operations[0].operation)\r
+ << operation_char(turn.operations[1].operation)\r
+ << " " << geometry::wkt(turn.point)\r
+ << std::endl;\r
+ }\r
+\r
+ template <typename Turn>\r
+ static inline void debug_turn(Turn const& t, bool non_crossing)\r
+ {\r
+ std::cout << "checking turn @"\r
+ << geometry::wkt(t.point)\r
+ << "; " << method_char(t.method)\r
+ << ":" << operation_char(t.operations[0].operation)\r
+ << "/" << operation_char(t.operations[1].operation)\r
+ << "; non-crossing? "\r
+ << std::boolalpha << non_crossing << std::noboolalpha\r
+ << std::endl;\r
+ }\r
+#endif\r
+\r
+ class is_crossing_turn\r
+ {\r
+ // return true is the operation is intersection or blocked\r
+ template <std::size_t Index, typename Turn>\r
+ static inline bool has_op_i_or_b(Turn const& t)\r
+ {\r
+ return\r
+ t.operations[Index].operation == overlay::operation_intersection\r
+ ||\r
+ t.operations[Index].operation == overlay::operation_blocked;\r
+ }\r
+\r
+ template <typename Turn>\r
+ static inline bool has_method_crosses(Turn const& t)\r
+ {\r
+ return t.method == overlay::method_crosses;\r
+ }\r
+\r
+ template <typename Turn>\r
+ static inline bool is_cc(Turn const& t)\r
+ {\r
+ return\r
+ (t.method == overlay::method_touch_interior\r
+ ||\r
+ t.method == overlay::method_equal\r
+ ||\r
+ t.method == overlay::method_collinear)\r
+ &&\r
+ t.operations[0].operation == t.operations[1].operation\r
+ &&\r
+ t.operations[0].operation == overlay::operation_continue\r
+ ;\r
+ }\r
+\r
+ template <typename Turn>\r
+ static inline bool has_i_or_b_ops(Turn const& t)\r
+ {\r
+ return\r
+ (t.method == overlay::method_touch\r
+ ||\r
+ t.method == overlay::method_touch_interior\r
+ ||\r
+ t.method == overlay::method_collinear)\r
+ &&\r
+ t.operations[1].operation != t.operations[0].operation\r
+ &&\r
+ (has_op_i_or_b<0>(t) || has_op_i_or_b<1>(t));\r
+ }\r
+\r
+ public:\r
+ template <typename Turn>\r
+ static inline bool apply(Turn const& t)\r
+ {\r
+ bool const is_crossing\r
+ = has_method_crosses(t) || is_cc(t) || has_i_or_b_ops(t);\r
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)\r
+ debug_turn(t, ! is_crossing);\r
+#endif\r
+ return is_crossing;\r
+ }\r
+ };\r
+\r
+ struct is_non_crossing_turn\r
+ {\r
+ template <typename Turn>\r
+ static inline bool apply(Turn const& t)\r
+ {\r
+ return ! is_crossing_turn::apply(t);\r
+ }\r
+ };\r
+\r
+ template <typename Turns>\r
+ static inline bool no_crossing_turns_or_empty(Turns const& turns)\r
+ {\r
+ return detail::check_iterator_range\r
+ <\r
+ is_non_crossing_turn,\r
+ true // allow an empty turns range\r
+ >::apply(boost::begin(turns), boost::end(turns));\r
+ }\r
+\r
+ template\r
+ <\r
+ typename LineString, typename Areal,\r
+ typename RobustPolicy,\r
+ typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(LineString const& linestring, Areal const& areal,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& )\r
+ {\r
+ if (boost::size(linestring) == 0)\r
+ {\r
+ return out;\r
+ }\r
+\r
+ typedef detail::overlay::follow\r
+ <\r
+ LineStringOut,\r
+ LineString,\r
+ Areal,\r
+ OverlayType,\r
+ false // do not remove spikes for linear geometries\r
+ > follower;\r
+\r
+ typedef typename point_type<LineStringOut>::type point_type;\r
+ typedef detail::overlay::traversal_turn_info\r
+ <\r
+ point_type,\r
+ typename geometry::segment_ratio_type<point_type, RobustPolicy>::type\r
+ > turn_info;\r
+ std::deque<turn_info> turns;\r
+\r
+ detail::get_turns::no_interrupt_policy policy;\r
+ geometry::get_turns\r
+ <\r
+ false,\r
+ (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),\r
+ detail::overlay::assign_null_policy\r
+ >(linestring, areal, robust_policy, turns, policy);\r
+\r
+ if (no_crossing_turns_or_empty(turns))\r
+ {\r
+ // No intersection points, it is either completely\r
+ // inside (interior + borders)\r
+ // or completely outside\r
+\r
+ // Use border point (on a segment) to check this\r
+ // (because turn points might skip some cases)\r
+ point_type border_point;\r
+ if (! geometry::point_on_border(border_point, linestring, true))\r
+ {\r
+ return out;\r
+ }\r
+\r
+ if (follower::included(border_point, areal, robust_policy))\r
+ {\r
+ LineStringOut copy;\r
+ geometry::convert(linestring, copy);\r
+ *out++ = copy;\r
+ }\r
+ return out;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)\r
+ int index = 0;\r
+ for(typename std::deque<turn_info>::const_iterator\r
+ it = turns.begin(); it != turns.end(); ++it)\r
+ {\r
+ debug_follow(*it, it->operations[0], index++);\r
+ }\r
+#endif\r
+\r
+ return follower::apply\r
+ (\r
+ linestring, areal,\r
+ geometry::detail::overlay::operation_intersection,\r
+ turns, robust_policy, out\r
+ );\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::intersection\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ // real types\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ // orientation\r
+ bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,\r
+ bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,\r
+ bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,\r
+ // tag dispatching:\r
+ typename TagIn1 = typename geometry::tag<Geometry1>::type,\r
+ typename TagIn2 = typename geometry::tag<Geometry2>::type,\r
+ typename TagOut = typename geometry::tag<GeometryOut>::type,\r
+ // metafunction finetuning helpers:\r
+ bool Areal1 = geometry::is_areal<Geometry1>::value,\r
+ bool Areal2 = geometry::is_areal<Geometry2>::value,\r
+ bool ArealOut = geometry::is_areal<GeometryOut>::value\r
+>\r
+struct intersection_insert\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS\r
+ , (types<Geometry1, Geometry2, GeometryOut>)\r
+ );\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename TagIn1, typename TagIn2, typename TagOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Geometry1, Geometry2,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ TagIn1, TagIn2, TagOut,\r
+ true, true, true\r
+ > : detail::overlay::overlay\r
+ <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>\r
+{};\r
+\r
+\r
+// Any areal type with box:\r
+template\r
+<\r
+ typename Geometry, typename Box,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename TagIn, typename TagOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Geometry, Box,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ TagIn, box_tag, TagOut,\r
+ true, true, true\r
+ > : detail::overlay::overlay\r
+ <Geometry, Box, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Segment1, typename Segment2,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Segment1, Segment2,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ segment_tag, segment_tag, point_tag,\r
+ false, false, false\r
+ > : detail::intersection::intersection_segment_segment_point<GeometryOut>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring1, typename Linestring2,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring1, Linestring2,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ linestring_tag, linestring_tag, point_tag,\r
+ false, false, false\r
+ > : detail::intersection::intersection_linestring_linestring_point<GeometryOut>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring, typename Box,\r
+ typename GeometryOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring, Box,\r
+ GeometryOut,\r
+ overlay_intersection,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ linestring_tag, box_tag, linestring_tag,\r
+ false, true, false\r
+ >\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Linestring const& linestring,\r
+ Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out, Strategy const& )\r
+ {\r
+ typedef typename point_type<GeometryOut>::type point_type;\r
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;\r
+ return detail::intersection::clip_range_with_box\r
+ <GeometryOut>(box, linestring, robust_policy, out, lb_strategy);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring, typename Polygon,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReverseLinestring, bool ReversePolygon, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring, Polygon,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReverseLinestring, ReversePolygon, ReverseOut,\r
+ linestring_tag, polygon_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::intersection_of_linestring_with_areal\r
+ <\r
+ ReversePolygon,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring, typename Ring,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool ReverseLinestring, bool ReverseRing, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring, Ring,\r
+ GeometryOut,\r
+ OverlayType,\r
+ ReverseLinestring, ReverseRing, ReverseOut,\r
+ linestring_tag, ring_tag, linestring_tag,\r
+ false, true, false\r
+ > : detail::intersection::intersection_of_linestring_with_areal\r
+ <\r
+ ReverseRing,\r
+ GeometryOut,\r
+ OverlayType\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename Segment, typename Box,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Segment, Box,\r
+ GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ segment_tag, box_tag, linestring_tag,\r
+ false, true, false\r
+ >\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Segment const& segment,\r
+ Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out, Strategy const& )\r
+ {\r
+ geometry::segment_view<Segment> range(segment);\r
+\r
+ typedef typename point_type<GeometryOut>::type point_type;\r
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;\r
+ return detail::intersection::clip_range_with_box\r
+ <GeometryOut>(box, range, robust_policy, out, lb_strategy);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename Tag1, typename Tag2,\r
+ bool Areal1, bool Areal2\r
+>\r
+struct intersection_insert\r
+ <\r
+ Geometry1, Geometry2,\r
+ PointOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ Tag1, Tag2, point_tag,\r
+ Areal1, Areal2, false\r
+ >\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out, Strategy const& )\r
+ {\r
+\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ PointOut,\r
+ typename segment_ratio_type<PointOut, RobustPolicy>::type\r
+ > turn_info;\r
+ std::vector<turn_info> turns;\r
+\r
+ detail::get_turns::no_interrupt_policy policy;\r
+ geometry::get_turns\r
+ <\r
+ false, false, detail::overlay::assign_null_policy\r
+ >(geometry1, geometry2, robust_policy, turns, policy);\r
+ for (typename std::vector<turn_info>::const_iterator it\r
+ = turns.begin(); it != turns.end(); ++it)\r
+ {\r
+ *out++ = it->point;\r
+ }\r
+\r
+ return out;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert_reversed\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Geometry1 const& g1,\r
+ Geometry2 const& g2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ return intersection_insert\r
+ <\r
+ Geometry2, Geometry1, GeometryOut,\r
+ OverlayType,\r
+ Reverse2, Reverse1, ReverseOut\r
+ >::apply(g2, g1, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+// dispatch for intersection(areal, areal, linear)\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename LinestringOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename Tag1, typename Tag2\r
+>\r
+struct intersection_insert\r
+ <\r
+ Geometry1, Geometry2,\r
+ LinestringOut,\r
+ overlay_intersection,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ Tag1, Tag2, linestring_tag,\r
+ true, true, false\r
+ >\r
+{\r
+ template\r
+ <\r
+ typename RobustPolicy, typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator oit,\r
+ Strategy const& strategy)\r
+ {\r
+ detail::boundary_view<Geometry1 const> view1(geometry1);\r
+ detail::boundary_view<Geometry2 const> view2(geometry2);\r
+\r
+ return detail::overlay::linear_linear_linestring\r
+ <\r
+ detail::boundary_view<Geometry1 const>,\r
+ detail::boundary_view<Geometry2 const>,\r
+ LinestringOut,\r
+ overlay_intersection\r
+ >::apply(view1, view2, robust_policy, oit, strategy);\r
+ }\r
+};\r
+\r
+// dispatch for non-areal geometries\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename GeometryOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename TagIn1, typename TagIn2\r
+>\r
+struct intersection_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ TagIn1, TagIn2, linestring_tag,\r
+ false, false, false\r
+ > : intersection_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut,\r
+ OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ typename tag_cast<TagIn1, pointlike_tag, linear_tag>::type,\r
+ typename tag_cast<TagIn2, pointlike_tag, linear_tag>::type,\r
+ linestring_tag,\r
+ false, false, false\r
+ >\r
+{};\r
+\r
+\r
+// dispatch for difference/intersection of linear geometries\r
+template\r
+<\r
+ typename Linear1, typename Linear2, typename LineStringOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linear1, Linear2, LineStringOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ linear_tag, linear_tag, linestring_tag,\r
+ false, false, false\r
+ > : detail::overlay::linear_linear_linestring\r
+ <\r
+ Linear1, Linear2, LineStringOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+// dispatch for difference/intersection of point-like geometries\r
+\r
+template\r
+<\r
+ typename Point1, typename Point2, typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Point1, Point2, PointOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ point_tag, point_tag, point_tag,\r
+ false, false, false\r
+ > : detail::overlay::point_point_point\r
+ <\r
+ Point1, Point2, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint, typename Point, typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiPoint, Point, PointOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ multi_point_tag, point_tag, point_tag,\r
+ false, false, false\r
+ > : detail::overlay::multipoint_point_point\r
+ <\r
+ MultiPoint, Point, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Point, typename MultiPoint, typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Point, MultiPoint, PointOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ point_tag, multi_point_tag, point_tag,\r
+ false, false, false\r
+ > : detail::overlay::point_multipoint_point\r
+ <\r
+ Point, MultiPoint, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint1, typename MultiPoint2, typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiPoint1, MultiPoint2, PointOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ multi_point_tag, multi_point_tag, point_tag,\r
+ false, false, false\r
+ > : detail::overlay::multipoint_multipoint_point\r
+ <\r
+ MultiPoint1, MultiPoint2, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+// dispatch for difference/intersection of pointlike-linear geometries\r
+template\r
+<\r
+ typename Point, typename Linear, typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename Tag\r
+>\r
+struct intersection_insert\r
+ <\r
+ Point, Linear, PointOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ point_tag, Tag, point_tag,\r
+ false, false, false\r
+ > : detail_dispatch::overlay::pointlike_linear_point\r
+ <\r
+ Point, Linear, PointOut, OverlayType,\r
+ point_tag, typename tag_cast<Tag, segment_tag, linear_tag>::type\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint, typename Linear, typename PointOut,\r
+ overlay_type OverlayType,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename Tag\r
+>\r
+struct intersection_insert\r
+ <\r
+ MultiPoint, Linear, PointOut, OverlayType,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ multi_point_tag, Tag, point_tag,\r
+ false, false, false\r
+ > : detail_dispatch::overlay::pointlike_linear_point\r
+ <\r
+ MultiPoint, Linear, PointOut, OverlayType,\r
+ multi_point_tag,\r
+ typename tag_cast<Tag, segment_tag, linear_tag>::type\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Linestring, typename MultiPoint, typename PointOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct intersection_insert\r
+ <\r
+ Linestring, MultiPoint, PointOut, overlay_intersection,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ linestring_tag, multi_point_tag, point_tag,\r
+ false, false, false\r
+ >\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Linestring const& linestring,\r
+ MultiPoint const& multipoint,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ return detail_dispatch::overlay::pointlike_linear_point\r
+ <\r
+ MultiPoint, Linestring, PointOut, overlay_intersection,\r
+ multi_point_tag, linear_tag\r
+ >::apply(multipoint, linestring, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace intersection\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename GeometryOut,\r
+ bool ReverseSecond,\r
+ overlay_type OverlayType,\r
+ typename Geometry1, typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+>\r
+inline OutputIterator insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+{\r
+ return boost::mpl::if_c\r
+ <\r
+ geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,\r
+ geometry::dispatch::intersection_insert_reversed\r
+ <\r
+ Geometry1, Geometry2,\r
+ GeometryOut,\r
+ OverlayType,\r
+ overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,\r
+ overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,\r
+ overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value\r
+ >,\r
+ geometry::dispatch::intersection_insert\r
+ <\r
+ Geometry1, Geometry2,\r
+ GeometryOut,\r
+ OverlayType,\r
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,\r
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value\r
+ >\r
+ >::type::apply(geometry1, geometry2, robust_policy, out, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{intersection} \brief_strategy\r
+\ingroup intersection\r
+\details \details_calc2{intersection_insert, spatial set theoretic intersection}\r
+ \brief_strategy. \details_insert{intersection}\r
+\tparam GeometryOut \tparam_geometry{\p_l_or_c}\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam OutputIterator \tparam_out{\p_l_or_c}\r
+\tparam Strategy \tparam_strategy_overlay\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{intersection}\r
+\param strategy \param_strategy{intersection}\r
+\return \return_out\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/intersection.qbk]}\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+>\r
+inline OutputIterator intersection_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ typedef typename Strategy::rescale_policy_type rescale_policy_type;\r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);\r
+\r
+ return detail::intersection::insert\r
+ <\r
+ GeometryOut, false, overlay_intersection\r
+ >(geometry1, geometry2, robust_policy, out, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{intersection}\r
+\ingroup intersection\r
+\details \details_calc2{intersection_insert, spatial set theoretic intersection}.\r
+ \details_insert{intersection}\r
+\tparam GeometryOut \tparam_geometry{\p_l_or_c}\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam OutputIterator \tparam_out{\p_l_or_c}\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{intersection}\r
+\return \return_out\r
+\r
+\qbk{[include reference/algorithms/intersection.qbk]}\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator intersection_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ OutputIterator out)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ typedef typename geometry::rescale_policy_type\r
+ <\r
+ typename geometry::point_type<Geometry1>::type // TODO from both\r
+ >::type rescale_policy_type;\r
+\r
+ typedef intersection_strategies\r
+ <\r
+ typename cs_tag<GeometryOut>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ typename geometry::point_type<GeometryOut>::type,\r
+ rescale_policy_type\r
+ > strategy;\r
+\r
+ return intersection_insert<GeometryOut>(geometry1, geometry2, out,\r
+ strategy());\r
+}\r
+\r
+}} // namespace detail::intersection\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <map>\r
+#include <set>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+// Wraps "turn_operation" from turn_info.hpp,\r
+// giving it extra information, necessary for sorting\r
+template <typename TurnOperation>\r
+struct indexed_turn_operation\r
+{\r
+ typedef TurnOperation type;\r
+\r
+ std::size_t turn_index;\r
+ std::size_t operation_index;\r
+ bool skip;\r
+ // use pointers to avoid copies, const& is not possible because of usage in vector\r
+ segment_identifier const* other_seg_id; // segment id of other segment of intersection of two segments\r
+ TurnOperation const* subject;\r
+\r
+ inline indexed_turn_operation(std::size_t ti, std::size_t oi,\r
+ TurnOperation const& sub,\r
+ segment_identifier const& oid)\r
+ : turn_index(ti)\r
+ , operation_index(oi)\r
+ , skip(false)\r
+ , other_seg_id(&oid)\r
+ , subject(boost::addressof(sub))\r
+ {}\r
+\r
+};\r
+\r
+template\r
+<\r
+ typename Turns,\r
+ typename Indexed,\r
+ typename Geometry1, typename Geometry2,\r
+ typename RobustPolicy,\r
+ bool Reverse1, bool Reverse2\r
+>\r
+struct less_by_segment_ratio\r
+{\r
+ inline less_by_segment_ratio(Turns const& turns\r
+ , operation_type for_operation\r
+ , Geometry1 const& geometry1\r
+ , Geometry2 const& geometry2\r
+ , RobustPolicy const& robust_policy)\r
+ : m_turns(turns)\r
+ , m_for_operation(for_operation)\r
+ , m_geometry1(geometry1)\r
+ , m_geometry2(geometry2)\r
+ , m_robust_policy(robust_policy)\r
+ {\r
+ }\r
+\r
+private :\r
+\r
+ Turns const& m_turns;\r
+ operation_type m_for_operation;\r
+ Geometry1 const& m_geometry1;\r
+ Geometry2 const& m_geometry2;\r
+ RobustPolicy const& m_robust_policy;\r
+\r
+ typedef typename geometry::point_type<Geometry1>::type point_type;\r
+\r
+ inline bool default_order(Indexed const& left, Indexed const& right) const\r
+ {\r
+ // We've nothing to sort on. Take the indexes\r
+ return left.turn_index < right.turn_index;\r
+ }\r
+\r
+ inline bool consider_relative_order(Indexed const& left,\r
+ Indexed const& right) const\r
+ {\r
+ point_type pi, pj, ri, rj, si, sj;\r
+\r
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,\r
+ left.subject->seg_id,\r
+ pi, pj);\r
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,\r
+ *left.other_seg_id,\r
+ ri, rj);\r
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,\r
+ *right.other_seg_id,\r
+ si, sj);\r
+\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type\r
+ >::type strategy;\r
+\r
+ int const side_rj_p = strategy::apply(pi, pj, rj);\r
+ int const side_sj_p = strategy::apply(pi, pj, sj);\r
+\r
+ // Put the one turning left (1; right == -1) as last\r
+ if (side_rj_p != side_sj_p)\r
+ {\r
+ return side_rj_p < side_sj_p;\r
+ }\r
+\r
+ int const side_sj_r = strategy::apply(ri, rj, sj);\r
+ int const side_rj_s = strategy::apply(si, sj, rj);\r
+\r
+ // If they both turn left: the most left as last\r
+ // If they both turn right: this is not relevant, but take also here most left\r
+ if (side_rj_s != side_sj_r)\r
+ {\r
+ return side_rj_s < side_sj_r;\r
+ }\r
+\r
+ return default_order(left, right);\r
+ }\r
+\r
+\r
+public :\r
+\r
+ // Note that left/right do NOT correspond to m_geometry1/m_geometry2\r
+ // but to the "indexed_turn_operation"\r
+ inline bool operator()(Indexed const& left, Indexed const& right) const\r
+ {\r
+ if (! (left.subject->seg_id == right.subject->seg_id))\r
+ {\r
+ return left.subject->seg_id < right.subject->seg_id;\r
+ }\r
+\r
+ // Both left and right are located on the SAME segment.\r
+\r
+ if (! (left.subject->fraction == right.subject->fraction))\r
+ {\r
+ return left.subject->fraction < right.subject->fraction;\r
+ }\r
+\r
+\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ turn_type const& left_turn = m_turns[left.turn_index];\r
+ turn_type const& right_turn = m_turns[right.turn_index];\r
+\r
+ // First check "real" intersection (crosses)\r
+ // -> distance zero due to precision, solve it by sorting\r
+ if (left_turn.method == method_crosses\r
+ && right_turn.method == method_crosses)\r
+ {\r
+ return consider_relative_order(left, right);\r
+ }\r
+\r
+ bool const left_both_xx = left_turn.both(operation_blocked);\r
+ bool const right_both_xx = right_turn.both(operation_blocked);\r
+ if (left_both_xx && ! right_both_xx)\r
+ {\r
+ return true;\r
+ }\r
+ if (! left_both_xx && right_both_xx)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ bool const left_both_uu = left_turn.both(operation_union);\r
+ bool const right_both_uu = right_turn.both(operation_union);\r
+ if (left_both_uu && ! right_both_uu)\r
+ {\r
+ return true;\r
+ }\r
+ if (! left_both_uu && right_both_uu)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return default_order(left, right);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/turns.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/turns/compare_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/turns/filter_continue_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename LineStringOut,\r
+ overlay_type OverlayType,\r
+ typename Geometry,\r
+ typename GeometryTag\r
+>\r
+struct linear_linear_no_intersections;\r
+\r
+\r
+template <typename LineStringOut, typename LineString>\r
+struct linear_linear_no_intersections\r
+ <\r
+ LineStringOut, overlay_difference, LineString, linestring_tag\r
+ >\r
+{\r
+ template <typename OutputIterator>\r
+ static inline OutputIterator apply(LineString const& linestring,\r
+ OutputIterator oit)\r
+ {\r
+ LineStringOut ls_out;\r
+ geometry::convert(linestring, ls_out);\r
+ *oit++ = ls_out;\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+template <typename LineStringOut, typename MultiLineString>\r
+struct linear_linear_no_intersections\r
+ <\r
+ LineStringOut,\r
+ overlay_difference,\r
+ MultiLineString,\r
+ multi_linestring_tag\r
+ >\r
+{\r
+ template <typename OutputIterator>\r
+ static inline OutputIterator apply(MultiLineString const& multilinestring,\r
+ OutputIterator oit)\r
+ {\r
+ for (typename boost::range_iterator<MultiLineString const>::type\r
+ it = boost::begin(multilinestring);\r
+ it != boost::end(multilinestring); ++it)\r
+ {\r
+ LineStringOut ls_out;\r
+ geometry::convert(*it, ls_out);\r
+ *oit++ = ls_out;\r
+ }\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+template <typename LineStringOut, typename Geometry, typename GeometryTag>\r
+struct linear_linear_no_intersections\r
+ <\r
+ LineStringOut, overlay_intersection, Geometry, GeometryTag\r
+ >\r
+{\r
+ template <typename OutputIterator>\r
+ static inline OutputIterator apply(Geometry const&,\r
+ OutputIterator oit)\r
+ {\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Linear1,\r
+ typename Linear2,\r
+ typename LinestringOut,\r
+ overlay_type OverlayType,\r
+ bool EnableFilterContinueTurns = false,\r
+ bool EnableRemoveDuplicateTurns = false,\r
+ bool EnableDegenerateTurns = true,\r
+#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS\r
+ bool EnableFollowIsolatedPoints = false\r
+#else\r
+ bool EnableFollowIsolatedPoints = true\r
+#endif\r
+>\r
+class linear_linear_linestring\r
+{\r
+protected:\r
+ struct assign_policy\r
+ {\r
+ static bool const include_no_turn = false;\r
+ static bool const include_degenerate = EnableDegenerateTurns;\r
+ static bool const include_opposite = false;\r
+\r
+ template\r
+ <\r
+ typename Info,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename IntersectionInfo\r
+ >\r
+ static inline void apply(Info& , Point1 const& , Point2 const& ,\r
+ IntersectionInfo const& )\r
+ {\r
+ }\r
+ };\r
+\r
+\r
+ template\r
+ <\r
+ typename Turns,\r
+ typename LinearGeometry1,\r
+ typename LinearGeometry2,\r
+ typename RobustPolicy\r
+ >\r
+ static inline void compute_turns(Turns& turns,\r
+ LinearGeometry1 const& linear1,\r
+ LinearGeometry2 const& linear2,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ turns.clear();\r
+\r
+ detail::get_turns::no_interrupt_policy interrupt_policy;\r
+\r
+ geometry::detail::relate::turns::get_turns\r
+ <\r
+ LinearGeometry1,\r
+ LinearGeometry2,\r
+ detail::get_turns::get_turn_info_type\r
+ <\r
+ LinearGeometry1,\r
+ LinearGeometry2,\r
+ assign_policy\r
+ >,\r
+ RobustPolicy\r
+ >::apply(turns, linear1, linear2, interrupt_policy, robust_policy);\r
+ }\r
+\r
+\r
+ template\r
+ <\r
+ overlay_type OverlayTypeForFollow,\r
+ bool FollowIsolatedPoints,\r
+ typename Turns,\r
+ typename LinearGeometry1,\r
+ typename LinearGeometry2,\r
+ typename OutputIterator\r
+ >\r
+ static inline OutputIterator\r
+ sort_and_follow_turns(Turns& turns,\r
+ LinearGeometry1 const& linear1,\r
+ LinearGeometry2 const& linear2,\r
+ OutputIterator oit)\r
+ {\r
+ // remove turns that have no added value\r
+ turns::filter_continue_turns\r
+ <\r
+ Turns,\r
+ EnableFilterContinueTurns && OverlayType != overlay_intersection\r
+ >::apply(turns);\r
+\r
+ // sort by seg_id, distance, and operation\r
+ std::sort(boost::begin(turns), boost::end(turns),\r
+ detail::turns::less_seg_fraction_other_op<>());\r
+\r
+ // remove duplicate turns\r
+ turns::remove_duplicate_turns\r
+ <\r
+ Turns, EnableRemoveDuplicateTurns\r
+ >::apply(turns);\r
+\r
+ return detail::overlay::following::linear::follow\r
+ <\r
+ LinestringOut,\r
+ LinearGeometry1,\r
+ LinearGeometry2,\r
+ OverlayTypeForFollow,\r
+ FollowIsolatedPoints,\r
+ !EnableFilterContinueTurns || OverlayType == overlay_intersection\r
+ >::apply(linear1, linear2, boost::begin(turns), boost::end(turns),\r
+ oit);\r
+ }\r
+\r
+public:\r
+ template\r
+ <\r
+ typename RobustPolicy, typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Linear1 const& linear1,\r
+ Linear2 const& linear2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator oit,\r
+ Strategy const& )\r
+ {\r
+ typedef typename detail::relate::turns::get_turns\r
+ <\r
+ Linear1,\r
+ Linear2,\r
+ detail::get_turns::get_turn_info_type\r
+ <\r
+ Linear1,\r
+ Linear2,\r
+ assign_policy\r
+ >,\r
+ RobustPolicy\r
+ >::turn_info turn_info;\r
+\r
+ typedef std::vector<turn_info> turns_container;\r
+\r
+ turns_container turns;\r
+ compute_turns(turns, linear1, linear2, robust_policy);\r
+\r
+ if ( turns.empty() )\r
+ {\r
+ // the two linear geometries are disjoint\r
+ return linear_linear_no_intersections\r
+ <\r
+ LinestringOut,\r
+ OverlayType,\r
+ Linear1,\r
+ typename tag<Linear1>::type\r
+ >::apply(linear1, oit);\r
+ }\r
+\r
+ return sort_and_follow_turns\r
+ <\r
+ OverlayType,\r
+ EnableFollowIsolatedPoints\r
+ && OverlayType == overlay_intersection\r
+ >(turns, linear1, linear2, oit);\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Linear1,\r
+ typename Linear2,\r
+ typename LinestringOut,\r
+ bool EnableFilterContinueTurns,\r
+ bool EnableRemoveDuplicateTurns,\r
+ bool EnableDegenerateTurns,\r
+ bool EnableFollowIsolatedPoints\r
+>\r
+struct linear_linear_linestring\r
+ <\r
+ Linear1, Linear2, LinestringOut, overlay_union,\r
+ EnableFilterContinueTurns, EnableRemoveDuplicateTurns,\r
+ EnableDegenerateTurns, EnableFollowIsolatedPoints\r
+ >\r
+{\r
+ template\r
+ <\r
+ typename RobustPolicy, typename OutputIterator, typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Linear1 const& linear1,\r
+ Linear2 const& linear2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator oit,\r
+ Strategy const& strategy)\r
+ {\r
+ oit = linear_linear_no_intersections\r
+ <\r
+ LinestringOut,\r
+ overlay_difference,\r
+ Linear1,\r
+ typename tag<Linear1>::type\r
+ >::apply(linear1, oit);\r
+\r
+ return linear_linear_linestring\r
+ <\r
+ Linear2, Linear1, LinestringOut, overlay_difference,\r
+ EnableFilterContinueTurns, EnableRemoveDuplicateTurns,\r
+ EnableDegenerateTurns, EnableFollowIsolatedPoints\r
+ >::apply(linear2, linear1, robust_policy, oit, strategy);\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP\r
+\r
+\r
+#include <deque>\r
+#include <map>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+#include <boost/geometry/algorithms/reverse.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE\r
+# include <boost/geometry/io/dsv/write.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+//! Default visitor for overlay, doing nothing\r
+struct overlay_null_visitor\r
+{\r
+ void print(char const* ) {}\r
+\r
+ template <typename Turns>\r
+ void print(char const* , Turns const& , int) {}\r
+\r
+ template <typename Turns>\r
+ void print(char const* , Turns const& , int , int ) {}\r
+\r
+ template <typename Turns>\r
+ void visit_turns(int , Turns const& ) {}\r
+\r
+ template <typename Clusters, typename Turns>\r
+ void visit_clusters(Clusters const& , Turns const& ) {}\r
+\r
+ template <typename Turns, typename Turn, typename Operation>\r
+ void visit_traverse(Turns const& , Turn const& , Operation const& , char const*)\r
+ {}\r
+\r
+ template <typename Turns, typename Turn, typename Operation>\r
+ void visit_traverse_reject(Turns const& , Turn const& , Operation const& , traverse_error_type )\r
+ {}\r
+};\r
+\r
+template <typename Turns, typename TurnInfoMap>\r
+inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns)\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::container_type container_type;\r
+\r
+ for (typename boost::range_iterator<Turns const>::type\r
+ it = boost::begin(turns);\r
+ it != boost::end(turns);\r
+ ++it)\r
+ {\r
+ typename boost::range_value<Turns>::type const& turn_info = *it;\r
+\r
+ if (turn_info.discarded\r
+ && ! turn_info.any_blocked()\r
+ && ! turn_info.colocated)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ for (typename boost::range_iterator<container_type const>::type\r
+ op_it = boost::begin(turn_info.operations);\r
+ op_it != boost::end(turn_info.operations);\r
+ ++op_it)\r
+ {\r
+ ring_identifier const ring_id\r
+ (\r
+ op_it->seg_id.source_index,\r
+ op_it->seg_id.multi_index,\r
+ op_it->seg_id.ring_index\r
+ );\r
+ turn_info_map[ring_id].has_normal_turn = true;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename GeometryOut, overlay_type OverlayType, bool ReverseOut,\r
+ typename Geometry1, typename Geometry2,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ OutputIterator out)\r
+{\r
+ typedef std::deque\r
+ <\r
+ typename geometry::ring_type<GeometryOut>::type\r
+ > ring_container_type;\r
+\r
+ typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+ // Union: return either of them\r
+ // Intersection: return nothing\r
+ // Difference: return first of them\r
+ if (OverlayType == overlay_intersection\r
+ || (OverlayType == overlay_difference && geometry::is_empty(geometry1)))\r
+ {\r
+ return out;\r
+ }\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+\r
+ std::map<ring_identifier, ring_turn_info> empty;\r
+ std::map<ring_identifier, properties> all_of_one_of_them;\r
+\r
+ select_rings<OverlayType>(geometry1, geometry2, empty, all_of_one_of_them);\r
+ ring_container_type rings;\r
+ assign_parents(geometry1, geometry2, rings, all_of_one_of_them);\r
+ return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut,\r
+ typename GeometryOut,\r
+ overlay_type OverlayType\r
+>\r
+struct overlay\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy, typename Visitor>\r
+ static inline OutputIterator apply(\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& ,\r
+ Visitor& visitor)\r
+ {\r
+ bool const is_empty1 = geometry::is_empty(geometry1);\r
+ bool const is_empty2 = geometry::is_empty(geometry2);\r
+\r
+ if (is_empty1 && is_empty2)\r
+ {\r
+ return out;\r
+ }\r
+\r
+ if (is_empty1 || is_empty2)\r
+ {\r
+ return return_if_one_input_is_empty\r
+ <\r
+ GeometryOut, OverlayType, ReverseOut\r
+ >(geometry1, geometry2, out);\r
+ }\r
+\r
+ typedef typename geometry::point_type<GeometryOut>::type point_type;\r
+ typedef detail::overlay::traversal_turn_info\r
+ <\r
+ point_type,\r
+ typename geometry::segment_ratio_type<point_type, RobustPolicy>::type\r
+ > turn_info;\r
+ typedef std::deque<turn_info> turn_container_type;\r
+\r
+ typedef std::deque\r
+ <\r
+ typename geometry::ring_type<GeometryOut>::type\r
+ > ring_container_type;\r
+\r
+ // Define the clusters, mapping cluster_id -> turns\r
+ typedef std::map\r
+ <\r
+ signed_size_type,\r
+ cluster_info\r
+ > cluster_type;\r
+\r
+ turn_container_type turns;\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE\r
+std::cout << "get turns" << std::endl;\r
+#endif\r
+ detail::get_turns::no_interrupt_policy policy;\r
+ geometry::get_turns\r
+ <\r
+ Reverse1, Reverse2,\r
+ detail::overlay::assign_null_policy\r
+ >(geometry1, geometry2, robust_policy, turns, policy);\r
+\r
+ visitor.visit_turns(1, turns);\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE\r
+std::cout << "enrich" << std::endl;\r
+#endif\r
+ typename Strategy::side_strategy_type side_strategy;\r
+ cluster_type clusters;\r
+\r
+ geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,\r
+ clusters, geometry1, geometry2,\r
+ robust_policy,\r
+ side_strategy);\r
+\r
+ visitor.visit_turns(2, turns);\r
+\r
+ visitor.visit_clusters(clusters, turns);\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE\r
+std::cout << "traverse" << std::endl;\r
+#endif\r
+ // Traverse through intersection/turn points and create rings of them.\r
+ // Note that these rings are always in clockwise order, even in CCW polygons,\r
+ // and are marked as "to be reversed" below\r
+ ring_container_type rings;\r
+ traverse<Reverse1, Reverse2, Geometry1, Geometry2, OverlayType>::apply\r
+ (\r
+ geometry1, geometry2,\r
+ robust_policy,\r
+ turns, rings,\r
+ clusters,\r
+ visitor\r
+ );\r
+\r
+ std::map<ring_identifier, ring_turn_info> turn_info_per_ring;\r
+ get_ring_turn_info(turn_info_per_ring, turns);\r
+\r
+ typedef ring_properties\r
+ <\r
+ typename geometry::point_type<GeometryOut>::type\r
+ > properties;\r
+\r
+ // Select all rings which are NOT touched by any intersection point\r
+ std::map<ring_identifier, properties> selected_ring_properties;\r
+ select_rings<OverlayType>(geometry1, geometry2, turn_info_per_ring,\r
+ selected_ring_properties);\r
+\r
+ // Add rings created during traversal\r
+ {\r
+ ring_identifier id(2, 0, -1);\r
+ for (typename boost::range_iterator<ring_container_type>::type\r
+ it = boost::begin(rings);\r
+ it != boost::end(rings);\r
+ ++it)\r
+ {\r
+ selected_ring_properties[id] = properties(*it);\r
+ selected_ring_properties[id].reversed = ReverseOut;\r
+ id.multi_index++;\r
+ }\r
+ }\r
+\r
+ assign_parents(geometry1, geometry2, rings, selected_ring_properties);\r
+\r
+ return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);\r
+ }\r
+\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(\r
+ Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ overlay_null_visitor visitor;\r
+ return apply(geometry1, geometry2, robust_policy, out, strategy, visitor);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// TODO: move to detail\r
+enum overlay_type\r
+{\r
+ overlay_union,\r
+ overlay_intersection,\r
+ overlay_difference,\r
+ overlay_buffer,\r
+ overlay_dissolve\r
+};\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+enum operation_type\r
+{\r
+ operation_none,\r
+ operation_union,\r
+ operation_intersection,\r
+ operation_blocked,\r
+ operation_continue,\r
+ operation_opposite\r
+};\r
+\r
+\r
+template <overlay_type OverlayType>\r
+struct operation_from_overlay\r
+{\r
+ static const operation_type value = operation_union;\r
+};\r
+\r
+template <>\r
+struct operation_from_overlay<overlay_intersection>\r
+{\r
+ static const operation_type value = operation_intersection;\r
+};\r
+\r
+template <>\r
+struct operation_from_overlay<overlay_difference>\r
+{\r
+ static const operation_type value = operation_intersection;\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP\r
+\r
+#include <iterator>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/iterators/segment_iterator.hpp>\r
+\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/not.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/less.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+// action struct for pointlike-linear difference/intersection\r
+// it works the same as its pointlike-pointlike counterpart, hence the\r
+// derivation\r
+template <typename PointOut, overlay_type OverlayType>\r
+struct action_selector_pl_l\r
+ : action_selector_pl_pl<PointOut, OverlayType>\r
+{};\r
+\r
+// difference/intersection of point-linear\r
+template\r
+<\r
+ typename Point,\r
+ typename Linear,\r
+ typename PointOut,\r
+ overlay_type OverlayType,\r
+ typename Policy\r
+>\r
+struct point_linear_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Point const& point,\r
+ Linear const& linear,\r
+ RobustPolicy const&,\r
+ OutputIterator oit,\r
+ Strategy const&)\r
+ {\r
+ action_selector_pl_l\r
+ <\r
+ PointOut, OverlayType\r
+ >::apply(point, Policy::apply(point, linear), oit);\r
+ return oit;\r
+ }\r
+};\r
+\r
+// difference/intersection of multipoint-segment\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename Segment,\r
+ typename PointOut,\r
+ overlay_type OverlayType,\r
+ typename Policy\r
+>\r
+struct multipoint_segment_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(MultiPoint const& multipoint,\r
+ Segment const& segment,\r
+ RobustPolicy const&,\r
+ OutputIterator oit,\r
+ Strategy const&)\r
+ {\r
+ for (typename boost::range_iterator<MultiPoint const>::type\r
+ it = boost::begin(multipoint);\r
+ it != boost::end(multipoint);\r
+ ++it)\r
+ {\r
+ action_selector_pl_l\r
+ <\r
+ PointOut, OverlayType\r
+ >::apply(*it, Policy::apply(*it, segment), oit);\r
+ }\r
+\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+// difference/intersection of multipoint-linear\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename Linear,\r
+ typename PointOut,\r
+ overlay_type OverlayType,\r
+ typename Policy\r
+>\r
+class multipoint_linear_point\r
+{\r
+private:\r
+ // structs for partition -- start\r
+ struct expand_box\r
+ {\r
+ template <typename Box, typename Geometry>\r
+ static inline void apply(Box& total, Geometry const& geometry)\r
+ {\r
+ geometry::expand(total, geometry::return_envelope<Box>(geometry));\r
+ }\r
+\r
+ };\r
+\r
+ struct overlaps_box\r
+ {\r
+ template <typename Box, typename Geometry>\r
+ static inline bool apply(Box const& box, Geometry const& geometry)\r
+ {\r
+ return ! geometry::disjoint(geometry, box);\r
+ }\r
+ };\r
+\r
+ template <typename OutputIterator>\r
+ class item_visitor_type\r
+ {\r
+ public:\r
+ item_visitor_type(OutputIterator& oit) : m_oit(oit) {}\r
+\r
+ template <typename Item1, typename Item2>\r
+ inline void apply(Item1 const& item1, Item2 const& item2)\r
+ {\r
+ action_selector_pl_l\r
+ <\r
+ PointOut, overlay_intersection\r
+ >::apply(item1, Policy::apply(item1, item2), m_oit);\r
+ }\r
+\r
+ private:\r
+ OutputIterator& m_oit;\r
+ };\r
+ // structs for partition -- end\r
+\r
+ class segment_range\r
+ {\r
+ public:\r
+ typedef geometry::segment_iterator<Linear const> const_iterator;\r
+ typedef const_iterator iterator;\r
+\r
+ segment_range(Linear const& linear)\r
+ : m_linear(linear)\r
+ {}\r
+\r
+ const_iterator begin() const\r
+ {\r
+ return geometry::segments_begin(m_linear);\r
+ }\r
+\r
+ const_iterator end() const\r
+ {\r
+ return geometry::segments_end(m_linear);\r
+ }\r
+\r
+ private:\r
+ Linear const& m_linear;\r
+ };\r
+\r
+ template <typename OutputIterator>\r
+ static inline OutputIterator get_common_points(MultiPoint const& multipoint,\r
+ Linear const& linear,\r
+ OutputIterator oit)\r
+ {\r
+ item_visitor_type<OutputIterator> item_visitor(oit);\r
+\r
+ segment_range rng(linear);\r
+\r
+ geometry::partition\r
+ <\r
+ geometry::model::box\r
+ <\r
+ typename boost::range_value<MultiPoint>::type\r
+ >,\r
+ expand_box,\r
+ overlaps_box\r
+ >::apply(multipoint, rng, item_visitor);\r
+\r
+ return oit;\r
+ }\r
+\r
+public:\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(MultiPoint const& multipoint,\r
+ Linear const& linear,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator oit,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef std::vector\r
+ <\r
+ typename boost::range_value<MultiPoint>::type\r
+ > point_vector_type;\r
+\r
+ point_vector_type common_points;\r
+\r
+ // compute the common points\r
+ get_common_points(multipoint, linear,\r
+ std::back_inserter(common_points));\r
+\r
+ return multipoint_multipoint_point\r
+ <\r
+ MultiPoint, point_vector_type, PointOut, OverlayType\r
+ >::apply(multipoint, common_points, robust_policy, oit, strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch { namespace overlay\r
+{\r
+\r
+// dispatch struct for pointlike-linear difference/intersection computation\r
+template\r
+<\r
+ typename PointLike,\r
+ typename Linear,\r
+ typename PointOut,\r
+ overlay_type OverlayType,\r
+ typename Tag1,\r
+ typename Tag2\r
+>\r
+struct pointlike_linear_point\r
+ : not_implemented<PointLike, Linear, PointOut>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Linear,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_linear_point\r
+ <\r
+ Point, Linear, PointOut, OverlayType, point_tag, linear_tag\r
+ > : detail::overlay::point_linear_point\r
+ <\r
+ Point, Linear, PointOut, OverlayType,\r
+ detail::not_<detail::disjoint::reverse_covered_by>\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Segment,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_linear_point\r
+ <\r
+ Point, Segment, PointOut, OverlayType, point_tag, segment_tag\r
+ > : detail::overlay::point_linear_point\r
+ <\r
+ Point, Segment, PointOut, OverlayType,\r
+ detail::not_<detail::disjoint::reverse_covered_by>\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename Linear,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_linear_point\r
+ <\r
+ MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag\r
+ > : detail::overlay::multipoint_linear_point\r
+ <\r
+ MultiPoint, Linear, PointOut, OverlayType,\r
+ detail::not_<detail::disjoint::reverse_covered_by>\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename Segment,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_linear_point\r
+ <\r
+ MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag\r
+ > : detail::overlay::multipoint_segment_point\r
+ <\r
+ MultiPoint, Segment, PointOut, OverlayType,\r
+ detail::not_<detail::disjoint::reverse_covered_by>\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace detail_dispatch::overlay\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/less.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+// struct for copying points of the pointlike geometries to output\r
+template\r
+<\r
+ typename PointOut,\r
+ typename GeometryIn,\r
+ typename TagIn = typename tag<GeometryIn>::type\r
+>\r
+struct copy_points\r
+ : not_implemented<PointOut, GeometryIn>\r
+{};\r
+\r
+template <typename PointOut, typename PointIn>\r
+struct copy_points<PointOut, PointIn, point_tag>\r
+{\r
+ template <typename OutputIterator>\r
+ static inline void apply(PointIn const& point_in,\r
+ OutputIterator& oit)\r
+ {\r
+ PointOut point_out;\r
+ geometry::convert(point_in, point_out);\r
+ *oit++ = point_out;\r
+ }\r
+};\r
+\r
+\r
+template <typename PointOut, typename MultiPointIn>\r
+struct copy_points<PointOut, MultiPointIn, multi_point_tag>\r
+{\r
+ template <typename OutputIterator>\r
+ static inline void apply(MultiPointIn const& multi_point_in,\r
+ OutputIterator& oit)\r
+ {\r
+ for (typename boost::range_iterator<MultiPointIn const>::type\r
+ it = boost::begin(multi_point_in);\r
+ it != boost::end(multi_point_in); ++it)\r
+ {\r
+ PointOut point_out;\r
+ geometry::convert(*it, point_out);\r
+ *oit++ = point_out;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+// action struct for difference/intersection\r
+template <typename PointOut, overlay_type OverlayType>\r
+struct action_selector_pl_pl\r
+{};\r
+\r
+template <typename PointOut>\r
+struct action_selector_pl_pl<PointOut, overlay_intersection>\r
+{\r
+ template\r
+ <\r
+ typename Point,\r
+ typename OutputIterator\r
+ >\r
+ static inline void apply(Point const& point,\r
+ bool is_common,\r
+ OutputIterator& oit)\r
+ {\r
+ if ( is_common )\r
+ {\r
+ copy_points<PointOut, Point>::apply(point, oit);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename PointOut>\r
+struct action_selector_pl_pl<PointOut, overlay_difference>\r
+{\r
+ template\r
+ <\r
+ typename Point,\r
+ typename OutputIterator\r
+ >\r
+ static inline void apply(Point const& point,\r
+ bool is_common,\r
+ OutputIterator& oit)\r
+ {\r
+ if ( !is_common )\r
+ {\r
+ copy_points<PointOut, Point>::apply(point, oit);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+//===========================================================================\r
+\r
+// difference/intersection of point-point\r
+template\r
+<\r
+ typename Point1,\r
+ typename Point2,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct point_point_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Point1 const& point1,\r
+ Point2 const& point2,\r
+ RobustPolicy const& ,\r
+ OutputIterator oit,\r
+ Strategy const&)\r
+ {\r
+ action_selector_pl_pl\r
+ <\r
+ PointOut, OverlayType\r
+ >::apply(point1,\r
+ detail::equals::equals_point_point(point1, point2),\r
+ oit);\r
+\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+\r
+// difference of multipoint-point\r
+//\r
+// the apply method in the following struct is called only for\r
+// difference; for intersection the reversal will\r
+// always call the point-multipoint version\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename Point,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct multipoint_point_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(MultiPoint const& multipoint,\r
+ Point const& point,\r
+ RobustPolicy const& ,\r
+ OutputIterator oit,\r
+ Strategy const&)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference );\r
+\r
+ for (typename boost::range_iterator<MultiPoint const>::type\r
+ it = boost::begin(multipoint);\r
+ it != boost::end(multipoint); ++it)\r
+ {\r
+ action_selector_pl_pl\r
+ <\r
+ PointOut, OverlayType\r
+ >::apply(*it,\r
+ detail::equals::equals_point_point(*it, point),\r
+ oit);\r
+ }\r
+\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+// difference/intersection of point-multipoint\r
+template\r
+<\r
+ typename Point,\r
+ typename MultiPoint,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct point_multipoint_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Point const& point,\r
+ MultiPoint const& multipoint,\r
+ RobustPolicy const& ,\r
+ OutputIterator oit,\r
+ Strategy const&)\r
+ {\r
+ typedef action_selector_pl_pl<PointOut, OverlayType> action;\r
+\r
+ for (typename boost::range_iterator<MultiPoint const>::type\r
+ it = boost::begin(multipoint);\r
+ it != boost::end(multipoint); ++it)\r
+ {\r
+ if ( detail::equals::equals_point_point(*it, point) )\r
+ {\r
+ action::apply(point, true, oit);\r
+ return oit;\r
+ }\r
+ }\r
+\r
+ action::apply(point, false, oit);\r
+ return oit;\r
+ }\r
+};\r
+\r
+\r
+\r
+// difference/intersection of multipoint-multipoint\r
+template\r
+<\r
+ typename MultiPoint1,\r
+ typename MultiPoint2,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct multipoint_multipoint_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(MultiPoint1 const& multipoint1,\r
+ MultiPoint2 const& multipoint2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator oit,\r
+ Strategy const& strategy)\r
+ {\r
+ if ( OverlayType != overlay_difference\r
+ && boost::size(multipoint1) > boost::size(multipoint2) )\r
+ {\r
+ return multipoint_multipoint_point\r
+ <\r
+ MultiPoint2, MultiPoint1, PointOut, OverlayType\r
+ >::apply(multipoint2, multipoint1, robust_policy, oit, strategy);\r
+ }\r
+\r
+ std::vector<typename boost::range_value<MultiPoint2>::type>\r
+ points2(boost::begin(multipoint2), boost::end(multipoint2));\r
+\r
+ std::sort(points2.begin(), points2.end(), detail::relate::less());\r
+\r
+ for (typename boost::range_iterator<MultiPoint1 const>::type\r
+ it1 = boost::begin(multipoint1);\r
+ it1 != boost::end(multipoint1); ++it1)\r
+ {\r
+ bool found = std::binary_search(points2.begin(), points2.end(),\r
+ *it1, detail::relate::less());\r
+\r
+ action_selector_pl_pl\r
+ <\r
+ PointOut, OverlayType\r
+ >::apply(*it1, found, oit);\r
+ }\r
+ return oit;\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch { namespace overlay\r
+{\r
+\r
+// dispatch struct for pointlike-pointlike difference/intersection\r
+// computation\r
+template\r
+<\r
+ typename PointLike1,\r
+ typename PointLike2,\r
+ typename PointOut,\r
+ overlay_type OverlayType,\r
+ typename Tag1,\r
+ typename Tag2\r
+>\r
+struct pointlike_pointlike_point\r
+ : not_implemented<PointLike1, PointLike2, PointOut>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Point1,\r
+ typename Point2,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_pointlike_point\r
+ <\r
+ Point1, Point2, PointOut, OverlayType,\r
+ point_tag, point_tag\r
+ > : detail::overlay::point_point_point\r
+ <\r
+ Point1, Point2, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename MultiPoint,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_pointlike_point\r
+ <\r
+ Point, MultiPoint, PointOut, OverlayType,\r
+ point_tag, multi_point_tag\r
+ > : detail::overlay::point_multipoint_point\r
+ <\r
+ Point, MultiPoint, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint,\r
+ typename Point,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_pointlike_point\r
+ <\r
+ MultiPoint, Point, PointOut, OverlayType,\r
+ multi_point_tag, point_tag\r
+ > : detail::overlay::multipoint_point_point\r
+ <\r
+ MultiPoint, Point, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPoint1,\r
+ typename MultiPoint2,\r
+ typename PointOut,\r
+ overlay_type OverlayType\r
+>\r
+struct pointlike_pointlike_point\r
+ <\r
+ MultiPoint1, MultiPoint2, PointOut, OverlayType,\r
+ multi_point_tag, multi_point_tag\r
+ > : detail::overlay::multipoint_multipoint_point\r
+ <\r
+ MultiPoint1, MultiPoint2, PointOut, OverlayType\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace detail_dispatch::overlay\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+// generic pointlike-pointlike union implementation\r
+template\r
+<\r
+ typename PointLike1,\r
+ typename PointLike2,\r
+ typename PointOut\r
+>\r
+struct union_pointlike_pointlike_point\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(PointLike1 const& pointlike1,\r
+ PointLike2 const& pointlike2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator oit,\r
+ Strategy const& strategy)\r
+ {\r
+ copy_points<PointOut, PointLike1>::apply(pointlike1, oit);\r
+\r
+ return detail_dispatch::overlay::pointlike_pointlike_point\r
+ <\r
+ PointLike2, PointLike1, PointOut, overlay_difference,\r
+ typename tag<PointLike2>::type,\r
+ typename tag<PointLike1>::type\r
+ >::apply(pointlike2, pointlike1, robust_policy, oit, strategy);\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template <typename Point>\r
+struct ring_properties\r
+{\r
+ typedef Point point_type;\r
+ typedef typename default_area_result<Point>::type area_type;\r
+\r
+ bool valid;\r
+\r
+ // Filled by "select_rings"\r
+ Point point;\r
+ area_type area;\r
+\r
+ // Filled by "update_ring_selection"\r
+ bool reversed;\r
+\r
+ // Filled/used by "assign_rings"\r
+ bool discarded;\r
+ ring_identifier parent;\r
+ area_type parent_area;\r
+ std::vector<ring_identifier> children;\r
+\r
+ inline ring_properties()\r
+ : valid(false)\r
+ , area(area_type())\r
+ , reversed(false)\r
+ , discarded(false)\r
+ , parent_area(-1)\r
+ {}\r
+\r
+ template <typename RingOrBox>\r
+ inline ring_properties(RingOrBox const& ring_or_box)\r
+ : reversed(false)\r
+ , discarded(false)\r
+ , parent_area(-1)\r
+ {\r
+ this->area = geometry::area(ring_or_box);\r
+ // We should take a point somewhere in the middle of the ring,\r
+ // to avoid taking a point on a (self)tangency,\r
+ // in cases where multiple points come together\r
+ valid = geometry::point_on_border(this->point, ring_or_box, true);\r
+ }\r
+\r
+ inline area_type get_area() const\r
+ {\r
+ return reversed ? -area : area;\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP\r
+\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_OVERLAY)\r
+# define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER\r
+#endif\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER)\r
+#include <iostream>\r
+#endif\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+\r
+// Internal struct to uniquely identify a segment\r
+// on a linestring,ring\r
+// or polygon (needs ring_index)\r
+// or multi-geometry (needs multi_index)\r
+struct segment_identifier\r
+{\r
+ inline segment_identifier()\r
+ : source_index(-1)\r
+ , multi_index(-1)\r
+ , ring_index(-1)\r
+ , segment_index(-1)\r
+ , piece_index(-1)\r
+ {}\r
+\r
+ inline segment_identifier(signed_size_type src,\r
+ signed_size_type mul,\r
+ signed_size_type rin,\r
+ signed_size_type seg)\r
+ : source_index(src)\r
+ , multi_index(mul)\r
+ , ring_index(rin)\r
+ , segment_index(seg)\r
+ , piece_index(-1)\r
+ {}\r
+\r
+ inline bool operator<(segment_identifier const& other) const\r
+ {\r
+ return source_index != other.source_index ? source_index < other.source_index\r
+ : multi_index !=other.multi_index ? multi_index < other.multi_index\r
+ : ring_index != other.ring_index ? ring_index < other.ring_index\r
+ : segment_index < other.segment_index\r
+ ;\r
+ }\r
+\r
+ inline bool operator==(segment_identifier const& other) const\r
+ {\r
+ return source_index == other.source_index\r
+ && segment_index == other.segment_index\r
+ && ring_index == other.ring_index\r
+ && multi_index == other.multi_index\r
+ ;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER)\r
+ friend std::ostream& operator<<(std::ostream &os, segment_identifier const& seg_id)\r
+ {\r
+ os\r
+ << "s:" << seg_id.source_index\r
+ << ", v:" << seg_id.segment_index // v:vertex because s is used for source\r
+ ;\r
+ if (seg_id.ring_index >= 0) os << ", r:" << seg_id.ring_index;\r
+ if (seg_id.multi_index >= 0) os << ", m:" << seg_id.multi_index;\r
+ return os;\r
+ }\r
+#endif\r
+\r
+ signed_size_type source_index;\r
+ signed_size_type multi_index;\r
+ signed_size_type ring_index;\r
+ signed_size_type segment_index;\r
+\r
+ // For buffer - todo: move this to buffer-only\r
+ signed_size_type piece_index;\r
+};\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP\r
+\r
+\r
+#include <map>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+struct ring_turn_info\r
+{\r
+ bool has_normal_turn;\r
+ bool within_other;\r
+\r
+ ring_turn_info()\r
+ : has_normal_turn(false)\r
+ , within_other(false)\r
+ {}\r
+};\r
+\r
+namespace dispatch\r
+{\r
+\r
+ template <typename Tag, typename Geometry>\r
+ struct select_rings\r
+ {};\r
+\r
+ template <typename Box>\r
+ struct select_rings<box_tag, Box>\r
+ {\r
+ template <typename Geometry, typename RingPropertyMap>\r
+ static inline void apply(Box const& box, Geometry const& ,\r
+ ring_identifier const& id, RingPropertyMap& ring_properties)\r
+ {\r
+ ring_properties[id] = typename RingPropertyMap::mapped_type(box);\r
+ }\r
+\r
+ template <typename RingPropertyMap>\r
+ static inline void apply(Box const& box,\r
+ ring_identifier const& id, RingPropertyMap& ring_properties)\r
+ {\r
+ ring_properties[id] = typename RingPropertyMap::mapped_type(box);\r
+ }\r
+ };\r
+\r
+ template <typename Ring>\r
+ struct select_rings<ring_tag, Ring>\r
+ {\r
+ template <typename Geometry, typename RingPropertyMap>\r
+ static inline void apply(Ring const& ring, Geometry const& ,\r
+ ring_identifier const& id, RingPropertyMap& ring_properties)\r
+ {\r
+ if (boost::size(ring) > 0)\r
+ {\r
+ ring_properties[id] = typename RingPropertyMap::mapped_type(ring);\r
+ }\r
+ }\r
+\r
+ template <typename RingPropertyMap>\r
+ static inline void apply(Ring const& ring,\r
+ ring_identifier const& id, RingPropertyMap& ring_properties)\r
+ {\r
+ if (boost::size(ring) > 0)\r
+ {\r
+ ring_properties[id] = typename RingPropertyMap::mapped_type(ring);\r
+ }\r
+ }\r
+ };\r
+\r
+\r
+ template <typename Polygon>\r
+ struct select_rings<polygon_tag, Polygon>\r
+ {\r
+ template <typename Geometry, typename RingPropertyMap>\r
+ static inline void apply(Polygon const& polygon, Geometry const& geometry,\r
+ ring_identifier id, RingPropertyMap& ring_properties)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+ typedef select_rings<ring_tag, ring_type> per_ring;\r
+\r
+ per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties);\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ id.ring_index++;\r
+ per_ring::apply(*it, geometry, id, ring_properties);\r
+ }\r
+ }\r
+\r
+ template <typename RingPropertyMap>\r
+ static inline void apply(Polygon const& polygon,\r
+ ring_identifier id, RingPropertyMap& ring_properties)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+ typedef select_rings<ring_tag, ring_type> per_ring;\r
+\r
+ per_ring::apply(exterior_ring(polygon), id, ring_properties);\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ id.ring_index++;\r
+ per_ring::apply(*it, id, ring_properties);\r
+ }\r
+ }\r
+ };\r
+\r
+ template <typename Multi>\r
+ struct select_rings<multi_polygon_tag, Multi>\r
+ {\r
+ template <typename Geometry, typename RingPropertyMap>\r
+ static inline void apply(Multi const& multi, Geometry const& geometry,\r
+ ring_identifier id, RingPropertyMap& ring_properties)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ Multi const\r
+ >::type iterator_type;\r
+\r
+ typedef select_rings<polygon_tag, typename boost::range_value<Multi>::type> per_polygon;\r
+\r
+ id.multi_index = 0;\r
+ for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)\r
+ {\r
+ id.ring_index = -1;\r
+ per_polygon::apply(*it, geometry, id, ring_properties);\r
+ id.multi_index++;\r
+ }\r
+ }\r
+ };\r
+\r
+} // namespace dispatch\r
+\r
+\r
+template<overlay_type OverlayType>\r
+struct decide\r
+{\r
+ // Default implementation (union, inflate, deflate, dissolve)\r
+ static bool include(ring_identifier const& , ring_turn_info const& info)\r
+ {\r
+ return ! info.within_other;\r
+ }\r
+\r
+ static bool reversed(ring_identifier const& , ring_turn_info const& )\r
+ {\r
+ return false;\r
+ }\r
+\r
+};\r
+\r
+template<>\r
+struct decide<overlay_difference>\r
+{\r
+ static bool include(ring_identifier const& id, ring_turn_info const& info)\r
+ {\r
+ // Difference: A - B\r
+\r
+ // If this is A (source_index=0), then the ring is inside B\r
+ // If this is B (source_index=1), then the ring is NOT inside A\r
+\r
+ // If this is A and the ring is within the other geometry,\r
+ // then we should NOT include it.\r
+ // If this is B then we SHOULD include it.\r
+\r
+ return id.source_index == 0\r
+ ? ! info.within_other\r
+ : info.within_other;\r
+ }\r
+\r
+ static bool reversed(ring_identifier const& id, ring_turn_info const& info)\r
+ {\r
+ // Difference: A - B\r
+ // If this is B, and the ring is included, it should be reversed afterwards\r
+\r
+ return id.source_index == 1 && include(id, info);\r
+ }\r
+};\r
+\r
+template<>\r
+struct decide<overlay_intersection>\r
+{\r
+ static bool include(ring_identifier const& , ring_turn_info const& info)\r
+ {\r
+ return info.within_other;\r
+ }\r
+\r
+ static bool reversed(ring_identifier const& , ring_turn_info const& )\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ overlay_type OverlayType,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename TurnInfoMap,\r
+ typename RingPropertyMap\r
+>\r
+inline void update_ring_selection(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ TurnInfoMap const& turn_info_map,\r
+ RingPropertyMap const& all_ring_properties,\r
+ RingPropertyMap& selected_ring_properties)\r
+{\r
+ selected_ring_properties.clear();\r
+\r
+ for (typename RingPropertyMap::const_iterator it = boost::begin(all_ring_properties);\r
+ it != boost::end(all_ring_properties);\r
+ ++it)\r
+ {\r
+ ring_identifier const& id = it->first;\r
+\r
+ ring_turn_info info;\r
+\r
+ typename TurnInfoMap::const_iterator tcit = turn_info_map.find(id);\r
+ if (tcit != turn_info_map.end())\r
+ {\r
+ info = tcit->second; // Copy by value\r
+ }\r
+\r
+ if (info.has_normal_turn)\r
+ {\r
+ // There are normal turns on this ring. It should be traversed, we\r
+ // don't include the original ring\r
+ continue;\r
+ }\r
+\r
+ // Check if the ring is within the other geometry, by taking\r
+ // a point lying on the ring\r
+ switch(id.source_index)\r
+ {\r
+ case 0 :\r
+ info.within_other = geometry::within(it->second.point, geometry2);\r
+ break;\r
+ case 1 :\r
+ info.within_other = geometry::within(it->second.point, geometry1);\r
+ break;\r
+ }\r
+\r
+ if (decide<OverlayType>::include(id, info))\r
+ {\r
+ typename RingPropertyMap::mapped_type properties = it->second; // Copy by value\r
+ properties.reversed = decide<OverlayType>::reversed(id, info);\r
+ selected_ring_properties[id] = properties;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/*!\r
+\brief The function select_rings select rings based on the overlay-type (union,intersection)\r
+*/\r
+template\r
+<\r
+ overlay_type OverlayType,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RingTurnInfoMap,\r
+ typename RingPropertyMap\r
+>\r
+inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ RingTurnInfoMap const& turn_info_per_ring,\r
+ RingPropertyMap& selected_ring_properties)\r
+{\r
+ typedef typename geometry::tag<Geometry1>::type tag1;\r
+ typedef typename geometry::tag<Geometry2>::type tag2;\r
+\r
+ RingPropertyMap all_ring_properties;\r
+ dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,\r
+ ring_identifier(0, -1, -1), all_ring_properties);\r
+ dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,\r
+ ring_identifier(1, -1, -1), all_ring_properties);\r
+\r
+ update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,\r
+ all_ring_properties, selected_ring_properties);\r
+}\r
+\r
+template\r
+<\r
+ overlay_type OverlayType,\r
+ typename Geometry,\r
+ typename RingTurnInfoMap,\r
+ typename RingPropertyMap\r
+>\r
+inline void select_rings(Geometry const& geometry,\r
+ RingTurnInfoMap const& turn_info_per_ring,\r
+ RingPropertyMap& selected_ring_properties)\r
+{\r
+ typedef typename geometry::tag<Geometry>::type tag;\r
+\r
+ RingPropertyMap all_ring_properties;\r
+ dispatch::select_rings<tag, Geometry>::apply(geometry,\r
+ ring_identifier(0, -1, -1), all_ring_properties);\r
+\r
+ update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,\r
+ all_ring_properties, selected_ring_properties);\r
+}\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/vector_c.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>\r
+#include <boost/geometry/algorithms/detail/partition.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace self_get_turn_points\r
+{\r
+\r
+struct no_interrupt_policy\r
+{\r
+ static bool const enabled = false;\r
+ static bool const has_intersections = false;\r
+\r
+\r
+ template <typename Range>\r
+ static inline bool apply(Range const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+class self_ip_exception : public geometry::exception {};\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Turns,\r
+ typename TurnPolicy,\r
+ typename RobustPolicy,\r
+ typename InterruptPolicy\r
+>\r
+struct self_section_visitor\r
+{\r
+ Geometry const& m_geometry;\r
+ RobustPolicy const& m_rescale_policy;\r
+ Turns& m_turns;\r
+ InterruptPolicy& m_interrupt_policy;\r
+\r
+ inline self_section_visitor(Geometry const& g,\r
+ RobustPolicy const& rp,\r
+ Turns& turns, InterruptPolicy& ip)\r
+ : m_geometry(g)\r
+ , m_rescale_policy(rp)\r
+ , m_turns(turns)\r
+ , m_interrupt_policy(ip)\r
+ {}\r
+\r
+ template <typename Section>\r
+ inline bool apply(Section const& sec1, Section const& sec2)\r
+ {\r
+ if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box)\r
+ && ! sec1.duplicate\r
+ && ! sec2.duplicate)\r
+ {\r
+ detail::get_turns::get_turns_in_sections\r
+ <\r
+ Geometry, Geometry,\r
+ false, false,\r
+ Section, Section,\r
+ TurnPolicy\r
+ >::apply(\r
+ 0, m_geometry, sec1,\r
+ 0, m_geometry, sec2,\r
+ false,\r
+ m_rescale_policy,\r
+ m_turns, m_interrupt_policy);\r
+ }\r
+ if (BOOST_GEOMETRY_CONDITION(m_interrupt_policy.has_intersections))\r
+ {\r
+ // TODO: we should give partition an interrupt policy.\r
+ // Now we throw, and catch below, to stop the partition loop.\r
+ throw self_ip_exception();\r
+ }\r
+ return true;\r
+ }\r
+\r
+};\r
+\r
+\r
+\r
+template<typename TurnPolicy>\r
+struct get_turns\r
+{\r
+ template <typename Geometry, typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline bool apply(\r
+ Geometry const& geometry,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns,\r
+ InterruptPolicy& interrupt_policy)\r
+ {\r
+ typedef model::box\r
+ <\r
+ typename geometry::robust_point_type\r
+ <\r
+ typename geometry::point_type<Geometry>::type,\r
+ RobustPolicy\r
+ >::type\r
+ > box_type;\r
+\r
+ typedef geometry::sections<box_type, 1> sections_type;\r
+\r
+ typedef boost::mpl::vector_c<std::size_t, 0> dimensions;\r
+\r
+ sections_type sec;\r
+ geometry::sectionalize<false, dimensions>(geometry, robust_policy, sec);\r
+\r
+ self_section_visitor\r
+ <\r
+ Geometry,\r
+ Turns, TurnPolicy, RobustPolicy, InterruptPolicy\r
+ > visitor(geometry, robust_policy, turns, interrupt_policy);\r
+\r
+ try\r
+ {\r
+ geometry::partition\r
+ <\r
+ box_type,\r
+ detail::section::get_section_box,\r
+ detail::section::overlaps_section_box\r
+ >::apply(sec, visitor);\r
+ }\r
+ catch(self_ip_exception const& )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::self_get_turn_points\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename GeometryTag,\r
+ typename Geometry,\r
+ typename TurnPolicy\r
+>\r
+struct self_get_turn_points\r
+{\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Ring,\r
+ typename TurnPolicy\r
+>\r
+struct self_get_turn_points\r
+ <\r
+ ring_tag, Ring,\r
+ TurnPolicy\r
+ >\r
+ : detail::self_get_turn_points::get_turns<TurnPolicy>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Box,\r
+ typename TurnPolicy\r
+>\r
+struct self_get_turn_points\r
+ <\r
+ box_tag, Box,\r
+ TurnPolicy\r
+ >\r
+{\r
+ template <typename RobustPolicy, typename Turns, typename InterruptPolicy>\r
+ static inline bool apply(\r
+ Box const& ,\r
+ RobustPolicy const& ,\r
+ Turns& ,\r
+ InterruptPolicy& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Polygon,\r
+ typename TurnPolicy\r
+>\r
+struct self_get_turn_points\r
+ <\r
+ polygon_tag, Polygon,\r
+ TurnPolicy\r
+ >\r
+ : detail::self_get_turn_points::get_turns<TurnPolicy>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename MultiPolygon,\r
+ typename TurnPolicy\r
+>\r
+struct self_get_turn_points\r
+ <\r
+ multi_polygon_tag, MultiPolygon,\r
+ TurnPolicy\r
+ >\r
+ : detail::self_get_turn_points::get_turns<TurnPolicy>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+ \brief Calculate self intersections of a geometry\r
+ \ingroup overlay\r
+ \tparam Geometry geometry type\r
+ \tparam Turns type of intersection container\r
+ (e.g. vector of "intersection/turn point"'s)\r
+ \param geometry geometry\r
+ \param robust_policy policy to handle robustness issues\r
+ \param turns container which will contain intersection points\r
+ \param interrupt_policy policy determining if process is stopped\r
+ when intersection is found\r
+ */\r
+template\r
+<\r
+ typename AssignPolicy,\r
+ typename Geometry,\r
+ typename RobustPolicy,\r
+ typename Turns,\r
+ typename InterruptPolicy\r
+>\r
+inline void self_turns(Geometry const& geometry,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns, InterruptPolicy& interrupt_policy)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;\r
+\r
+ dispatch::self_get_turn_points\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ turn_policy\r
+ >::apply(geometry, robust_policy, turns, interrupt_policy);\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/geometry/algorithms/detail/direction_code.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay { namespace sort_by_side\r
+{\r
+\r
+enum direction_type { dir_unknown = -1, dir_from = 0, dir_to = 1 };\r
+\r
+// Point-wrapper, adding some properties\r
+template <typename Point>\r
+struct ranked_point\r
+{\r
+ ranked_point()\r
+ : rank(0)\r
+ , turn_index(-1)\r
+ , operation_index(-1)\r
+ , direction(dir_unknown)\r
+ , count_left(0)\r
+ , count_right(0)\r
+ , operation(operation_none)\r
+ {}\r
+\r
+ ranked_point(const Point& p, signed_size_type ti, signed_size_type oi,\r
+ direction_type d, operation_type op, segment_identifier sid)\r
+ : point(p)\r
+ , rank(0)\r
+ , zone(-1)\r
+ , turn_index(ti)\r
+ , operation_index(oi)\r
+ , direction(d)\r
+ , count_left(0)\r
+ , count_right(0)\r
+ , operation(op)\r
+ , seg_id(sid)\r
+ {}\r
+\r
+ Point point;\r
+ std::size_t rank;\r
+ signed_size_type zone; // index of closed zone, in uu turn there would be 2 zones\r
+ signed_size_type turn_index;\r
+ signed_size_type operation_index;\r
+ direction_type direction;\r
+ std::size_t count_left;\r
+ std::size_t count_right;\r
+ operation_type operation;\r
+ segment_identifier seg_id;\r
+};\r
+\r
+struct less_by_turn_index\r
+{\r
+ template <typename T>\r
+ inline bool operator()(const T& first, const T& second) const\r
+ {\r
+ return first.turn_index == second.turn_index\r
+ ? first.index < second.index\r
+ : first.turn_index < second.turn_index\r
+ ;\r
+ }\r
+};\r
+\r
+struct less_by_index\r
+{\r
+ template <typename T>\r
+ inline bool operator()(const T& first, const T& second) const\r
+ {\r
+ // First order by from/to\r
+ if (first.direction != second.direction)\r
+ {\r
+ return first.direction < second.direction;\r
+ }\r
+ // All the same, order by turn index (we might consider length too)\r
+ return first.turn_index < second.turn_index;\r
+ }\r
+};\r
+\r
+struct less_false\r
+{\r
+ template <typename T>\r
+ inline bool operator()(const T&, const T& ) const\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Point, typename LessOnSame, typename Compare>\r
+struct less_by_side\r
+{\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type side;\r
+\r
+ less_by_side(const Point& p1, const Point& p2)\r
+ : m_p1(p1)\r
+ , m_p2(p2)\r
+ {}\r
+\r
+ template <typename T>\r
+ inline bool operator()(const T& first, const T& second) const\r
+ {\r
+ LessOnSame on_same;\r
+ Compare compare;\r
+\r
+ int const side_first = side::apply(m_p1, m_p2, first.point);\r
+ int const side_second = side::apply(m_p1, m_p2, second.point);\r
+\r
+ if (side_first == 0 && side_second == 0)\r
+ {\r
+ // Both collinear. They might point into different directions: <------*------>\r
+ // If so, order the one going backwards as the very first.\r
+\r
+ int const first_code = direction_code(m_p1, m_p2, first.point);\r
+ int const second_code = direction_code(m_p1, m_p2, second.point);\r
+\r
+ // Order by code, backwards first, then forward.\r
+ return first_code != second_code\r
+ ? first_code < second_code\r
+ : on_same(first, second)\r
+ ;\r
+ }\r
+ else if (side_first == 0\r
+ && direction_code(m_p1, m_p2, first.point) == -1)\r
+ {\r
+ // First collinear and going backwards.\r
+ // Order as the very first, so return always true\r
+ return true;\r
+ }\r
+ else if (side_second == 0\r
+ && direction_code(m_p1, m_p2, second.point) == -1)\r
+ {\r
+ // Second is collinear and going backwards\r
+ // Order as very last, so return always false\r
+ return false;\r
+ }\r
+\r
+ // They are not both collinear\r
+\r
+ if (side_first != side_second)\r
+ {\r
+ return compare(side_first, side_second);\r
+ }\r
+\r
+ // They are both left, both right, and/or both collinear (with each other and/or with p1,p2)\r
+ // Check mutual side\r
+ int const side_second_wrt_first = side::apply(m_p2, first.point, second.point);\r
+\r
+ if (side_second_wrt_first == 0)\r
+ {\r
+ return on_same(first, second);\r
+ }\r
+\r
+ int const side_first_wrt_second = -side_second_wrt_first;\r
+\r
+ // Both are on same side, and not collinear\r
+ // Union: return true if second is right w.r.t. first, so -1,\r
+ // so other is 1. union has greater as compare functor\r
+ // Intersection: v.v.\r
+ return compare(side_first_wrt_second, side_second_wrt_first);\r
+ }\r
+\r
+private :\r
+ Point m_p1, m_p2;\r
+};\r
+\r
+template <bool Reverse1, bool Reverse2, typename Point, typename Compare>\r
+struct side_sorter\r
+{\r
+ typedef ranked_point<Point> rp;\r
+\r
+ inline void set_origin(Point const& origin)\r
+ {\r
+ m_origin = origin;\r
+ }\r
+\r
+ template <typename Operation, typename Geometry1, typename Geometry2>\r
+ void add(Operation const& op, signed_size_type turn_index, signed_size_type op_index,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ bool is_origin)\r
+ {\r
+ Point point1, point2, point3;\r
+ geometry::copy_segment_points<Reverse1, Reverse2>(geometry1, geometry2,\r
+ op.seg_id, point1, point2, point3);\r
+ Point const& point_to = op.fraction.is_one() ? point3 : point2;\r
+\r
+ m_ranked_points.push_back(rp(point1, turn_index, op_index, dir_from, op.operation, op.seg_id));\r
+ m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op.operation, op.seg_id));\r
+\r
+ if (is_origin)\r
+ {\r
+ m_origin = point1;\r
+ }\r
+ }\r
+\r
+ void apply(Point const& turn_point)\r
+ {\r
+ // We need three compare functors:\r
+ // 1) to order clockwise (union) or counter clockwise (intersection)\r
+ // 2) to order by side, resulting in unique ranks for all points\r
+ // 3) to order by side, resulting in non-unique ranks\r
+ // to give colinear points\r
+\r
+ // Sort by side and assign rank\r
+ less_by_side<Point, less_by_index, Compare> less_unique(m_origin, turn_point);\r
+ less_by_side<Point, less_false, Compare> less_non_unique(m_origin, turn_point);\r
+\r
+ std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);\r
+\r
+ std::size_t colinear_rank = 0;\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ if (i > 0\r
+ && less_non_unique(m_ranked_points[i - 1], m_ranked_points[i]))\r
+ {\r
+ // It is not collinear\r
+ colinear_rank++;\r
+ }\r
+\r
+ m_ranked_points[i].rank = colinear_rank;\r
+ }\r
+ }\r
+\r
+ template <signed_size_type segment_identifier::*Member, typename Map>\r
+ void find_open_generic(Map& handled)\r
+ {\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ const rp& ranked = m_ranked_points[i];\r
+ if (ranked.direction != dir_from)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ signed_size_type const& index = ranked.seg_id.*Member;\r
+ if (! handled[index])\r
+ {\r
+ find_polygons_for_source<Member>(index, i);\r
+ handled[index] = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ void find_open()\r
+ {\r
+ // TODO: we might pass Buffer as overlay_type, instead on the fly below\r
+ bool one_source = true;\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ const rp& ranked = m_ranked_points[i];\r
+ signed_size_type const& src = ranked.seg_id.source_index;\r
+ if (src != 0)\r
+ {\r
+ one_source = false;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (one_source)\r
+ {\r
+ // by multi index\r
+ std::map<signed_size_type, bool> handled;\r
+ find_open_generic\r
+ <\r
+ &segment_identifier::piece_index\r
+ >(handled);\r
+ }\r
+ else\r
+ {\r
+ // by source (there should only source 0,1) TODO assert this\r
+ bool handled[2] = {false, false};\r
+ find_open_generic\r
+ <\r
+ &segment_identifier::source_index\r
+ >(handled);\r
+ }\r
+\r
+ assign_zones();\r
+ }\r
+\r
+ void reverse()\r
+ {\r
+ if (m_ranked_points.empty())\r
+ {\r
+ return;\r
+ }\r
+\r
+ int const last = 1 + m_ranked_points.back().rank;\r
+\r
+ // Move iterator after rank==0\r
+ bool has_first = false;\r
+ typename container_type::iterator it = m_ranked_points.begin() + 1;\r
+ for (; it != m_ranked_points.end() && it->rank == 0; ++it)\r
+ {\r
+ has_first = true;\r
+ }\r
+\r
+ if (has_first)\r
+ {\r
+ // Reverse first part (having rank == 0), if any,\r
+ // but skip the very first row\r
+ std::reverse(m_ranked_points.begin() + 1, it);\r
+ for (typename container_type::iterator fit = m_ranked_points.begin();\r
+ fit != it; ++fit)\r
+ {\r
+ BOOST_ASSERT(fit->rank == 0);\r
+ }\r
+ }\r
+\r
+ // Reverse the rest (main rank > 0)\r
+ std::reverse(it, m_ranked_points.end());\r
+ for (; it != m_ranked_points.end(); ++it)\r
+ {\r
+ BOOST_ASSERT(it->rank > 0);\r
+ it->rank = last - it->rank;\r
+ }\r
+ }\r
+\r
+ //! Check how many open spaces there are\r
+ template <typename Turns>\r
+ std::size_t open_count(Turns const& turns) const\r
+ {\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ std::size_t result = 0;\r
+ std::size_t last_rank = 0;\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ rp const& ranked_point = m_ranked_points[i];\r
+\r
+ if (ranked_point.rank > last_rank\r
+ && ranked_point.direction == sort_by_side::dir_to)\r
+ {\r
+ // TODO: take count-left / count_right from rank itself\r
+ turn_type const& ranked_turn = turns[ranked_point.turn_index];\r
+ turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index];\r
+ if (ranked_op.enriched.count_left == 0\r
+ && ranked_op.enriched.count_right > 0)\r
+ {\r
+ result++;\r
+ last_rank = ranked_point.rank;\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+//protected :\r
+\r
+ typedef std::vector<rp> container_type;\r
+ container_type m_ranked_points;\r
+ Point m_origin;\r
+\r
+private :\r
+\r
+\r
+ std::size_t move(std::size_t index) const\r
+ {\r
+ std::size_t const result = index + 1;\r
+ return result >= m_ranked_points.size() ? 0 : result;\r
+ }\r
+\r
+ //! member is pointer to member (source_index or multi_index)\r
+ template <signed_size_type segment_identifier::*Member>\r
+ std::size_t move(signed_size_type member_index, std::size_t index) const\r
+ {\r
+ std::size_t result = move(index);\r
+ while (m_ranked_points[result].seg_id.*Member != member_index)\r
+ {\r
+ result = move(result);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ void assign_ranks(std::size_t min_rank, std::size_t max_rank, int side_index)\r
+ {\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ rp& ranked = m_ranked_points[i];\r
+ // Suppose there are 8 ranks, if min=4,max=6: assign 4,5,6\r
+ // if min=5,max=2: assign from 5,6,7,1,2\r
+ bool const in_range\r
+ = max_rank >= min_rank\r
+ ? ranked.rank >= min_rank && ranked.rank <= max_rank\r
+ : ranked.rank >= min_rank || ranked.rank <= max_rank\r
+ ;\r
+\r
+ if (in_range)\r
+ {\r
+ if (side_index == 1)\r
+ {\r
+ ranked.count_left++;\r
+ }\r
+ else if (side_index == 2)\r
+ {\r
+ ranked.count_right++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ template <signed_size_type segment_identifier::*Member>\r
+ void find_polygons_for_source(signed_size_type the_index,\r
+ std::size_t start_index)\r
+ {\r
+ int state = 1; // 'closed', because start_index is "from", arrives at the turn\r
+ std::size_t last_from_rank = m_ranked_points[start_index].rank;\r
+ std::size_t previous_rank = m_ranked_points[start_index].rank;\r
+\r
+ for (std::size_t index = move<Member>(the_index, start_index);\r
+ ;\r
+ index = move<Member>(the_index, index))\r
+ {\r
+ rp& ranked = m_ranked_points[index];\r
+\r
+ if (ranked.rank != previous_rank && state == 0)\r
+ {\r
+ assign_ranks(last_from_rank, previous_rank - 1, 1);\r
+ assign_ranks(last_from_rank + 1, previous_rank, 2);\r
+ }\r
+\r
+ if (index == start_index)\r
+ {\r
+ return;\r
+ }\r
+\r
+ if (ranked.direction == dir_from)\r
+ {\r
+ last_from_rank = ranked.rank;\r
+ state++;\r
+ }\r
+ else if (ranked.direction == dir_to)\r
+ {\r
+ state--;\r
+ }\r
+\r
+ previous_rank = ranked.rank;\r
+ }\r
+ }\r
+\r
+ //! Find closed zones and assign it\r
+ void assign_zones()\r
+ {\r
+ // Find a starting point (the first rank after an outgoing rank\r
+ // with no polygons on the left side)\r
+ std::size_t start_rank = m_ranked_points.size() + 1;\r
+ std::size_t start_index = 0;\r
+ std::size_t max_rank = 0;\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ rp const& ranked_point = m_ranked_points[i];\r
+ if (ranked_point.rank > max_rank)\r
+ {\r
+ max_rank = ranked_point.rank;\r
+ }\r
+ if (ranked_point.direction == sort_by_side::dir_to\r
+ && ranked_point.count_left == 0\r
+ && ranked_point.count_right > 0)\r
+ {\r
+ start_rank = ranked_point.rank + 1;\r
+ }\r
+ if (ranked_point.rank == start_rank && start_index == 0)\r
+ {\r
+ start_index = i;\r
+ }\r
+ }\r
+\r
+ // Assign the zones\r
+ std::size_t const undefined_rank = max_rank + 1;\r
+ std::size_t zone_id = 0;\r
+ std::size_t last_rank = 0;\r
+ std::size_t rank_at_next_zone = undefined_rank;\r
+ std::size_t index = start_index;\r
+ for (std::size_t i = 0; i < m_ranked_points.size(); i++)\r
+ {\r
+ rp& ranked_point = m_ranked_points[index];\r
+\r
+ // Implement cyclic behavior\r
+ index++;\r
+ if (index == m_ranked_points.size())\r
+ {\r
+ index = 0;\r
+ }\r
+\r
+ if (ranked_point.rank != last_rank)\r
+ {\r
+ if (ranked_point.rank == rank_at_next_zone)\r
+ {\r
+ zone_id++;\r
+ rank_at_next_zone = undefined_rank;\r
+ }\r
+\r
+ if (ranked_point.direction == sort_by_side::dir_to\r
+ && ranked_point.count_left == 0\r
+ && ranked_point.count_right > 0)\r
+ {\r
+ rank_at_next_zone = ranked_point.rank + 1;\r
+ if (rank_at_next_zone > max_rank)\r
+ {\r
+ rank_at_next_zone = 0;\r
+ }\r
+ }\r
+\r
+ last_rank = ranked_point.rank;\r
+ }\r
+\r
+ ranked_point.zone = zone_id;\r
+ }\r
+ }\r
+\r
+\r
+};\r
+\r
+\r
+}}} // namespace detail::overlay::sort_by_side\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP\r
+\r
+\r
+#include <string>\r
+\r
+#include <boost/array.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+ static inline std::string dir(int d)\r
+ {\r
+ return d == 0 ? "-" : (d == 1 ? "L" : d == -1 ? "R" : "#");\r
+ }\r
+ static inline std::string how_str(int h)\r
+ {\r
+ return h == 0 ? "-" : (h == 1 ? "A" : "D");\r
+ }\r
+\r
+ template <typename P>\r
+ std::ostream& operator<<(std::ostream &os, turn_info<P> const& info)\r
+ {\r
+ os << "\t"\r
+ << " src " << info.seg_id.source_index\r
+ << " seg " << info.seg_id.segment_index\r
+ << " (// " << info.other_id.source_index\r
+ << "." << info.other_id.segment_index << ")"\r
+ << " how " << info.how\r
+ << "[" << how_str(info.arrival)\r
+ << " " << dir(info.direction)\r
+ << (info.opposite ? " o" : "")\r
+ << "]"\r
+ << " sd "\r
+ << dir(info.sides.get<0,0>())\r
+ << dir(info.sides.get<0,1>())\r
+ << dir(info.sides.get<1,0>())\r
+ << dir(info.sides.get<1,1>())\r
+ << " nxt seg " << info.travels_to_vertex_index\r
+ << " , ip " << info.travels_to_ip_index\r
+ << " , or " << info.next_ip_index\r
+ << " frac " << info.fraction\r
+ << info.visit_state;\r
+ if (info.flagged)\r
+ {\r
+ os << " FLAGGED";\r
+ }\r
+ return os;\r
+ }\r
+\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \\r
+ || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \\r
+ || defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)\r
+# include <string>\r
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+# include <boost/geometry/io/wkt/wkt.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+template <typename Turn, typename Operation>\r
+#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE\r
+inline void debug_traverse(Turn const& turn, Operation op,\r
+ std::string const& header)\r
+{\r
+ std::cout << header\r
+ << " at " << op.seg_id\r
+ << " meth: " << method_char(turn.method)\r
+ << " op: " << operation_char(op.operation)\r
+ << " vis: " << visited_char(op.visited)\r
+ << " of: " << operation_char(turn.operations[0].operation)\r
+ << operation_char(turn.operations[1].operation)\r
+ << " " << geometry::wkt(turn.point)\r
+ << std::endl;\r
+\r
+ if (boost::contains(header, "Finished"))\r
+ {\r
+ std::cout << std::endl;\r
+ }\r
+}\r
+#else\r
+inline void debug_traverse(Turn const& , Operation, const char*)\r
+{\r
+}\r
+#endif\r
+\r
+\r
+//! Metafunction to define side_order (clockwise, ccw) by operation_type\r
+template <operation_type OpType>\r
+struct side_compare {};\r
+\r
+template <>\r
+struct side_compare<operation_union>\r
+{\r
+ typedef std::greater<int> type;\r
+};\r
+\r
+template <>\r
+struct side_compare<operation_intersection>\r
+{\r
+ typedef std::less<int> type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ bool Reverse1,\r
+ bool Reverse2,\r
+ overlay_type OverlayType,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename RobustPolicy,\r
+ typename Visitor\r
+>\r
+struct traversal\r
+{\r
+ static const operation_type target_operation = operation_from_overlay<OverlayType>::value;\r
+\r
+ typedef typename side_compare<target_operation>::type side_compare_type;\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ typedef typename geometry::point_type<Geometry1>::type point_type;\r
+ typedef sort_by_side::side_sorter\r
+ <\r
+ Reverse1, Reverse2,\r
+ point_type, side_compare_type\r
+ > sbs_type;\r
+\r
+ inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ Turns& turns, Clusters const& clusters,\r
+ RobustPolicy const& robust_policy, Visitor& visitor)\r
+ : m_geometry1(geometry1)\r
+ , m_geometry2(geometry2)\r
+ , m_turns(turns)\r
+ , m_clusters(clusters)\r
+ , m_robust_policy(robust_policy)\r
+ , m_visitor(visitor)\r
+ {\r
+ }\r
+\r
+ inline void finalize_visit_info()\r
+ {\r
+ for (typename boost::range_iterator<Turns>::type\r
+ it = boost::begin(m_turns);\r
+ it != boost::end(m_turns);\r
+ ++it)\r
+ {\r
+ turn_type& turn = *it;\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type& op = turn.operations[i];\r
+ op.visited.finalize();\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void set_visited(turn_type& turn, turn_operation_type& op)\r
+ {\r
+ // On "continue", set "visited" for ALL directions in this turn\r
+ if (op.operation == detail::overlay::operation_continue)\r
+ {\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type& op = turn.operations[i];\r
+ if (op.visited.none())\r
+ {\r
+ op.visited.set_visited();\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ op.visited.set_visited();\r
+ }\r
+ }\r
+\r
+ inline bool is_visited(turn_type const& turn, turn_operation_type const& op,\r
+ signed_size_type turn_index, int op_index) const\r
+ {\r
+ return op.visited.visited();\r
+ }\r
+\r
+ inline bool select_source(signed_size_type turn_index,\r
+ segment_identifier const& seg_id1,\r
+ segment_identifier const& seg_id2) const\r
+ {\r
+ if (target_operation == operation_intersection)\r
+ {\r
+ // For intersections always switch sources\r
+ return seg_id1.source_index != seg_id2.source_index;\r
+ }\r
+ else if (target_operation == operation_union)\r
+ {\r
+ // For uu, only switch sources if indicated\r
+ turn_type const& turn = m_turns[turn_index];\r
+\r
+ if (OverlayType == overlay_buffer)\r
+ {\r
+ // Buffer does not use source_index (always 0)\r
+ return turn.switch_source\r
+ ? seg_id1.multi_index != seg_id2.multi_index\r
+ : seg_id1.multi_index == seg_id2.multi_index;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)\r
+ if (turn.switch_source == 1)\r
+ {\r
+ std::cout << "Switch source at " << turn_index << std::endl;\r
+ }\r
+ else\r
+ {\r
+ std::cout << "DON'T SWITCH SOURCES at " << turn_index << std::endl;\r
+ }\r
+#endif\r
+ return turn.switch_source\r
+ ? seg_id1.source_index != seg_id2.source_index\r
+ : seg_id1.source_index == seg_id2.source_index;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ inline\r
+ signed_size_type get_next_turn_index(turn_operation_type const& op) const\r
+ {\r
+ return op.enriched.next_ip_index == -1\r
+ ? op.enriched.travels_to_ip_index\r
+ : op.enriched.next_ip_index;\r
+ }\r
+\r
+ inline bool traverse_possible(signed_size_type turn_index) const\r
+ {\r
+ if (turn_index == -1)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ turn_type const& turn = m_turns[turn_index];\r
+\r
+ // It is not a dead end if there is an operation to continue, or of\r
+ // there is a cluster (assuming for now we can get out of the cluster)\r
+ return turn.cluster_id >= 0\r
+ || turn.has(target_operation)\r
+ || turn.has(operation_continue);\r
+ }\r
+\r
+ inline\r
+ bool select_cc_operation(turn_type const& turn,\r
+ signed_size_type start_turn_index,\r
+ int& selected_op_index) const\r
+ {\r
+ // For "cc", take either one, but if there is a starting one,\r
+ // take that one. If next is dead end, skip that one.\r
+\r
+ bool result = false;\r
+\r
+ typename turn_operation_type::comparable_distance_type\r
+ max_remaining_distance = 0;\r
+\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type const& op = turn.operations[i];\r
+\r
+ signed_size_type const next_turn_index = get_next_turn_index(op);\r
+\r
+ if (! result && traverse_possible(next_turn_index))\r
+ {\r
+ max_remaining_distance = op.remaining_distance;\r
+ selected_op_index = i;\r
+ debug_traverse(turn, op, " Candidate");\r
+ result = true;\r
+ }\r
+\r
+ if (result)\r
+ {\r
+ if (next_turn_index == start_turn_index)\r
+ {\r
+ selected_op_index = i;\r
+ debug_traverse(turn, op, " Candidate cc override (start)");\r
+ }\r
+ else if (op.remaining_distance > max_remaining_distance)\r
+ {\r
+ max_remaining_distance = op.remaining_distance;\r
+ selected_op_index = i;\r
+ debug_traverse(turn, op, " Candidate cc override (remaining)");\r
+ }\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ inline\r
+ bool select_noncc_operation(turn_type const& turn,\r
+ signed_size_type turn_index,\r
+ segment_identifier const& seg_id,\r
+ int& selected_op_index) const\r
+ {\r
+ // For "ii", take the other one (alternate)\r
+ // UNLESS the other one is already visited\r
+ // For "uu", take the same one (see above);\r
+\r
+ bool result = false;\r
+\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type const& op = turn.operations[i];\r
+\r
+ if (op.operation == target_operation\r
+ && ! op.visited.finished()\r
+ && (! result || select_source(turn_index, op.seg_id, seg_id)))\r
+ {\r
+ selected_op_index = i;\r
+ debug_traverse(turn, op, " Candidate");\r
+ result = true;\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ inline\r
+ bool select_operation(const turn_type& turn,\r
+ signed_size_type turn_index,\r
+ signed_size_type start_turn_index,\r
+ segment_identifier const& previous_seg_id,\r
+ int& selected_op_index) const\r
+ {\r
+ bool result = false;\r
+ selected_op_index = -1;\r
+ if (turn.both(operation_continue))\r
+ {\r
+ result = select_cc_operation(turn, start_turn_index,\r
+ selected_op_index);\r
+ }\r
+ else\r
+ {\r
+ result = select_noncc_operation(turn, turn_index,\r
+ previous_seg_id, selected_op_index);\r
+ }\r
+ if (result)\r
+ {\r
+ debug_traverse(turn, turn.operations[selected_op_index], " Accepted");\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ inline int starting_operation_index(const turn_type& turn) const\r
+ {\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ if (turn.operations[i].visited.started())\r
+ {\r
+ return i;\r
+ }\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ inline bool both_finished(const turn_type& turn) const\r
+ {\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ if (! turn.operations[i].visited.finished())\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ inline bool select_from_cluster(signed_size_type& turn_index,\r
+ int& op_index, signed_size_type start_turn_index,\r
+ sbs_type const& sbs, bool is_touching) const\r
+ {\r
+ bool const is_union = target_operation == operation_union;\r
+ bool const is_intersection = target_operation == operation_intersection;\r
+\r
+ std::size_t selected_rank = 0;\r
+ std::size_t min_rank = 0;\r
+ bool result = false;\r
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)\r
+ {\r
+ typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];\r
+ if (result && ranked_point.rank > selected_rank)\r
+ {\r
+ return result;\r
+ }\r
+\r
+ turn_type const& ranked_turn = m_turns[ranked_point.turn_index];\r
+ turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index];\r
+\r
+ if (result && ranked_op.visited.finalized())\r
+ {\r
+ // One of the arcs in the same direction as the selected result\r
+ // is already traversed.\r
+ return false;\r
+ }\r
+\r
+ if (! is_touching && ranked_op.visited.finalized())\r
+ {\r
+ // Skip this one, go to next\r
+ min_rank = ranked_point.rank;\r
+ continue;\r
+ }\r
+\r
+ if (ranked_point.direction == sort_by_side::dir_to\r
+ && (ranked_point.rank > min_rank\r
+ || ranked_turn.both(operation_continue)))\r
+ {\r
+ if ((is_union\r
+ && ranked_op.enriched.count_left == 0\r
+ && ranked_op.enriched.count_right > 0)\r
+ || (is_intersection\r
+ && ranked_op.enriched.count_right == 2))\r
+ {\r
+ if (result && ranked_point.turn_index != start_turn_index)\r
+ {\r
+ // Don't override - only override if arrive at start\r
+ continue;\r
+ }\r
+\r
+ turn_index = ranked_point.turn_index;\r
+ op_index = ranked_point.operation_index;\r
+\r
+ if (is_intersection\r
+ && ranked_turn.both(operation_intersection)\r
+ && ranked_op.visited.finalized())\r
+ {\r
+ // Override:\r
+ // For a ii turn, even though one operation might be selected,\r
+ // it should take the other one if the first one is used in a completed ring\r
+ op_index = 1 - ranked_point.operation_index;\r
+ }\r
+\r
+ result = true;\r
+ selected_rank = ranked_point.rank;\r
+ }\r
+ else if (! is_touching)\r
+ {\r
+ return result;\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ inline bool select_turn_from_cluster(signed_size_type& turn_index,\r
+ int& op_index, bool& is_touching,\r
+ signed_size_type start_turn_index,\r
+ segment_identifier const& previous_seg_id) const\r
+ {\r
+ bool const is_union = target_operation == operation_union;\r
+\r
+ turn_type const& turn = m_turns[turn_index];\r
+ BOOST_ASSERT(turn.cluster_id >= 0);\r
+\r
+ typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id);\r
+ BOOST_ASSERT(mit != m_clusters.end());\r
+\r
+ cluster_info const& cinfo = mit->second;\r
+ std::set<signed_size_type> const& ids = cinfo.turn_indices;\r
+\r
+ sbs_type sbs;\r
+\r
+ bool has_origin = false;\r
+\r
+ for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();\r
+ sit != ids.end(); ++sit)\r
+ {\r
+ signed_size_type cluster_turn_index = *sit;\r
+ turn_type const& cluster_turn = m_turns[cluster_turn_index];\r
+ if (cluster_turn.discarded)\r
+ {\r
+ // Defensive check, discarded turns should not be in cluster\r
+ continue;\r
+ }\r
+\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ turn_operation_type const& op = cluster_turn.operations[i];\r
+ bool is_origin = false;\r
+ if (cluster_turn_index == turn_index)\r
+ {\r
+ // Check if this is the origin\r
+ if (OverlayType == overlay_buffer)\r
+ {\r
+ is_origin = op.seg_id.multi_index == previous_seg_id.multi_index;\r
+ }\r
+ else\r
+ {\r
+ is_origin = op.seg_id.source_index\r
+ == previous_seg_id.source_index;\r
+ }\r
+ if (is_origin)\r
+ {\r
+ has_origin = true;\r
+ }\r
+ }\r
+\r
+ sbs.add(op, cluster_turn_index, i, m_geometry1, m_geometry2,\r
+ is_origin);\r
+ }\r
+ }\r
+\r
+ if (! has_origin)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ sbs.apply(turn.point);\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)\r
+ is_touching = is_union && cinfo.open_count > 1;\r
+ if (is_touching)\r
+ {\r
+ if (cinfo.switch_source)\r
+ {\r
+ is_touching = false;\r
+ std::cout << "CLUSTER: SWITCH SOURCES at " << turn_index << std::endl;\r
+ }\r
+ else\r
+ {\r
+ std::cout << "CLUSTER: CONTINUE at " << turn_index << std::endl;\r
+ }\r
+ }\r
+#else\r
+ is_touching = is_union && cinfo.open_count > 1 && ! cinfo.switch_source;\r
+#endif\r
+ if (is_touching)\r
+ {\r
+ sbs.reverse();\r
+ }\r
+\r
+ return select_from_cluster(turn_index, op_index, start_turn_index, sbs,\r
+ is_touching);\r
+ }\r
+\r
+ inline void change_index_for_self_turn(signed_size_type& to_vertex_index,\r
+ turn_type const& start_turn,\r
+ turn_operation_type const& start_op,\r
+ int start_op_index) const\r
+ {\r
+ if (OverlayType != overlay_buffer)\r
+ {\r
+ return;\r
+ }\r
+\r
+ // It travels to itself, can happen. If this is a buffer, it can\r
+ // sometimes travel to itself in the following configuration:\r
+ //\r
+ // +---->--+\r
+ // | |\r
+ // | +---*----+ *: one turn, with segment index 2/7\r
+ // | | | |\r
+ // | +---C | C: closing point (start/end)\r
+ // | |\r
+ // +------------+\r
+ //\r
+ // If it starts on segment 2 and travels to itself on segment 2, that\r
+ // should be corrected to 7 because that is the shortest path\r
+ //\r
+ // Also a uu turn (touching with another buffered ring) might have this\r
+ // apparent configuration, but there it should\r
+ // always travel the whole ring\r
+\r
+ turn_operation_type const& other_op\r
+ = start_turn.operations[1 - start_op_index];\r
+\r
+ bool const correct\r
+ = ! start_turn.both(operation_union)\r
+ && start_op.seg_id.segment_index == to_vertex_index;\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)\r
+ std::cout << " WARNING: self-buffer "\r
+ << " correct=" << correct\r
+ << " turn=" << operation_char(start_turn.operations[0].operation)\r
+ << operation_char(start_turn.operations[1].operation)\r
+ << " start=" << start_op.seg_id.segment_index\r
+ << " from=" << to_vertex_index\r
+ << " to=" << other_op.enriched.travels_to_vertex_index\r
+ << std::endl;\r
+#endif\r
+\r
+ if (correct)\r
+ {\r
+ to_vertex_index = other_op.enriched.travels_to_vertex_index;\r
+ }\r
+ }\r
+\r
+ bool select_turn_from_enriched(signed_size_type& turn_index,\r
+ segment_identifier& previous_seg_id,\r
+ signed_size_type& to_vertex_index,\r
+ signed_size_type start_turn_index,\r
+ int start_op_index,\r
+ turn_type const& previous_turn,\r
+ turn_operation_type const& previous_op,\r
+ bool is_start) const\r
+ {\r
+ to_vertex_index = -1;\r
+\r
+ if (previous_op.enriched.next_ip_index < 0)\r
+ {\r
+ // There is no next IP on this segment\r
+ if (previous_op.enriched.travels_to_vertex_index < 0\r
+ || previous_op.enriched.travels_to_ip_index < 0)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ to_vertex_index = previous_op.enriched.travels_to_vertex_index;\r
+\r
+ if (is_start &&\r
+ previous_op.enriched.travels_to_ip_index == start_turn_index)\r
+ {\r
+ change_index_for_self_turn(to_vertex_index, previous_turn,\r
+ previous_op, start_op_index);\r
+ }\r
+\r
+ turn_index = previous_op.enriched.travels_to_ip_index;\r
+ previous_seg_id = previous_op.seg_id;\r
+ }\r
+ else\r
+ {\r
+ // Take the next IP on this segment\r
+ turn_index = previous_op.enriched.next_ip_index;\r
+ previous_seg_id = previous_op.seg_id;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ bool select_turn(signed_size_type start_turn_index,\r
+ signed_size_type& turn_index,\r
+ int& op_index,\r
+ bool& is_touching,\r
+ int previous_op_index,\r
+ signed_size_type previous_turn_index,\r
+ segment_identifier const& previous_seg_id,\r
+ bool is_start)\r
+ {\r
+ if (m_turns[turn_index].cluster_id >= 0)\r
+ {\r
+ if (! select_turn_from_cluster(turn_index, op_index, is_touching,\r
+ start_turn_index, previous_seg_id))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (is_start && turn_index == previous_turn_index)\r
+ {\r
+ op_index = previous_op_index;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ turn_type const& current_turn = m_turns[turn_index];\r
+\r
+ op_index = starting_operation_index(current_turn);\r
+ if (op_index == -1)\r
+ {\r
+ if (both_finished(current_turn))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (! select_operation(current_turn, turn_index,\r
+ start_turn_index,\r
+ previous_seg_id,\r
+ op_index))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+private :\r
+ Geometry1 const& m_geometry1;\r
+ Geometry2 const& m_geometry2;\r
+ Turns& m_turns;\r
+ Clusters const& m_clusters;\r
+ RobustPolicy const& m_robust_policy;\r
+ Visitor& m_visitor;\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/visit_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template <typename Point, typename SegmentRatio>\r
+struct traversal_turn_operation : public turn_operation<Point, SegmentRatio>\r
+{\r
+ enrichment_info<Point> enriched;\r
+ visit_info visited;\r
+};\r
+\r
+template <typename Point, typename SegmentRatio>\r
+struct traversal_turn_info\r
+ : public turn_info\r
+ <\r
+ Point,\r
+ SegmentRatio,\r
+ traversal_turn_operation<Point, SegmentRatio>\r
+ >\r
+{};\r
+\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traversal.hpp>\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template\r
+<\r
+ bool Reverse1,\r
+ bool Reverse2,\r
+ overlay_type OverlayType,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename RobustPolicy,\r
+ typename Visitor,\r
+ typename Backtrack\r
+>\r
+struct traversal_ring_creator\r
+{\r
+ typedef traversal<Reverse1, Reverse2, OverlayType,\r
+ Geometry1, Geometry2, Turns, Clusters, RobustPolicy, Visitor>\r
+ traversal_type;\r
+\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ static const operation_type target_operation\r
+ = operation_from_overlay<OverlayType>::value;\r
+\r
+ inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ Turns& turns, Clusters const& clusters,\r
+ RobustPolicy const& robust_policy, Visitor& visitor)\r
+ : m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor)\r
+ , m_geometry1(geometry1)\r
+ , m_geometry2(geometry2)\r
+ , m_turns(turns)\r
+ , m_clusters(clusters)\r
+ , m_robust_policy(robust_policy)\r
+ , m_visitor(visitor)\r
+ , m_has_uu(false)\r
+ {\r
+\r
+ }\r
+\r
+ template <typename Ring>\r
+ inline traverse_error_type travel_to_next_turn(signed_size_type start_turn_index,\r
+ int start_op_index,\r
+ signed_size_type& turn_index,\r
+ int& op_index,\r
+ Ring& current_ring,\r
+ bool is_start)\r
+ {\r
+ int const previous_op_index = op_index;\r
+ signed_size_type const previous_turn_index = turn_index;\r
+ turn_type& previous_turn = m_turns[turn_index];\r
+ turn_operation_type& previous_op = previous_turn.operations[op_index];\r
+ segment_identifier previous_seg_id;\r
+\r
+ signed_size_type to_vertex_index = -1;\r
+ if (! m_trav.select_turn_from_enriched(turn_index, previous_seg_id,\r
+ to_vertex_index, start_turn_index, start_op_index,\r
+ previous_turn, previous_op, is_start))\r
+ {\r
+ return is_start\r
+ ? traverse_error_no_next_ip_at_start\r
+ : traverse_error_no_next_ip;\r
+ }\r
+ if (to_vertex_index >= 0)\r
+ {\r
+ if (previous_op.seg_id.source_index == 0)\r
+ {\r
+ geometry::copy_segments<Reverse1>(m_geometry1,\r
+ previous_op.seg_id, to_vertex_index,\r
+ m_robust_policy, current_ring);\r
+ }\r
+ else\r
+ {\r
+ geometry::copy_segments<Reverse2>(m_geometry2,\r
+ previous_op.seg_id, to_vertex_index,\r
+ m_robust_policy, current_ring);\r
+ }\r
+ }\r
+\r
+ if (m_turns[turn_index].discarded)\r
+ {\r
+ return is_start\r
+ ? traverse_error_dead_end_at_start\r
+ : traverse_error_dead_end;\r
+ }\r
+\r
+ if (is_start)\r
+ {\r
+ // Register the start\r
+ previous_op.visited.set_started();\r
+ m_visitor.visit_traverse(m_turns, previous_turn, previous_op, "Start");\r
+ }\r
+\r
+ bool is_touching = false;\r
+ if (! m_trav.select_turn(start_turn_index, turn_index, op_index,\r
+ is_touching,\r
+ previous_op_index, previous_turn_index, previous_seg_id,\r
+ is_start))\r
+ {\r
+ return is_start\r
+ ? traverse_error_no_next_ip_at_start\r
+ : traverse_error_no_next_ip;\r
+ }\r
+\r
+ {\r
+ // Check operation (TODO: this might be redundant or should be catched before)\r
+ const turn_type& current_turn = m_turns[turn_index];\r
+ const turn_operation_type& op = current_turn.operations[op_index];\r
+ if (op.visited.finalized()\r
+ || m_trav.is_visited(current_turn, op, turn_index, op_index))\r
+ {\r
+ return traverse_error_visit_again;\r
+ }\r
+ }\r
+\r
+ // Update registration and append point\r
+ turn_type& current_turn = m_turns[turn_index];\r
+ turn_operation_type& op = current_turn.operations[op_index];\r
+ detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point,\r
+ m_robust_policy);\r
+\r
+ // Register the visit\r
+ m_trav.set_visited(current_turn, op);\r
+ m_visitor.visit_traverse(m_turns, current_turn, op, "Visit");\r
+\r
+ return traverse_error_none;\r
+ }\r
+\r
+ template <typename Ring>\r
+ inline traverse_error_type traverse(Ring& ring,\r
+ signed_size_type start_turn_index, int start_op_index)\r
+ {\r
+ turn_type const& start_turn = m_turns[start_turn_index];\r
+ turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index];\r
+\r
+ detail::overlay::append_no_dups_or_spikes(ring, start_turn.point,\r
+ m_robust_policy);\r
+\r
+ signed_size_type current_turn_index = start_turn_index;\r
+ int current_op_index = start_op_index;\r
+\r
+ traverse_error_type error = travel_to_next_turn(start_turn_index,\r
+ start_op_index,\r
+ current_turn_index, current_op_index,\r
+ ring, true);\r
+\r
+ if (error != traverse_error_none)\r
+ {\r
+ // This is not necessarily a problem, it happens for clustered turns\r
+ // which are "build in" or otherwise point inwards\r
+ return error;\r
+ }\r
+\r
+ if (current_turn_index == start_turn_index)\r
+ {\r
+ start_op.visited.set_finished();\r
+ m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish");\r
+ return traverse_error_none;\r
+ }\r
+\r
+ std::size_t const max_iterations = 2 + 2 * m_turns.size();\r
+ for (std::size_t i = 0; i <= max_iterations; i++)\r
+ {\r
+ // We assume clockwise polygons only, non self-intersecting, closed.\r
+ // However, the input might be different, and checking validity\r
+ // is up to the library user.\r
+\r
+ // Therefore we make here some sanity checks. If the input\r
+ // violates the assumptions, the output polygon will not be correct\r
+ // but the routine will stop and output the current polygon, and\r
+ // will continue with the next one.\r
+\r
+ // Below three reasons to stop.\r
+ error = travel_to_next_turn(start_turn_index, start_op_index,\r
+ current_turn_index, current_op_index,\r
+ ring, false);\r
+\r
+ if (error != traverse_error_none)\r
+ {\r
+ return error;\r
+ }\r
+\r
+ if (current_turn_index == start_turn_index\r
+ && current_op_index == start_op_index)\r
+ {\r
+ start_op.visited.set_finished();\r
+ m_visitor.visit_traverse(m_turns, start_turn, start_op, "Finish");\r
+ return traverse_error_none;\r
+ }\r
+ }\r
+\r
+ return traverse_error_endless_loop;\r
+ }\r
+\r
+ template <typename Rings>\r
+ void traverse_with_operation(turn_type const& start_turn,\r
+ std::size_t turn_index, int op_index,\r
+ Rings& rings, std::size_t& finalized_ring_size,\r
+ typename Backtrack::state_type& state)\r
+ {\r
+ typedef typename boost::range_value<Rings>::type ring_type;\r
+\r
+ turn_operation_type const& start_op = start_turn.operations[op_index];\r
+\r
+ if (! start_op.visited.none()\r
+ || ! start_op.enriched.startable\r
+ || start_op.visited.rejected()\r
+ || ! (start_op.operation == target_operation\r
+ || start_op.operation == detail::overlay::operation_continue))\r
+ {\r
+ return;\r
+ }\r
+\r
+ ring_type ring;\r
+ traverse_error_type traverse_error = traverse(ring, turn_index, op_index);\r
+\r
+ if (traverse_error == traverse_error_none)\r
+ {\r
+ std::size_t const min_num_points\r
+ = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<ring_type>::value\r
+ >::value;\r
+\r
+ if (geometry::num_points(ring) >= min_num_points)\r
+ {\r
+ clean_closing_dups_and_spikes(ring, m_robust_policy);\r
+ rings.push_back(ring);\r
+\r
+ m_trav.finalize_visit_info();\r
+ finalized_ring_size++;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Backtrack::apply(\r
+ finalized_ring_size,\r
+ rings, ring, m_turns, start_turn,\r
+ m_turns[turn_index].operations[op_index],\r
+ traverse_error,\r
+ m_geometry1, m_geometry2, m_robust_policy,\r
+ state, m_visitor);\r
+ }\r
+ }\r
+\r
+ template <typename Rings>\r
+ void iterate(Rings& rings, std::size_t& finalized_ring_size,\r
+ typename Backtrack::state_type& state,\r
+ int pass)\r
+ {\r
+ if (pass == 1)\r
+ {\r
+ if (target_operation == operation_intersection)\r
+ {\r
+ // Second pass currently only used for uu\r
+ return;\r
+ }\r
+ if (! m_has_uu)\r
+ {\r
+ // There is no uu found in first pass\r
+ return;\r
+ }\r
+ }\r
+\r
+ // Iterate through all unvisited points\r
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)\r
+ {\r
+ turn_type const& start_turn = m_turns[turn_index];\r
+\r
+ if (start_turn.discarded || start_turn.blocked())\r
+ {\r
+ // Skip discarded and blocked turns\r
+ continue;\r
+ }\r
+ if (target_operation == operation_union)\r
+ {\r
+ if (start_turn.both(operation_union))\r
+ {\r
+ // Start with a uu-turn only in the second pass\r
+ m_has_uu = true;\r
+ if (pass == 0)\r
+ {\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+\r
+ for (int op_index = 0; op_index < 2; op_index++)\r
+ {\r
+ traverse_with_operation(start_turn, turn_index, op_index,\r
+ rings, finalized_ring_size, state);\r
+ }\r
+ }\r
+ }\r
+\r
+private:\r
+ traversal_type m_trav;\r
+\r
+ Geometry1 const& m_geometry1;\r
+ Geometry2 const& m_geometry2;\r
+ Turns& m_turns;\r
+ Clusters const& m_clusters;\r
+ RobustPolicy const& m_robust_policy;\r
+ Visitor& m_visitor;\r
+\r
+ // Next member is only used for operation union\r
+ bool m_has_uu;\r
+\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015-2016 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+// Generic function (is this used somewhere else too?)\r
+inline ring_identifier ring_id_by_seg_id(segment_identifier const& seg_id)\r
+{\r
+ return ring_identifier(seg_id.source_index, seg_id.multi_index, seg_id.ring_index);\r
+}\r
+\r
+template\r
+<\r
+ bool Reverse1,\r
+ bool Reverse2,\r
+ overlay_type OverlayType,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Turns,\r
+ typename Clusters,\r
+ typename RobustPolicy,\r
+ typename Visitor\r
+>\r
+struct traversal_switch_detector\r
+{\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ typedef typename turn_type::turn_operation_type turn_operation_type;\r
+\r
+ // For convenience\r
+ typedef std::set<signed_size_type>::const_iterator set_iterator;\r
+\r
+ inline traversal_switch_detector(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ Turns& turns, Clusters& clusters,\r
+ RobustPolicy const& robust_policy, Visitor& visitor)\r
+ : m_geometry1(geometry1)\r
+ , m_geometry2(geometry2)\r
+ , m_turns(turns)\r
+ , m_clusters(clusters)\r
+ , m_robust_policy(robust_policy)\r
+ , m_visitor(visitor)\r
+ , m_region_id(0)\r
+ {\r
+\r
+ }\r
+\r
+ static inline bool connects_same_zone(turn_type const& turn)\r
+ {\r
+ if (turn.cluster_id == -1)\r
+ {\r
+ // If it is a uu-turn (non clustered), it is never same zone\r
+ return ! turn.both(operation_union);\r
+ }\r
+\r
+ // It is a cluster, check zones of both operations\r
+ return turn.operations[0].enriched.zone\r
+ == turn.operations[1].enriched.zone;\r
+ }\r
+\r
+ inline int get_region_id(turn_operation_type const& op) const\r
+ {\r
+ std::map<ring_identifier, int>::const_iterator it\r
+ = m_regions.find(ring_id_by_seg_id(op.seg_id));\r
+ return it == m_regions.end() ? -1 : it->second;\r
+ }\r
+\r
+ void create_region(ring_identifier const& ring_id, std::set<signed_size_type> const& ring_turn_indices, int region_id = -1)\r
+ {\r
+ std::map<ring_identifier, int>::const_iterator it = m_regions.find(ring_id);\r
+ if (it != m_regions.end())\r
+ {\r
+ // The ring is already gathered in a region, quit\r
+ return;\r
+ }\r
+ if (region_id == -1)\r
+ {\r
+ region_id = m_region_id++;\r
+ }\r
+\r
+ // Assign this ring to specified region\r
+ m_regions[ring_id] = region_id;\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)\r
+ std::cout << " ADD " << ring_id << " TO REGION " << region_id << std::endl;\r
+#endif\r
+\r
+ // Find connecting rings, recursively\r
+ for (set_iterator sit = ring_turn_indices.begin();\r
+ sit != ring_turn_indices.end(); ++sit)\r
+ {\r
+ int const turn_index = *sit;\r
+ turn_type const& turn = m_turns[turn_index];\r
+ if (! connects_same_zone(turn))\r
+ {\r
+ // This is a non clustered uu-turn, or a cluster connecting different 'zones'\r
+ continue;\r
+ }\r
+\r
+ // This turn connects two rings (interior connected), create the\r
+ // same region\r
+ for (int op_index = 0; op_index < 2; op_index++)\r
+ {\r
+ turn_operation_type const& op = turn.operations[op_index];\r
+ ring_identifier connected_ring_id = ring_id_by_seg_id(op.seg_id);\r
+ if (connected_ring_id != ring_id)\r
+ {\r
+ propagate_region(connected_ring_id, region_id);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ void propagate_region(ring_identifier const& ring_id, int region_id)\r
+ {\r
+ std::map<ring_identifier, std::set<signed_size_type> >::const_iterator it = m_turns_per_ring.find(ring_id);\r
+ if (it != m_turns_per_ring.end())\r
+ {\r
+ create_region(ring_id, it->second, region_id);\r
+ }\r
+ }\r
+\r
+ void iterate()\r
+ {\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)\r
+ std::cout << "SWITCH BEGIN ITERATION" << std::endl;\r
+#endif\r
+\r
+ // Collect turns per ring\r
+ m_turns_per_ring.clear();\r
+ m_regions.clear();\r
+ m_region_id = 1;\r
+\r
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)\r
+ {\r
+ turn_type const& turn = m_turns[turn_index];\r
+\r
+ for (int op_index = 0; op_index < 2; op_index++)\r
+ {\r
+ turn_operation_type const& op = turn.operations[op_index];\r
+ m_turns_per_ring[ring_id_by_seg_id(op.seg_id)].insert(turn_index);\r
+ }\r
+ }\r
+\r
+ // All rings having turns are in the map. Now iterate them\r
+ for (std::map<ring_identifier, std::set<signed_size_type> >::const_iterator it\r
+ = m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it)\r
+ {\r
+ create_region(it->first, it->second);\r
+ }\r
+\r
+ // Now that all regions are filled, assign switch_source property\r
+ // Iterate through all clusters\r
+ for (typename Clusters::iterator it = m_clusters.begin(); it != m_clusters.end(); ++it)\r
+ {\r
+ cluster_info& cinfo = it->second;\r
+ if (cinfo.open_count <= 1)\r
+ {\r
+ // Not a touching cluster\r
+ continue;\r
+ }\r
+\r
+ // A touching cluster, gather regions\r
+ std::set<int> regions;\r
+\r
+ std::set<signed_size_type> const& ids = cinfo.turn_indices;\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)\r
+ std::cout << "SWITCH EXAMINE CLUSTER " << it->first << std::endl;\r
+#endif\r
+\r
+ for (set_iterator sit = ids.begin(); sit != ids.end(); ++sit)\r
+ {\r
+ signed_size_type turn_index = *sit;\r
+ turn_type const& turn = m_turns[turn_index];\r
+ for (int oi = 0; oi < 2; oi++)\r
+ {\r
+ int const region = get_region_id(turn.operations[oi]);\r
+ regions.insert(region);\r
+ }\r
+ }\r
+ // Switch source if this cluster connects the same region\r
+ cinfo.switch_source = regions.size() == 1;\r
+ }\r
+\r
+ // Iterate through all uu turns (non-clustered)\r
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)\r
+ {\r
+ turn_type& turn = m_turns[turn_index];\r
+\r
+ if (turn.discarded\r
+ || turn.blocked()\r
+ || turn.cluster_id >= 0\r
+ || ! turn.both(operation_union))\r
+ {\r
+ // Skip discarded, blocked, non-uu and clustered turns\r
+ continue;\r
+ }\r
+\r
+ if (OverlayType == overlay_buffer)\r
+ {\r
+ // For deflate, the region approach does not work because many\r
+ // pieces are outside the real polygons\r
+ // TODO: implement this in another way for buffer\r
+ // (because now buffer might output invalid geometries)\r
+ continue;\r
+ }\r
+\r
+ int const region0 = get_region_id(turn.operations[0]);\r
+ int const region1 = get_region_id(turn.operations[1]);\r
+\r
+ // Switch sources for same region\r
+ turn.switch_source = region0 == region1;\r
+ }\r
+\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)\r
+ std::cout << "SWITCH END ITERATION" << std::endl;\r
+\r
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)\r
+ {\r
+ turn_type const& turn = m_turns[turn_index];\r
+\r
+ if (turn.both(operation_union) && turn.cluster_id < 0)\r
+ {\r
+ std::cout << "UU SWITCH RESULT "\r
+ << turn_index << " -> "\r
+ << turn.switch_source << std::endl;\r
+ }\r
+ }\r
+\r
+ for (typename Clusters::const_iterator it = m_clusters.begin(); it != m_clusters.end(); ++it)\r
+ {\r
+ cluster_info const& cinfo = it->second;\r
+ if (cinfo.open_count > 1)\r
+ {\r
+ std::cout << "CL SWITCH RESULT " << it->first\r
+ << " -> " << cinfo.switch_source << std::endl;\r
+ }\r
+ else\r
+ {\r
+ std::cout << "CL SWITCH RESULT " << it->first\r
+ << " is not registered as open" << std::endl;\r
+ }\r
+ }\r
+#endif\r
+\r
+ }\r
+\r
+private:\r
+\r
+ Geometry1 const& m_geometry1;\r
+ Geometry2 const& m_geometry2;\r
+ Turns& m_turns;\r
+ Clusters& m_clusters;\r
+ RobustPolicy const& m_robust_policy;\r
+ Visitor& m_visitor;\r
+\r
+ std::map<ring_identifier, int> m_regions;\r
+ std::map<ring_identifier, std::set<signed_size_type> > m_turns_per_ring;\r
+ int m_region_id;\r
+\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+/*!\r
+ \brief Traverses through intersection points / geometries\r
+ \ingroup overlay\r
+ */\r
+template\r
+<\r
+ bool Reverse1, bool Reverse2,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ overlay_type OverlayType,\r
+ typename Backtrack = backtrack_check_self_intersections<Geometry1, Geometry2>\r
+>\r
+class traverse\r
+{\r
+\r
+ template <typename Turns>\r
+ static void reset_visits(Turns& turns)\r
+ {\r
+ for (typename boost::range_iterator<Turns>::type\r
+ it = boost::begin(turns);\r
+ it != boost::end(turns);\r
+ ++it)\r
+ {\r
+ for (int i = 0; i < 2; i++)\r
+ {\r
+ it->operations[i].visited.reset();\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+public :\r
+ template\r
+ <\r
+ typename RobustPolicy,\r
+ typename Turns,\r
+ typename Rings,\r
+ typename Visitor,\r
+ typename Clusters\r
+ >\r
+ static inline void apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ Turns& turns, Rings& rings,\r
+ Clusters& clusters,\r
+ Visitor& visitor)\r
+ {\r
+ traversal_switch_detector\r
+ <\r
+ Reverse1, Reverse2, OverlayType,\r
+ Geometry1, Geometry2,\r
+ Turns, Clusters,\r
+ RobustPolicy, Visitor\r
+ > switch_detector(geometry1, geometry2, turns, clusters,\r
+ robust_policy, visitor);\r
+\r
+ switch_detector.iterate();\r
+ reset_visits(turns);\r
+\r
+ traversal_ring_creator\r
+ <\r
+ Reverse1, Reverse2, OverlayType,\r
+ Geometry1, Geometry2,\r
+ Turns, Clusters,\r
+ RobustPolicy, Visitor,\r
+ Backtrack\r
+ > trav(geometry1, geometry2, turns, clusters,\r
+ robust_policy, visitor);\r
+\r
+ std::size_t finalized_ring_size = boost::size(rings);\r
+\r
+ typename Backtrack::state_type state;\r
+\r
+ for (int pass = 0; pass < 2; pass++)\r
+ {\r
+ trav.iterate(rings, finalized_ring_size, state, pass);\r
+ }\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP\r
+\r
+\r
+#include <boost/array.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+enum method_type\r
+{\r
+ method_none,\r
+ method_disjoint,\r
+ method_crosses,\r
+ method_touch,\r
+ method_touch_interior,\r
+ method_collinear,\r
+ method_equal,\r
+ method_error\r
+};\r
+\r
+\r
+/*!\r
+ \brief Turn operation: operation\r
+ \details Information necessary for traversal phase (a phase\r
+ of the overlay process). The information is gathered during the\r
+ get_turns (segment intersection) phase.\r
+ The class is to be included in the turn_info class, either direct\r
+ or a derived or similar class with more (e.g. enrichment) information.\r
+ */\r
+template <typename Point, typename SegmentRatio>\r
+struct turn_operation\r
+{\r
+ typedef SegmentRatio segment_ratio_type;\r
+\r
+ operation_type operation;\r
+ segment_identifier seg_id;\r
+ SegmentRatio fraction;\r
+\r
+ typedef typename coordinate_type<Point>::type comparable_distance_type;\r
+ comparable_distance_type remaining_distance;\r
+\r
+ inline turn_operation()\r
+ : operation(operation_none)\r
+ , remaining_distance(0)\r
+ {}\r
+};\r
+\r
+\r
+/*!\r
+ \brief Turn information: intersection point, method, and turn information\r
+ \details Information necessary for traversal phase (a phase\r
+ of the overlay process). The information is gathered during the\r
+ get_turns (segment intersection) phase.\r
+ \tparam Point point type of intersection point\r
+ \tparam Operation gives classes opportunity to add additional info\r
+ \tparam Container gives classes opportunity to define how operations are stored\r
+ */\r
+template\r
+<\r
+ typename Point,\r
+ typename SegmentRatio,\r
+ typename Operation = turn_operation<Point, SegmentRatio>,\r
+ typename Container = boost::array<Operation, 2>\r
+>\r
+struct turn_info\r
+{\r
+ typedef Point point_type;\r
+ typedef SegmentRatio segment_ratio_type;\r
+ typedef Operation turn_operation_type;\r
+ typedef Container container_type;\r
+\r
+ Point point;\r
+ method_type method;\r
+ int cluster_id;\r
+ bool discarded;\r
+ bool colocated;\r
+ bool switch_source; // For u/u turns which can either switch or not\r
+\r
+ Container operations;\r
+\r
+ inline turn_info()\r
+ : method(method_none)\r
+ , cluster_id(-1)\r
+ , discarded(false)\r
+ , colocated(false)\r
+ , switch_source(false)\r
+ {}\r
+\r
+ inline bool both(operation_type type) const\r
+ {\r
+ return has12(type, type);\r
+ }\r
+\r
+ inline bool has(operation_type type) const\r
+ {\r
+ return this->operations[0].operation == type\r
+ || this->operations[1].operation == type;\r
+ }\r
+\r
+ inline bool combination(operation_type type1, operation_type type2) const\r
+ {\r
+ return has12(type1, type2) || has12(type2, type1);\r
+ }\r
+\r
+ inline bool blocked() const\r
+ {\r
+ return both(operation_blocked);\r
+ }\r
+ inline bool opposite() const\r
+ {\r
+ return both(operation_opposite);\r
+ }\r
+ inline bool any_blocked() const\r
+ {\r
+ return has(operation_blocked);\r
+ }\r
+\r
+\r
+private :\r
+ inline bool has12(operation_type type1, operation_type type2) const\r
+ {\r
+ return this->operations[0].operation == type1\r
+ && this->operations[1].operation == type2\r
+ ;\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+class visit_info\r
+{\r
+private :\r
+ static const int NONE = 0;\r
+ static const int STARTED = 1;\r
+ static const int VISITED = 2;\r
+ static const int FINISHED = 3;\r
+ static const int REJECTED = 4;\r
+\r
+ int m_visit_code;\r
+ bool m_rejected;\r
+ bool m_final;\r
+\r
+public:\r
+ inline visit_info()\r
+ : m_visit_code(0)\r
+ , m_rejected(false)\r
+ , m_final(false)\r
+ {}\r
+\r
+ inline void set_visited() { m_visit_code = VISITED; }\r
+ inline void set_started() { m_visit_code = STARTED; }\r
+ inline void set_finished() { m_visit_code = FINISHED; }\r
+ inline void set_rejected()\r
+ {\r
+ m_visit_code = REJECTED;\r
+ m_rejected = true;\r
+ }\r
+\r
+ inline bool none() const { return m_visit_code == NONE; }\r
+ inline bool visited() const { return m_visit_code == VISITED; }\r
+ inline bool started() const { return m_visit_code == STARTED; }\r
+ inline bool finished() const { return m_visit_code == FINISHED; }\r
+ inline bool rejected() const { return m_rejected; }\r
+ inline bool finalized() const { return m_final; }\r
+\r
+ inline void clear()\r
+ {\r
+ if (! m_rejected && ! m_final)\r
+ {\r
+ m_visit_code = NONE;\r
+ }\r
+ }\r
+\r
+ inline void reset()\r
+ {\r
+ *this = visit_info();\r
+ }\r
+\r
+ inline void finalize()\r
+ {\r
+ if (visited() || started() || finished() )\r
+ {\r
+ m_final = true;\r
+ }\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION\r
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)\r
+ {\r
+ if (v.m_visit_code != 0)\r
+ {\r
+ os << " VIS: " << int(v.m_visit_code);\r
+ }\r
+ return os;\r
+ }\r
+#endif\r
+\r
+};\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif //DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP\r
+\r
+#include <cstddef>\r
+#include <vector>\r
+#include <boost/range.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace partition\r
+{\r
+\r
+template <int Dimension, typename Box>\r
+inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)\r
+{\r
+ typedef typename coordinate_type<Box>::type ctype;\r
+\r
+ // Divide input box into two parts, e.g. left/right\r
+ ctype two = 2;\r
+ ctype mid = (geometry::get<min_corner, Dimension>(box)\r
+ + geometry::get<max_corner, Dimension>(box)) / two;\r
+\r
+ lower_box = box;\r
+ upper_box = box;\r
+ geometry::set<max_corner, Dimension>(lower_box, mid);\r
+ geometry::set<min_corner, Dimension>(upper_box, mid);\r
+}\r
+\r
+// Divide forward_range into three subsets: lower, upper and oversized\r
+// (not-fitting)\r
+// (lower == left or bottom, upper == right or top)\r
+template <typename OverlapsPolicy, typename Box, typename IteratorVector>\r
+inline void divide_into_subsets(Box const& lower_box,\r
+ Box const& upper_box,\r
+ IteratorVector const& input,\r
+ IteratorVector& lower,\r
+ IteratorVector& upper,\r
+ IteratorVector& exceeding)\r
+{\r
+ typedef typename boost::range_iterator\r
+ <\r
+ IteratorVector const\r
+ >::type it_type;\r
+\r
+ for(it_type it = boost::begin(input); it != boost::end(input); ++it)\r
+ {\r
+ bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it);\r
+ bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it);\r
+\r
+ if (lower_overlapping && upper_overlapping)\r
+ {\r
+ exceeding.push_back(*it);\r
+ }\r
+ else if (lower_overlapping)\r
+ {\r
+ lower.push_back(*it);\r
+ }\r
+ else if (upper_overlapping)\r
+ {\r
+ upper.push_back(*it);\r
+ }\r
+ else\r
+ {\r
+ // Is nowhere. That is (since 1.58) possible, it might be\r
+ // skipped by the OverlapsPolicy to enhance performance\r
+ }\r
+ }\r
+}\r
+\r
+template\r
+<\r
+ typename ExpandPolicy,\r
+ typename Box,\r
+ typename IteratorVector\r
+>\r
+inline void expand_with_elements(Box& total, IteratorVector const& input)\r
+{\r
+ typedef typename boost::range_iterator<IteratorVector const>::type it_type;\r
+ for(it_type it = boost::begin(input); it != boost::end(input); ++it)\r
+ {\r
+ ExpandPolicy::apply(total, **it);\r
+ }\r
+}\r
+\r
+\r
+// Match forward_range with itself\r
+template <typename Policy, typename IteratorVector>\r
+inline void handle_one(IteratorVector const& input, Policy& policy)\r
+{\r
+ if (boost::size(input) == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ typedef typename boost::range_iterator<IteratorVector const>::type it_type;\r
+\r
+ // Quadratic behaviour at lowest level (lowest quad, or all exceeding)\r
+ for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1)\r
+ {\r
+ it_type it2 = it1;\r
+ for (++it2; it2 != boost::end(input); ++it2)\r
+ {\r
+ policy.apply(**it1, **it2);\r
+ }\r
+ }\r
+}\r
+\r
+// Match forward range 1 with forward range 2\r
+template\r
+<\r
+ typename Policy,\r
+ typename IteratorVector1,\r
+ typename IteratorVector2\r
+>\r
+inline void handle_two(IteratorVector1 const& input1,\r
+ IteratorVector2 const& input2,\r
+ Policy& policy)\r
+{\r
+ typedef typename boost::range_iterator\r
+ <\r
+ IteratorVector1 const\r
+ >::type iterator_type1;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ IteratorVector2 const\r
+ >::type iterator_type2;\r
+\r
+ if (boost::size(input1) == 0 || boost::size(input2) == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ for(iterator_type1 it1 = boost::begin(input1);\r
+ it1 != boost::end(input1);\r
+ ++it1)\r
+ {\r
+ for(iterator_type2 it2 = boost::begin(input2);\r
+ it2 != boost::end(input2);\r
+ ++it2)\r
+ {\r
+ policy.apply(**it1, **it2);\r
+ }\r
+ }\r
+}\r
+\r
+template <typename IteratorVector>\r
+inline bool recurse_ok(IteratorVector const& input,\r
+ std::size_t min_elements, std::size_t level)\r
+{\r
+ return boost::size(input) >= min_elements\r
+ && level < 100;\r
+}\r
+\r
+template <typename IteratorVector1, typename IteratorVector2>\r
+inline bool recurse_ok(IteratorVector1 const& input1,\r
+ IteratorVector2 const& input2,\r
+ std::size_t min_elements, std::size_t level)\r
+{\r
+ return boost::size(input1) >= min_elements\r
+ && recurse_ok(input2, min_elements, level);\r
+}\r
+\r
+template\r
+<\r
+ typename IteratorVector1,\r
+ typename IteratorVector2,\r
+ typename IteratorVector3\r
+>\r
+inline bool recurse_ok(IteratorVector1 const& input1,\r
+ IteratorVector2 const& input2,\r
+ IteratorVector3 const& input3,\r
+ std::size_t min_elements, std::size_t level)\r
+{\r
+ return boost::size(input1) >= min_elements\r
+ && recurse_ok(input2, input3, min_elements, level);\r
+}\r
+\r
+template\r
+<\r
+ int Dimension,\r
+ typename Box,\r
+ typename OverlapsPolicy1,\r
+ typename OverlapsPolicy2,\r
+ typename ExpandPolicy1,\r
+ typename ExpandPolicy2,\r
+ typename VisitBoxPolicy\r
+>\r
+class partition_two_ranges;\r
+\r
+\r
+template\r
+<\r
+ int Dimension,\r
+ typename Box,\r
+ typename OverlapsPolicy,\r
+ typename ExpandPolicy,\r
+ typename VisitBoxPolicy\r
+>\r
+class partition_one_range\r
+{\r
+ template <typename IteratorVector>\r
+ static inline Box get_new_box(IteratorVector const& input)\r
+ {\r
+ Box box;\r
+ geometry::assign_inverse(box);\r
+ expand_with_elements<ExpandPolicy>(box, input);\r
+ return box;\r
+ }\r
+\r
+ template <typename Policy, typename IteratorVector>\r
+ static inline void next_level(Box const& box,\r
+ IteratorVector const& input,\r
+ std::size_t level, std::size_t min_elements,\r
+ Policy& policy, VisitBoxPolicy& box_policy)\r
+ {\r
+ if (recurse_ok(input, min_elements, level))\r
+ {\r
+ partition_one_range\r
+ <\r
+ 1 - Dimension,\r
+ Box,\r
+ OverlapsPolicy,\r
+ ExpandPolicy,\r
+ VisitBoxPolicy\r
+ >::apply(box, input, level + 1, min_elements, policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_one(input, policy);\r
+ }\r
+ }\r
+\r
+ // Function to switch to two forward ranges if there are\r
+ // geometries exceeding the separation line\r
+ template <typename Policy, typename IteratorVector>\r
+ static inline void next_level2(Box const& box,\r
+ IteratorVector const& input1,\r
+ IteratorVector const& input2,\r
+ std::size_t level, std::size_t min_elements,\r
+ Policy& policy, VisitBoxPolicy& box_policy)\r
+ {\r
+ if (recurse_ok(input1, input2, min_elements, level))\r
+ {\r
+ partition_two_ranges\r
+ <\r
+ 1 - Dimension,\r
+ Box,\r
+ OverlapsPolicy, OverlapsPolicy,\r
+ ExpandPolicy, ExpandPolicy,\r
+ VisitBoxPolicy\r
+ >::apply(box, input1, input2, level + 1, min_elements,\r
+ policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_two(input1, input2, policy);\r
+ }\r
+ }\r
+\r
+public :\r
+ template <typename Policy, typename IteratorVector>\r
+ static inline void apply(Box const& box,\r
+ IteratorVector const& input,\r
+ std::size_t level,\r
+ std::size_t min_elements,\r
+ Policy& policy, VisitBoxPolicy& box_policy)\r
+ {\r
+ box_policy.apply(box, level);\r
+\r
+ Box lower_box, upper_box;\r
+ divide_box<Dimension>(box, lower_box, upper_box);\r
+\r
+ IteratorVector lower, upper, exceeding;\r
+ divide_into_subsets<OverlapsPolicy>(lower_box, upper_box,\r
+ input, lower, upper, exceeding);\r
+\r
+ if (boost::size(exceeding) > 0)\r
+ {\r
+ // Get the box of exceeding-only\r
+ Box exceeding_box = get_new_box(exceeding);\r
+\r
+ // Recursively do exceeding elements only, in next dimension they\r
+ // will probably be less exceeding within the new box\r
+ next_level(exceeding_box, exceeding, level, min_elements,\r
+ policy, box_policy);\r
+\r
+ // Switch to two forward ranges, combine exceeding with\r
+ // lower resp upper, but not lower/lower, upper/upper\r
+ next_level2(exceeding_box, exceeding, lower, level, min_elements,\r
+ policy, box_policy);\r
+ next_level2(exceeding_box, exceeding, upper, level, min_elements,\r
+ policy, box_policy);\r
+ }\r
+\r
+ // Recursively call operation both parts\r
+ next_level(lower_box, lower, level, min_elements, policy, box_policy);\r
+ next_level(upper_box, upper, level, min_elements, policy, box_policy);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ int Dimension,\r
+ typename Box,\r
+ typename OverlapsPolicy1,\r
+ typename OverlapsPolicy2,\r
+ typename ExpandPolicy1,\r
+ typename ExpandPolicy2,\r
+ typename VisitBoxPolicy\r
+>\r
+class partition_two_ranges\r
+{\r
+ template\r
+ <\r
+ typename Policy,\r
+ typename IteratorVector1,\r
+ typename IteratorVector2\r
+ >\r
+ static inline void next_level(Box const& box,\r
+ IteratorVector1 const& input1,\r
+ IteratorVector2 const& input2,\r
+ std::size_t level, std::size_t min_elements,\r
+ Policy& policy, VisitBoxPolicy& box_policy)\r
+ {\r
+ partition_two_ranges\r
+ <\r
+ 1 - Dimension,\r
+ Box,\r
+ OverlapsPolicy1,\r
+ OverlapsPolicy2,\r
+ ExpandPolicy1,\r
+ ExpandPolicy2,\r
+ VisitBoxPolicy\r
+ >::apply(box, input1, input2, level + 1, min_elements,\r
+ policy, box_policy);\r
+ }\r
+\r
+ template <typename ExpandPolicy, typename IteratorVector>\r
+ static inline Box get_new_box(IteratorVector const& input)\r
+ {\r
+ Box box;\r
+ geometry::assign_inverse(box);\r
+ expand_with_elements<ExpandPolicy>(box, input);\r
+ return box;\r
+ }\r
+\r
+ template <typename IteratorVector1, typename IteratorVector2>\r
+ static inline Box get_new_box(IteratorVector1 const& input1,\r
+ IteratorVector2 const& input2)\r
+ {\r
+ Box box = get_new_box<ExpandPolicy1>(input1);\r
+ expand_with_elements<ExpandPolicy2>(box, input2);\r
+ return box;\r
+ }\r
+\r
+public :\r
+ template\r
+ <\r
+ typename Policy,\r
+ typename IteratorVector1,\r
+ typename IteratorVector2\r
+ >\r
+ static inline void apply(Box const& box,\r
+ IteratorVector1 const& input1,\r
+ IteratorVector2 const& input2,\r
+ std::size_t level,\r
+ std::size_t min_elements,\r
+ Policy& policy, VisitBoxPolicy& box_policy)\r
+ {\r
+ box_policy.apply(box, level);\r
+\r
+ Box lower_box, upper_box;\r
+ divide_box<Dimension>(box, lower_box, upper_box);\r
+\r
+ IteratorVector1 lower1, upper1, exceeding1;\r
+ IteratorVector2 lower2, upper2, exceeding2;\r
+ divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box,\r
+ input1, lower1, upper1, exceeding1);\r
+ divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box,\r
+ input2, lower2, upper2, exceeding2);\r
+\r
+ if (boost::size(exceeding1) > 0)\r
+ {\r
+ // All exceeding from 1 with 2:\r
+\r
+ if (recurse_ok(exceeding1, exceeding2, min_elements, level))\r
+ {\r
+ Box exceeding_box = get_new_box(exceeding1, exceeding2);\r
+ next_level(exceeding_box, exceeding1, exceeding2, level,\r
+ min_elements, policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_two(exceeding1, exceeding2, policy);\r
+ }\r
+\r
+ // All exceeding from 1 with lower and upper of 2:\r
+\r
+ // (Check sizes of all three forward ranges to avoid recurse into\r
+ // the same combinations again and again)\r
+ if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))\r
+ {\r
+ Box exceeding_box = get_new_box<ExpandPolicy1>(exceeding1);\r
+ next_level(exceeding_box, exceeding1, lower2, level,\r
+ min_elements, policy, box_policy);\r
+ next_level(exceeding_box, exceeding1, upper2, level,\r
+ min_elements, policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_two(exceeding1, lower2, policy);\r
+ handle_two(exceeding1, upper2, policy);\r
+ }\r
+ }\r
+\r
+ if (boost::size(exceeding2) > 0)\r
+ {\r
+ // All exceeding from 2 with lower and upper of 1:\r
+ if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))\r
+ {\r
+ Box exceeding_box = get_new_box<ExpandPolicy2>(exceeding2);\r
+ next_level(exceeding_box, lower1, exceeding2, level,\r
+ min_elements, policy, box_policy);\r
+ next_level(exceeding_box, upper1, exceeding2, level,\r
+ min_elements, policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_two(lower1, exceeding2, policy);\r
+ handle_two(upper1, exceeding2, policy);\r
+ }\r
+ }\r
+\r
+ if (recurse_ok(lower1, lower2, min_elements, level))\r
+ {\r
+ next_level(lower_box, lower1, lower2, level,\r
+ min_elements, policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_two(lower1, lower2, policy);\r
+ }\r
+ if (recurse_ok(upper1, upper2, min_elements, level))\r
+ {\r
+ next_level(upper_box, upper1, upper2, level,\r
+ min_elements, policy, box_policy);\r
+ }\r
+ else\r
+ {\r
+ handle_two(upper1, upper2, policy);\r
+ }\r
+ }\r
+};\r
+\r
+struct visit_no_policy\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Box const&, std::size_t )\r
+ {}\r
+};\r
+\r
+struct include_all_policy\r
+{\r
+ template <typename Item>\r
+ static inline bool apply(Item const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::partition\r
+\r
+template\r
+<\r
+ typename Box,\r
+ typename ExpandPolicy1,\r
+ typename OverlapsPolicy1,\r
+ typename ExpandPolicy2 = ExpandPolicy1,\r
+ typename OverlapsPolicy2 = OverlapsPolicy1,\r
+ typename IncludePolicy1 = detail::partition::include_all_policy,\r
+ typename IncludePolicy2 = detail::partition::include_all_policy,\r
+ typename VisitBoxPolicy = detail::partition::visit_no_policy\r
+>\r
+class partition\r
+{\r
+ template\r
+ <\r
+ typename ExpandPolicy,\r
+ typename IncludePolicy,\r
+ typename ForwardRange,\r
+ typename IteratorVector\r
+ >\r
+ static inline void expand_to_range(ForwardRange const& forward_range,\r
+ Box& total, IteratorVector& iterator_vector)\r
+ {\r
+ for(typename boost::range_iterator<ForwardRange const>::type it\r
+ = boost::begin(forward_range);\r
+ it != boost::end(forward_range);\r
+ ++it)\r
+ {\r
+ if (IncludePolicy::apply(*it))\r
+ {\r
+ ExpandPolicy::apply(total, *it);\r
+ iterator_vector.push_back(it);\r
+ }\r
+ }\r
+ }\r
+\r
+public :\r
+ template <typename ForwardRange, typename VisitPolicy>\r
+ static inline void apply(ForwardRange const& forward_range,\r
+ VisitPolicy& visitor,\r
+ std::size_t min_elements = 16,\r
+ VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()\r
+ )\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ ForwardRange const\r
+ >::type iterator_type;\r
+\r
+ if (std::size_t(boost::size(forward_range)) > min_elements)\r
+ {\r
+ std::vector<iterator_type> iterator_vector;\r
+ Box total;\r
+ assign_inverse(total);\r
+ expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range,\r
+ total, iterator_vector);\r
+\r
+ detail::partition::partition_one_range\r
+ <\r
+ 0, Box,\r
+ OverlapsPolicy1,\r
+ ExpandPolicy1,\r
+ VisitBoxPolicy\r
+ >::apply(total, iterator_vector, 0, min_elements,\r
+ visitor, box_visitor);\r
+ }\r
+ else\r
+ {\r
+ for(iterator_type it1 = boost::begin(forward_range);\r
+ it1 != boost::end(forward_range);\r
+ ++it1)\r
+ {\r
+ iterator_type it2 = it1;\r
+ for(++it2; it2 != boost::end(forward_range); ++it2)\r
+ {\r
+ visitor.apply(*it1, *it2);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ typename ForwardRange1,\r
+ typename ForwardRange2,\r
+ typename VisitPolicy\r
+ >\r
+ static inline void apply(ForwardRange1 const& forward_range1,\r
+ ForwardRange2 const& forward_range2,\r
+ VisitPolicy& visitor,\r
+ std::size_t min_elements = 16,\r
+ VisitBoxPolicy box_visitor\r
+ = detail::partition::visit_no_policy()\r
+ )\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ ForwardRange1 const\r
+ >::type iterator_type1;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ ForwardRange2 const\r
+ >::type iterator_type2;\r
+\r
+ if (std::size_t(boost::size(forward_range1)) > min_elements\r
+ && std::size_t(boost::size(forward_range2)) > min_elements)\r
+ {\r
+ std::vector<iterator_type1> iterator_vector1;\r
+ std::vector<iterator_type2> iterator_vector2;\r
+ Box total;\r
+ assign_inverse(total);\r
+ expand_to_range<ExpandPolicy1, IncludePolicy1>(forward_range1,\r
+ total, iterator_vector1);\r
+ expand_to_range<ExpandPolicy2, IncludePolicy2>(forward_range2,\r
+ total, iterator_vector2);\r
+\r
+ detail::partition::partition_two_ranges\r
+ <\r
+ 0, Box, OverlapsPolicy1, OverlapsPolicy2,\r
+ ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy\r
+ >::apply(total, iterator_vector1, iterator_vector2,\r
+ 0, min_elements, visitor, box_visitor);\r
+ }\r
+ else\r
+ {\r
+ for(iterator_type1 it1 = boost::begin(forward_range1);\r
+ it1 != boost::end(forward_range1);\r
+ ++it1)\r
+ {\r
+ for(iterator_type2 it2 = boost::begin(forward_range2);\r
+ it2 != boost::end(forward_range2);\r
+ ++it2)\r
+ {\r
+ visitor.apply(*it1, *it2);\r
+ }\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/direction_code.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+// Checks if a point ("last_point") causes a spike w.r.t.\r
+// the specified two other points (segment_a, segment_b)\r
+//\r
+// x-------x------x\r
+// a lp b\r
+//\r
+// Above, lp generates a spike w.r.t. segment(a,b)\r
+// So specify last point first, then (a,b)\r
+// The segment's orientation does matter: if lp is to the right of b\r
+// no spike is reported\r
+template <typename Point1, typename Point2, typename Point3>\r
+static inline bool point_is_spike_or_equal(Point1 const& last_point,\r
+ Point2 const& segment_a,\r
+ Point3 const& segment_b)\r
+{\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point1>::type\r
+ >::type side_strategy;\r
+\r
+ int const side = side_strategy::apply(last_point, segment_a, segment_b);\r
+ if (side == 0)\r
+ {\r
+ // Last point is collinear w.r.t previous segment.\r
+ // Check if it is equal\r
+ int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);\r
+ int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);\r
+ if (sgn_x1 == 0 && sgn_y1 == 0)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ // Check if it moves forward\r
+ int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);\r
+ int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);\r
+\r
+ return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;\r
+ }\r
+ return false;\r
+}\r
+\r
+template\r
+<\r
+ typename Point1,\r
+ typename Point2,\r
+ typename Point3,\r
+ typename RobustPolicy\r
+>\r
+static inline bool point_is_spike_or_equal(Point1 const& last_point,\r
+ Point2 const& segment_a,\r
+ Point3 const& segment_b,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+ if (point_is_spike_or_equal(last_point, segment_a, segment_b))\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Try using specified robust policy\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ Point1,\r
+ RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ robust_point_type last_point_rob, segment_a_rob, segment_b_rob;\r
+ geometry::recalculate(last_point_rob, last_point, robust_policy);\r
+ geometry::recalculate(segment_a_rob, segment_a, robust_policy);\r
+ geometry::recalculate(segment_b_rob, segment_b, robust_policy);\r
+\r
+ return point_is_spike_or_equal\r
+ (\r
+ last_point_rob,\r
+ segment_a_rob,\r
+ segment_b_rob\r
+ );\r
+}\r
+\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace point_on_border\r
+{\r
+\r
+\r
+template<typename Point>\r
+struct get_point\r
+{\r
+ static inline bool apply(Point& destination, Point const& source, bool)\r
+ {\r
+ destination = source;\r
+ return true;\r
+ }\r
+};\r
+\r
+template<typename Point, std::size_t Dimension, std::size_t DimensionCount>\r
+struct midpoint_helper\r
+{\r
+ template <typename InputPoint>\r
+ static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2)\r
+ {\r
+ typename coordinate_type<Point>::type const two = 2;\r
+ set<Dimension>(p,\r
+ (get<Dimension>(p1) + get<Dimension>(p2)) / two);\r
+ return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2);\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, std::size_t DimensionCount>\r
+struct midpoint_helper<Point, DimensionCount, DimensionCount>\r
+{\r
+ template <typename InputPoint>\r
+ static inline bool apply(Point& , InputPoint const& , InputPoint const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template<typename Point, typename Range>\r
+struct point_on_range\r
+{\r
+ static inline bool apply(Point& point, Range const& range, bool midpoint)\r
+ {\r
+ const std::size_t n = boost::size(range);\r
+ if (midpoint && n > 1)\r
+ {\r
+ typedef typename boost::range_iterator\r
+ <\r
+ Range const\r
+ >::type iterator;\r
+\r
+ iterator it = boost::begin(range);\r
+ iterator prev = it++;\r
+ while (it != boost::end(range)\r
+ && detail::equals::equals_point_point(*it, *prev))\r
+ {\r
+ prev = it++;\r
+ }\r
+ if (it != boost::end(range))\r
+ {\r
+ return midpoint_helper\r
+ <\r
+ Point,\r
+ 0, dimension<Point>::value\r
+ >::apply(point, *prev, *it);\r
+ }\r
+ }\r
+\r
+ if (n > 0)\r
+ {\r
+ geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+template<typename Point, typename Polygon>\r
+struct point_on_polygon\r
+{\r
+ static inline bool apply(Point& point, Polygon const& polygon, bool midpoint)\r
+ {\r
+ return point_on_range\r
+ <\r
+ Point,\r
+ typename ring_type<Polygon>::type\r
+ >::apply(point, exterior_ring(polygon), midpoint);\r
+ }\r
+};\r
+\r
+\r
+template<typename Point, typename Box>\r
+struct point_on_box\r
+{\r
+ static inline bool apply(Point& point, Box const& box, bool midpoint)\r
+ {\r
+ if (midpoint)\r
+ {\r
+ Point p1, p2;\r
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);\r
+ detail::assign::assign_box_2d_corner<max_corner, min_corner>(box, p2);\r
+ midpoint_helper\r
+ <\r
+ Point,\r
+ 0, dimension<Point>::value\r
+ >::apply(point, p1, p2);\r
+ }\r
+ else\r
+ {\r
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename MultiGeometry,\r
+ typename Policy\r
+>\r
+struct point_on_multi\r
+{\r
+ static inline bool apply(Point& point, MultiGeometry const& multi, bool midpoint)\r
+ {\r
+ // Take a point on the first multi-geometry\r
+ // (i.e. the first that is not empty)\r
+ for (typename boost::range_iterator\r
+ <\r
+ MultiGeometry const\r
+ >::type it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ if (Policy::apply(point, *it, midpoint))\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::point_on_border\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename GeometryTag,\r
+ typename Point,\r
+ typename Geometry\r
+\r
+>\r
+struct point_on_border\r
+{};\r
+\r
+\r
+template<typename Point>\r
+struct point_on_border<point_tag, Point, Point>\r
+ : detail::point_on_border::get_point<Point>\r
+{};\r
+\r
+\r
+template<typename Point, typename Linestring>\r
+struct point_on_border<linestring_tag, Point, Linestring>\r
+ : detail::point_on_border::point_on_range<Point, Linestring>\r
+{};\r
+\r
+\r
+template<typename Point, typename Ring>\r
+struct point_on_border<ring_tag, Point, Ring>\r
+ : detail::point_on_border::point_on_range<Point, Ring>\r
+{};\r
+\r
+\r
+template<typename Point, typename Polygon>\r
+struct point_on_border<polygon_tag, Point, Polygon>\r
+ : detail::point_on_border::point_on_polygon<Point, Polygon>\r
+{};\r
+\r
+\r
+template<typename Point, typename Box>\r
+struct point_on_border<box_tag, Point, Box>\r
+ : detail::point_on_border::point_on_box<Point, Box>\r
+{};\r
+\r
+\r
+template<typename Point, typename Multi>\r
+struct point_on_border<multi_polygon_tag, Point, Multi>\r
+ : detail::point_on_border::point_on_multi\r
+ <\r
+ Point,\r
+ Multi,\r
+ detail::point_on_border::point_on_polygon\r
+ <\r
+ Point,\r
+ typename boost::range_value<Multi>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+template<typename Point, typename Multi>\r
+struct point_on_border<multi_linestring_tag, Point, Multi>\r
+ : detail::point_on_border::point_on_multi\r
+ <\r
+ Point,\r
+ Multi,\r
+ detail::point_on_border::point_on_range\r
+ <\r
+ Point,\r
+ typename boost::range_value<Multi>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief Take point on a border\r
+\ingroup overlay\r
+\tparam Geometry geometry type. This also defines the type of the output point\r
+\param point to assign\r
+\param geometry geometry to take point from\r
+\param midpoint boolean flag, true if the point should not be a vertex, but some point\r
+ in between of two vertices\r
+\return TRUE if successful, else false.\r
+ It is only false if polygon/line have no points\r
+\note for a polygon, it is always a point on the exterior ring\r
+\note for take_midpoint, it is not taken from two consecutive duplicate vertices,\r
+ (unless there are no other).\r
+ */\r
+template <typename Point, typename Geometry>\r
+inline bool point_on_border(Point& point,\r
+ Geometry const& geometry,\r
+ bool midpoint = false)\r
+{\r
+ concepts::check<Point>();\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::point_on_border\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Point,\r
+ Geometry\r
+ >::apply(point, geometry, midpoint);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/numeric/conversion/bounds.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/range/begin.hpp>\r
+#include <boost/range/end.hpp>\r
+#include <boost/range/iterator.hpp>\r
+#include <boost/range/size.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace recalculate\r
+{\r
+\r
+template <std::size_t Dimension>\r
+struct recalculate_point\r
+{\r
+ template <typename Point1, typename Point2, typename Strategy>\r
+ static inline void apply(Point1& point1, Point2 const& point2, Strategy const& strategy)\r
+ {\r
+ std::size_t const dim = Dimension - 1;\r
+ geometry::set<dim>(point1, strategy.template apply<dim>(geometry::get<dim>(point2)));\r
+ recalculate_point<dim>::apply(point1, point2, strategy);\r
+ }\r
+};\r
+\r
+template <>\r
+struct recalculate_point<0>\r
+{\r
+ template <typename Point1, typename Point2, typename Strategy>\r
+ static inline void apply(Point1&, Point2 const&, Strategy const&)\r
+ {\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t Dimension>\r
+struct recalculate_indexed\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline void apply(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ // Do it for both indices in one dimension\r
+ static std::size_t const dim = Dimension - 1;\r
+ geometry::set<0, dim>(geometry1, strategy.template apply<dim>(geometry::get<0, dim>(geometry2)));\r
+ geometry::set<1, dim>(geometry1, strategy.template apply<dim>(geometry::get<1, dim>(geometry2)));\r
+ recalculate_indexed<dim>::apply(geometry1, geometry2, strategy);\r
+ }\r
+};\r
+\r
+template <>\r
+struct recalculate_indexed<0>\r
+{\r
+\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline void apply(Geometry1& , Geometry2 const& , Strategy const& )\r
+ {\r
+ }\r
+};\r
+\r
+struct range_to_range\r
+{\r
+ template\r
+ <\r
+ typename Range1,\r
+ typename Range2,\r
+ typename Strategy\r
+ >\r
+ static inline void apply(Range1& destination, Range2 const& source,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename geometry::point_type<Range2>::type point_type;\r
+ typedef recalculate_point<geometry::dimension<point_type>::value> per_point;\r
+ geometry::clear(destination);\r
+\r
+ for (typename boost::range_iterator<Range2 const>::type it\r
+ = boost::begin(source);\r
+ it != boost::end(source);\r
+ ++it)\r
+ {\r
+ point_type p;\r
+ per_point::apply(p, *it, strategy);\r
+ geometry::append(destination, p);\r
+ }\r
+ }\r
+};\r
+\r
+struct polygon_to_polygon\r
+{\r
+private:\r
+ template\r
+ <\r
+ typename IteratorIn,\r
+ typename IteratorOut,\r
+ typename Strategy\r
+ >\r
+ static inline void iterate(IteratorIn begin, IteratorIn end,\r
+ IteratorOut it_out,\r
+ Strategy const& strategy)\r
+ {\r
+ for (IteratorIn it_in = begin; it_in != end; ++it_in, ++it_out)\r
+ {\r
+ range_to_range::apply(*it_out, *it_in, strategy);\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ typename InteriorRingsOut,\r
+ typename InteriorRingsIn,\r
+ typename Strategy\r
+ >\r
+ static inline void apply_interior_rings(\r
+ InteriorRingsOut& interior_rings_out,\r
+ InteriorRingsIn const& interior_rings_in,\r
+ Strategy const& strategy)\r
+ {\r
+ traits::resize<InteriorRingsOut>::apply(interior_rings_out,\r
+ boost::size(interior_rings_in));\r
+\r
+ iterate(\r
+ boost::begin(interior_rings_in), boost::end(interior_rings_in),\r
+ boost::begin(interior_rings_out),\r
+ strategy);\r
+ }\r
+\r
+public:\r
+ template\r
+ <\r
+ typename Polygon1,\r
+ typename Polygon2,\r
+ typename Strategy\r
+ >\r
+ static inline void apply(Polygon1& destination, Polygon2 const& source,\r
+ Strategy const& strategy)\r
+ {\r
+ range_to_range::apply(geometry::exterior_ring(destination),\r
+ geometry::exterior_ring(source), strategy);\r
+\r
+ apply_interior_rings(geometry::interior_rings(destination),\r
+ geometry::interior_rings(source), strategy);\r
+ }\r
+};\r
+\r
+}} // namespace detail::recalculate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename geometry::tag<Geometry1>::type,\r
+ typename Tag2 = typename geometry::tag<Geometry2>::type\r
+>\r
+struct recalculate : not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+template <typename Point1, typename Point2>\r
+struct recalculate<Point1, Point2, point_tag, point_tag>\r
+ : detail::recalculate::recalculate_point<geometry::dimension<Point1>::value>\r
+{};\r
+\r
+template <typename Box1, typename Box2>\r
+struct recalculate<Box1, Box2, box_tag, box_tag>\r
+ : detail::recalculate::recalculate_indexed<geometry::dimension<Box1>::value>\r
+{};\r
+\r
+template <typename Segment1, typename Segment2>\r
+struct recalculate<Segment1, Segment2, segment_tag, segment_tag>\r
+ : detail::recalculate::recalculate_indexed<geometry::dimension<Segment1>::value>\r
+{};\r
+\r
+template <typename Polygon1, typename Polygon2>\r
+struct recalculate<Polygon1, Polygon2, polygon_tag, polygon_tag>\r
+ : detail::recalculate::polygon_to_polygon\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+inline void recalculate(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry1>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ // static assert dimensions (/types) are the same\r
+\r
+ dispatch::recalculate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP\r
+\r
+#include <boost/geometry/core/topological_dimension.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+#include <boost/geometry/algorithms/detail/sub_range.hpp>\r
+#include <boost/geometry/algorithms/detail/single_geometry.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/turns.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+ \r
+// WARNING!\r
+// TODO: In the worst case calling this Pred in a loop for MultiPolygon/MultiPolygon may take O(NM)\r
+// Use the rtree in this case!\r
+\r
+// may be used to set EI and EB for an Areal geometry for which no turns were generated\r
+template <typename OtherAreal, typename Result, bool TransposeResult>\r
+class no_turns_aa_pred\r
+{\r
+public:\r
+ no_turns_aa_pred(OtherAreal const& other_areal, Result & res)\r
+ : m_result(res)\r
+ , m_other_areal(other_areal)\r
+ , m_flags(0)\r
+ {\r
+ // check which relations must be analysed\r
+\r
+ if ( ! may_update<interior, interior, '2', TransposeResult>(m_result)\r
+ && ! may_update<boundary, interior, '1', TransposeResult>(m_result)\r
+ && ! may_update<exterior, interior, '2', TransposeResult>(m_result) )\r
+ {\r
+ m_flags |= 1;\r
+ }\r
+\r
+ if ( ! may_update<interior, exterior, '2', TransposeResult>(m_result)\r
+ && ! may_update<boundary, exterior, '1', TransposeResult>(m_result) )\r
+ {\r
+ m_flags |= 2;\r
+ }\r
+ }\r
+\r
+ template <typename Areal>\r
+ bool operator()(Areal const& areal)\r
+ {\r
+ // if those flags are set nothing will change\r
+ if ( m_flags == 3 )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ typedef typename geometry::point_type<Areal>::type point_type;\r
+ point_type pt;\r
+ bool const ok = boost::geometry::point_on_border(pt, areal);\r
+\r
+ // TODO: for now ignore, later throw an exception?\r
+ if ( !ok )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ // check if the areal is inside the other_areal\r
+ // TODO: This is O(N)\r
+ // Run in a loop O(NM) - optimize!\r
+ int const pig = detail::within::point_in_geometry(pt, m_other_areal);\r
+ //BOOST_GEOMETRY_ASSERT( pig != 0 );\r
+ \r
+ // inside\r
+ if ( pig > 0 )\r
+ {\r
+ update<interior, interior, '2', TransposeResult>(m_result);\r
+ update<boundary, interior, '1', TransposeResult>(m_result);\r
+ update<exterior, interior, '2', TransposeResult>(m_result);\r
+ m_flags |= 1;\r
+\r
+ // TODO: OPTIMIZE!\r
+ // Only the interior rings of other ONE single geometry must be checked\r
+ // NOT all geometries\r
+\r
+ // Check if any interior ring is outside\r
+ ring_identifier ring_id(0, -1, 0);\r
+ std::size_t const irings_count = geometry::num_interior_rings(areal);\r
+ for ( ; static_cast<std::size_t>(ring_id.ring_index) < irings_count ;\r
+ ++ring_id.ring_index )\r
+ {\r
+ typename detail::sub_range_return_type<Areal const>::type\r
+ range_ref = detail::sub_range(areal, ring_id);\r
+\r
+ if ( boost::empty(range_ref) )\r
+ {\r
+ // TODO: throw exception?\r
+ continue; // ignore\r
+ }\r
+\r
+ // TODO: O(N)\r
+ // Optimize!\r
+ int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal);\r
+\r
+ // hole outside\r
+ if ( hpig < 0 )\r
+ {\r
+ update<interior, exterior, '2', TransposeResult>(m_result);\r
+ update<boundary, exterior, '1', TransposeResult>(m_result);\r
+ m_flags |= 2;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ // outside\r
+ else\r
+ {\r
+ update<interior, exterior, '2', TransposeResult>(m_result);\r
+ update<boundary, exterior, '1', TransposeResult>(m_result);\r
+ m_flags |= 2;\r
+\r
+ // Check if any interior ring is inside\r
+ ring_identifier ring_id(0, -1, 0);\r
+ std::size_t const irings_count = geometry::num_interior_rings(areal);\r
+ for ( ; static_cast<std::size_t>(ring_id.ring_index) < irings_count ;\r
+ ++ring_id.ring_index )\r
+ {\r
+ typename detail::sub_range_return_type<Areal const>::type\r
+ range_ref = detail::sub_range(areal, ring_id);\r
+\r
+ if ( boost::empty(range_ref) )\r
+ {\r
+ // TODO: throw exception?\r
+ continue; // ignore\r
+ }\r
+\r
+ // TODO: O(N)\r
+ // Optimize!\r
+ int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal);\r
+\r
+ // hole inside\r
+ if ( hpig > 0 )\r
+ {\r
+ update<interior, interior, '2', TransposeResult>(m_result);\r
+ update<boundary, interior, '1', TransposeResult>(m_result);\r
+ update<exterior, interior, '2', TransposeResult>(m_result);\r
+ m_flags |= 1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ return m_flags != 3 && !m_result.interrupt;\r
+ }\r
+\r
+private:\r
+ Result & m_result;\r
+ OtherAreal const& m_other_areal;\r
+ int m_flags;\r
+};\r
+\r
+// The implementation of an algorithm calculating relate() for A/A\r
+template <typename Geometry1, typename Geometry2>\r
+struct areal_areal\r
+{\r
+ // check Linear / Areal\r
+ BOOST_STATIC_ASSERT(topological_dimension<Geometry1>::value == 2\r
+ && topological_dimension<Geometry2>::value == 2);\r
+\r
+ static const bool interruption_enabled = true;\r
+\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+ \r
+ template <typename Result>\r
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)\r
+ {\r
+// TODO: If Areal geometry may have infinite size, change the following line:\r
+\r
+ // The result should be FFFFFFFFF\r
+ relate::set<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+\r
+ // get and analyse turns\r
+ typedef typename turns::get_turns<Geometry1, Geometry2>::turn_info turn_type;\r
+ std::vector<turn_type> turns;\r
+\r
+ interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);\r
+\r
+ turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+\r
+ no_turns_aa_pred<Geometry2, Result, false> pred1(geometry2, result);\r
+ for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+\r
+ no_turns_aa_pred<Geometry1, Result, true> pred2(geometry1, result);\r
+ for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+ \r
+ if ( turns.empty() )\r
+ return;\r
+\r
+ if ( may_update<interior, interior, '2'>(result)\r
+ || may_update<interior, exterior, '2'>(result)\r
+ || may_update<boundary, interior, '1'>(result)\r
+ || may_update<boundary, exterior, '1'>(result)\r
+ || may_update<exterior, interior, '2'>(result) )\r
+ {\r
+ // sort turns\r
+ typedef turns::less<0, turns::less_op_areal_areal<0> > less;\r
+ std::sort(turns.begin(), turns.end(), less());\r
+\r
+ /*if ( may_update<interior, exterior, '2'>(result)\r
+ || may_update<boundary, exterior, '1'>(result)\r
+ || may_update<boundary, interior, '1'>(result)\r
+ || may_update<exterior, interior, '2'>(result) )*/\r
+ {\r
+ // analyse sorted turns\r
+ turns_analyser<turn_type, 0> analyser;\r
+ analyse_each_turn(result, analyser, turns.begin(), turns.end());\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+ }\r
+\r
+ if ( may_update<interior, interior, '2'>(result)\r
+ || may_update<interior, exterior, '2'>(result)\r
+ || may_update<boundary, interior, '1'>(result)\r
+ || may_update<boundary, exterior, '1'>(result)\r
+ || may_update<exterior, interior, '2'>(result) )\r
+ {\r
+ // analyse rings for which turns were not generated\r
+ // or only i/i or u/u was generated\r
+ uncertain_rings_analyser<0, Result, Geometry1, Geometry2> rings_analyser(result, geometry1, geometry2);\r
+ analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end());\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+ }\r
+ }\r
+\r
+ if ( may_update<interior, interior, '2', true>(result)\r
+ || may_update<interior, exterior, '2', true>(result)\r
+ || may_update<boundary, interior, '1', true>(result)\r
+ || may_update<boundary, exterior, '1', true>(result)\r
+ || may_update<exterior, interior, '2', true>(result) )\r
+ {\r
+ // sort turns\r
+ typedef turns::less<1, turns::less_op_areal_areal<1> > less;\r
+ std::sort(turns.begin(), turns.end(), less());\r
+\r
+ /*if ( may_update<interior, exterior, '2', true>(result)\r
+ || may_update<boundary, exterior, '1', true>(result)\r
+ || may_update<boundary, interior, '1', true>(result)\r
+ || may_update<exterior, interior, '2', true>(result) )*/\r
+ {\r
+ // analyse sorted turns\r
+ turns_analyser<turn_type, 1> analyser;\r
+ analyse_each_turn(result, analyser, turns.begin(), turns.end());\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+ }\r
+\r
+ if ( may_update<interior, interior, '2', true>(result)\r
+ || may_update<interior, exterior, '2', true>(result)\r
+ || may_update<boundary, interior, '1', true>(result)\r
+ || may_update<boundary, exterior, '1', true>(result)\r
+ || may_update<exterior, interior, '2', true>(result) )\r
+ {\r
+ // analyse rings for which turns were not generated\r
+ // or only i/i or u/u was generated\r
+ uncertain_rings_analyser<1, Result, Geometry2, Geometry1> rings_analyser(result, geometry2, geometry1);\r
+ analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end());\r
+\r
+ //if ( result.interrupt )\r
+ // return;\r
+ }\r
+ }\r
+ }\r
+\r
+ // interrupt policy which may be passed to get_turns to interrupt the analysis\r
+ // based on the info in the passed result/mask\r
+ template <typename Result>\r
+ class interrupt_policy_areal_areal\r
+ {\r
+ public:\r
+ static bool const enabled = true;\r
+\r
+ interrupt_policy_areal_areal(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Result & result)\r
+ : m_result(result)\r
+ , m_geometry1(geometry1)\r
+ , m_geometry2(geometry2)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& turns)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+ \r
+ for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)\r
+ {\r
+ per_turn<0>(*it);\r
+ per_turn<1>(*it);\r
+ }\r
+\r
+ return m_result.interrupt;\r
+ }\r
+\r
+ private:\r
+ template <std::size_t OpId, typename Turn>\r
+ inline void per_turn(Turn const& turn)\r
+ {\r
+ //static const std::size_t other_op_id = (OpId + 1) % 2;\r
+ static const bool transpose_result = OpId != 0;\r
+\r
+ overlay::operation_type const op = turn.operations[OpId].operation;\r
+\r
+ if ( op == overlay::operation_union )\r
+ {\r
+ // ignore u/u\r
+ /*if ( turn.operations[other_op_id].operation != overlay::operation_union )\r
+ {\r
+ update<interior, exterior, '2', transpose_result>(m_result);\r
+ update<boundary, exterior, '1', transpose_result>(m_result);\r
+ }*/\r
+\r
+ update<boundary, boundary, '0', transpose_result>(m_result);\r
+ }\r
+ else if ( op == overlay::operation_intersection )\r
+ {\r
+ // ignore i/i\r
+ /*if ( turn.operations[other_op_id].operation != overlay::operation_intersection )\r
+ {\r
+ // not correct e.g. for G1 touching G2 in a point where a hole is touching the exterior ring\r
+ // in this case 2 turns i/... and u/u will be generated for this IP\r
+ //update<interior, interior, '2', transpose_result>(m_result);\r
+\r
+ //update<boundary, interior, '1', transpose_result>(m_result);\r
+ }*/\r
+\r
+ update<boundary, boundary, '0', transpose_result>(m_result);\r
+ }\r
+ else if ( op == overlay::operation_continue )\r
+ {\r
+ update<boundary, boundary, '1', transpose_result>(m_result);\r
+ update<interior, interior, '2', transpose_result>(m_result);\r
+ }\r
+ else if ( op == overlay::operation_blocked )\r
+ {\r
+ update<boundary, boundary, '1', transpose_result>(m_result);\r
+ update<interior, exterior, '2', transpose_result>(m_result);\r
+ }\r
+ }\r
+\r
+ Result & m_result;\r
+ Geometry1 const& m_geometry1;\r
+ Geometry2 const& m_geometry2;\r
+ };\r
+\r
+ // This analyser should be used like Input or SinglePass Iterator\r
+ // IMPORTANT! It should be called also for the end iterator - last\r
+ template <typename TurnInfo, std::size_t OpId>\r
+ class turns_analyser\r
+ {\r
+ typedef typename TurnInfo::point_type turn_point_type;\r
+\r
+ static const std::size_t op_id = OpId;\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+ static const bool transpose_result = OpId != 0;\r
+\r
+ public:\r
+ turns_analyser()\r
+ : m_previous_turn_ptr(0)\r
+ , m_previous_operation(overlay::operation_none)\r
+ , m_enter_detected(false)\r
+ , m_exit_detected(false)\r
+ {}\r
+\r
+ template <typename Result,\r
+ typename TurnIt>\r
+ void apply(Result & result, TurnIt it)\r
+ {\r
+ //BOOST_GEOMETRY_ASSERT( it != last );\r
+\r
+ overlay::operation_type const op = it->operations[op_id].operation;\r
+\r
+ if ( op != overlay::operation_union\r
+ && op != overlay::operation_intersection\r
+ && op != overlay::operation_blocked\r
+ && op != overlay::operation_continue )\r
+ {\r
+ return;\r
+ }\r
+\r
+ segment_identifier const& seg_id = it->operations[op_id].seg_id;\r
+ //segment_identifier const& other_id = it->operations[other_op_id].seg_id;\r
+\r
+ const bool first_in_range = m_seg_watcher.update(seg_id);\r
+\r
+ if ( m_previous_turn_ptr )\r
+ {\r
+ if ( m_exit_detected /*m_previous_operation == overlay::operation_union*/ )\r
+ {\r
+ // real exit point - may be multiple\r
+ if ( first_in_range\r
+ || ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )\r
+ {\r
+ update_exit(result);\r
+ m_exit_detected = false;\r
+ }\r
+ // fake exit point, reset state\r
+ else if ( op != overlay::operation_union )\r
+ {\r
+ m_exit_detected = false;\r
+ }\r
+ } \r
+ /*else*/\r
+ if ( m_enter_detected /*m_previous_operation == overlay::operation_intersection*/ )\r
+ {\r
+ // real entry point\r
+ if ( first_in_range\r
+ || ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )\r
+ {\r
+ update_enter(result);\r
+ m_enter_detected = false;\r
+ }\r
+ // fake entry point, reset state\r
+ else if ( op != overlay::operation_intersection )\r
+ {\r
+ m_enter_detected = false;\r
+ }\r
+ }\r
+ }\r
+\r
+ if ( op == overlay::operation_union )\r
+ {\r
+ // already set in interrupt policy\r
+ //update<boundary, boundary, '0', transpose_result>(m_result);\r
+\r
+ // ignore u/u\r
+ //if ( it->operations[other_op_id].operation != overlay::operation_union )\r
+ {\r
+ m_exit_detected = true;\r
+ }\r
+ }\r
+ else if ( op == overlay::operation_intersection )\r
+ {\r
+ // ignore i/i\r
+ if ( it->operations[other_op_id].operation != overlay::operation_intersection )\r
+ {\r
+ // this was set in the interrupt policy but it was wrong\r
+ // also here it's wrong since it may be a fake entry point\r
+ //update<interior, interior, '2', transpose_result>(result);\r
+\r
+ // already set in interrupt policy\r
+ //update<boundary, boundary, '0', transpose_result>(result);\r
+ m_enter_detected = true;\r
+ }\r
+ }\r
+ else if ( op == overlay::operation_blocked )\r
+ {\r
+ // already set in interrupt policy\r
+ }\r
+ else // if ( op == overlay::operation_continue )\r
+ {\r
+ // already set in interrupt policy\r
+ }\r
+\r
+ // store ref to previously analysed (valid) turn\r
+ m_previous_turn_ptr = boost::addressof(*it);\r
+ // and previously analysed (valid) operation\r
+ m_previous_operation = op;\r
+ }\r
+\r
+ // it == last\r
+ template <typename Result>\r
+ void apply(Result & result)\r
+ {\r
+ //BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ if ( m_exit_detected /*m_previous_operation == overlay::operation_union*/ )\r
+ {\r
+ update_exit(result);\r
+ m_exit_detected = false;\r
+ }\r
+\r
+ if ( m_enter_detected /*m_previous_operation == overlay::operation_intersection*/ )\r
+ {\r
+ update_enter(result);\r
+ m_enter_detected = false;\r
+ }\r
+ }\r
+\r
+ template <typename Result>\r
+ static inline void update_exit(Result & result)\r
+ {\r
+ update<interior, exterior, '2', transpose_result>(result);\r
+ update<boundary, exterior, '1', transpose_result>(result);\r
+ }\r
+\r
+ template <typename Result>\r
+ static inline void update_enter(Result & result)\r
+ {\r
+ update<interior, interior, '2', transpose_result>(result);\r
+ update<boundary, interior, '1', transpose_result>(result);\r
+ update<exterior, interior, '2', transpose_result>(result);\r
+ }\r
+\r
+ private:\r
+ segment_watcher<same_ring> m_seg_watcher;\r
+ TurnInfo * m_previous_turn_ptr;\r
+ overlay::operation_type m_previous_operation;\r
+ bool m_enter_detected;\r
+ bool m_exit_detected;\r
+ };\r
+\r
+ // call analyser.apply() for each turn in range\r
+ // IMPORTANT! The analyser is also called for the end iterator - last\r
+ template <typename Result,\r
+ typename Analyser,\r
+ typename TurnIt>\r
+ static inline void analyse_each_turn(Result & res,\r
+ Analyser & analyser,\r
+ TurnIt first, TurnIt last)\r
+ {\r
+ if ( first == last )\r
+ return;\r
+\r
+ for ( TurnIt it = first ; it != last ; ++it )\r
+ {\r
+ analyser.apply(res, it);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(res.interrupt) )\r
+ return;\r
+ }\r
+\r
+ analyser.apply(res);\r
+ }\r
+\r
+ template <std::size_t OpId, typename Result, typename Geometry, typename OtherGeometry>\r
+ class uncertain_rings_analyser\r
+ {\r
+ static const bool transpose_result = OpId != 0;\r
+ static const int other_id = (OpId + 1) % 2;\r
+\r
+ public:\r
+ inline uncertain_rings_analyser(Result & result,\r
+ Geometry const& geom,\r
+ OtherGeometry const& other_geom)\r
+ : geometry(geom), other_geometry(other_geom)\r
+ , interrupt(result.interrupt) // just in case, could be false as well\r
+ , m_result(result)\r
+ , m_flags(0)\r
+ {\r
+ // check which relations must be analysed\r
+ // NOTE: 1 and 4 could probably be connected\r
+\r
+ if ( ! may_update<interior, interior, '2', transpose_result>(m_result) )\r
+ {\r
+ m_flags |= 1;\r
+ }\r
+\r
+ if ( ! may_update<interior, exterior, '2', transpose_result>(m_result)\r
+ && ! may_update<boundary, exterior, '1', transpose_result>(m_result) )\r
+ {\r
+ m_flags |= 2;\r
+ }\r
+\r
+ if ( ! may_update<boundary, interior, '1', transpose_result>(m_result)\r
+ && ! may_update<exterior, interior, '2', transpose_result>(m_result) )\r
+ {\r
+ m_flags |= 4;\r
+ }\r
+ }\r
+\r
+ inline void no_turns(segment_identifier const& seg_id)\r
+ {\r
+ // if those flags are set nothing will change\r
+ if ( m_flags == 7 )\r
+ {\r
+ return;\r
+ }\r
+\r
+ typename detail::sub_range_return_type<Geometry const>::type\r
+ range_ref = detail::sub_range(geometry, seg_id);\r
+\r
+ if ( boost::empty(range_ref) )\r
+ {\r
+ // TODO: throw an exception?\r
+ return; // ignore\r
+ }\r
+ \r
+ // TODO: possible optimization\r
+ // if the range is an interior ring we may use other IPs generated for this single geometry\r
+ // to know which other single geometries should be checked\r
+\r
+ // TODO: optimize! e.g. use spatial index\r
+ // O(N) - running it in a loop gives O(NM)\r
+ int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry);\r
+\r
+ //BOOST_GEOMETRY_ASSERT(pig != 0);\r
+ if ( pig > 0 )\r
+ {\r
+ update<interior, interior, '2', transpose_result>(m_result);\r
+ m_flags |= 1;\r
+\r
+ update<boundary, interior, '1', transpose_result>(m_result);\r
+ update<exterior, interior, '2', transpose_result>(m_result);\r
+ m_flags |= 4;\r
+ }\r
+ else\r
+ {\r
+ update<boundary, exterior, '1', transpose_result>(m_result);\r
+ update<interior, exterior, '2', transpose_result>(m_result);\r
+ m_flags |= 2;\r
+ }\r
+\r
+// TODO: break if all things are set\r
+// also some of them could be checked outside, before the analysis\r
+// In this case we shouldn't relay just on dummy flags\r
+// Flags should be initialized with proper values\r
+// or the result should be checked directly\r
+// THIS IS ALSO TRUE FOR OTHER ANALYSERS! in L/L and L/A\r
+\r
+ interrupt = m_flags == 7 || m_result.interrupt;\r
+ }\r
+\r
+ template <typename TurnIt>\r
+ inline void turns(TurnIt first, TurnIt last)\r
+ {\r
+ // if those flags are set nothing will change\r
+ if ( (m_flags & 6) == 6 )\r
+ {\r
+ return;\r
+ }\r
+\r
+ bool found_ii = false;\r
+ bool found_uu = false;\r
+\r
+ for ( TurnIt it = first ; it != last ; ++it )\r
+ {\r
+ if ( it->operations[0].operation == overlay::operation_intersection \r
+ && it->operations[1].operation == overlay::operation_intersection )\r
+ {\r
+ found_ii = true;\r
+ }\r
+ else if ( it->operations[0].operation == overlay::operation_union \r
+ && it->operations[1].operation == overlay::operation_union )\r
+ {\r
+ found_uu = true;\r
+ }\r
+ else // ignore\r
+ {\r
+ return; // don't interrupt\r
+ }\r
+ }\r
+\r
+ // only i/i was generated for this ring\r
+ if ( found_ii )\r
+ {\r
+ update<interior, interior, '2', transpose_result>(m_result);\r
+ m_flags |= 1;\r
+\r
+ //update<boundary, boundary, '0', transpose_result>(m_result); \r
+\r
+ update<boundary, interior, '1', transpose_result>(m_result);\r
+ update<exterior, interior, '2', transpose_result>(m_result);\r
+ m_flags |= 4;\r
+ }\r
+\r
+ // only u/u was generated for this ring\r
+ if ( found_uu )\r
+ {\r
+ update<boundary, exterior, '1', transpose_result>(m_result);\r
+ update<interior, exterior, '2', transpose_result>(m_result);\r
+ m_flags |= 2;\r
+ }\r
+\r
+ interrupt = m_flags == 7 || m_result.interrupt; // interrupt if the result won't be changed in the future\r
+ }\r
+\r
+ Geometry const& geometry;\r
+ OtherGeometry const& other_geometry;\r
+ bool interrupt;\r
+\r
+ private:\r
+ Result & m_result;\r
+ int m_flags;\r
+ };\r
+\r
+ template <std::size_t OpId>\r
+ class analyse_uncertain_rings\r
+ {\r
+ public:\r
+ template <typename Analyser, typename TurnIt>\r
+ static inline void apply(Analyser & analyser, TurnIt first, TurnIt last)\r
+ {\r
+ if ( first == last )\r
+ return;\r
+\r
+ for_preceding_rings(analyser, *first);\r
+ //analyser.per_turn(*first);\r
+\r
+ TurnIt prev = first;\r
+ for ( ++first ; first != last ; ++first, ++prev )\r
+ {\r
+ // same multi\r
+ if ( prev->operations[OpId].seg_id.multi_index\r
+ == first->operations[OpId].seg_id.multi_index )\r
+ {\r
+ // same ring\r
+ if ( prev->operations[OpId].seg_id.ring_index\r
+ == first->operations[OpId].seg_id.ring_index )\r
+ {\r
+ //analyser.per_turn(*first);\r
+ }\r
+ // same multi, next ring\r
+ else\r
+ {\r
+ //analyser.end_ring(*prev);\r
+ analyser.turns(prev, first);\r
+\r
+ //if ( prev->operations[OpId].seg_id.ring_index + 1\r
+ // < first->operations[OpId].seg_id.ring_index)\r
+ {\r
+ for_no_turns_rings(analyser,\r
+ *first,\r
+ prev->operations[OpId].seg_id.ring_index + 1,\r
+ first->operations[OpId].seg_id.ring_index);\r
+ }\r
+\r
+ //analyser.per_turn(*first);\r
+ }\r
+ }\r
+ // next multi\r
+ else\r
+ {\r
+ //analyser.end_ring(*prev);\r
+ analyser.turns(prev, first);\r
+ for_following_rings(analyser, *prev);\r
+ for_preceding_rings(analyser, *first);\r
+ //analyser.per_turn(*first);\r
+ }\r
+\r
+ if ( analyser.interrupt )\r
+ {\r
+ return;\r
+ }\r
+ }\r
+\r
+ //analyser.end_ring(*prev);\r
+ analyser.turns(prev, first); // first == last\r
+ for_following_rings(analyser, *prev);\r
+ }\r
+\r
+ private:\r
+ template <typename Analyser, typename Turn>\r
+ static inline void for_preceding_rings(Analyser & analyser, Turn const& turn)\r
+ {\r
+ segment_identifier const& seg_id = turn.operations[OpId].seg_id;\r
+\r
+ for_no_turns_rings(analyser, turn, -1, seg_id.ring_index);\r
+ }\r
+\r
+ template <typename Analyser, typename Turn>\r
+ static inline void for_following_rings(Analyser & analyser, Turn const& turn)\r
+ {\r
+ segment_identifier const& seg_id = turn.operations[OpId].seg_id;\r
+\r
+ signed_size_type\r
+ count = boost::numeric_cast<signed_size_type>(\r
+ geometry::num_interior_rings(\r
+ detail::single_geometry(analyser.geometry, seg_id)));\r
+ \r
+ for_no_turns_rings(analyser, turn, seg_id.ring_index + 1, count);\r
+ }\r
+\r
+ template <typename Analyser, typename Turn>\r
+ static inline void for_no_turns_rings(Analyser & analyser,\r
+ Turn const& turn,\r
+ signed_size_type first,\r
+ signed_size_type last)\r
+ {\r
+ segment_identifier seg_id = turn.operations[OpId].seg_id;\r
+\r
+ for ( seg_id.ring_index = first ; seg_id.ring_index < last ; ++seg_id.ring_index )\r
+ {\r
+ analyser.no_turns(seg_id);\r
+ }\r
+ }\r
+ };\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+#include <boost/geometry/algorithms/detail/sub_range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+#include <boost/geometry/util/has_nan_coordinate.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+enum boundary_query { boundary_front, boundary_back, boundary_any };\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type>\r
+class boundary_checker {};\r
+\r
+template <typename Geometry>\r
+class boundary_checker<Geometry, linestring_tag>\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+public:\r
+ boundary_checker(Geometry const& g)\r
+ : has_boundary( boost::size(g) >= 2\r
+ && !detail::equals::equals_point_point(range::front(g), range::back(g)) )\r
+ , geometry(g)\r
+ {}\r
+\r
+ template <boundary_query BoundaryQuery>\r
+ bool is_endpoint_boundary(point_type const& pt) const\r
+ {\r
+ boost::ignore_unused_variable_warning(pt);\r
+#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER\r
+ // may give false positives for INT\r
+ BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)\r
+ && detail::equals::equals_point_point(pt, range::front(geometry))\r
+ || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)\r
+ && detail::equals::equals_point_point(pt, range::back(geometry)) );\r
+#endif\r
+ return has_boundary;\r
+ }\r
+\r
+private:\r
+ bool has_boundary;\r
+ Geometry const& geometry;\r
+};\r
+\r
+template <typename Geometry>\r
+class boundary_checker<Geometry, multi_linestring_tag>\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+public:\r
+ boundary_checker(Geometry const& g)\r
+ : is_filled(false), geometry(g)\r
+ {}\r
+\r
+ // First call O(NlogN)\r
+ // Each next call O(logN)\r
+ template <boundary_query BoundaryQuery>\r
+ bool is_endpoint_boundary(point_type const& pt) const\r
+ {\r
+ typedef typename boost::range_size<Geometry>::type size_type;\r
+ size_type multi_count = boost::size(geometry);\r
+\r
+ if ( multi_count < 1 )\r
+ return false;\r
+\r
+ if ( ! is_filled )\r
+ {\r
+ //boundary_points.clear();\r
+ boundary_points.reserve(multi_count * 2);\r
+\r
+ typedef typename boost::range_iterator<Geometry const>::type multi_iterator;\r
+ for ( multi_iterator it = boost::begin(geometry) ;\r
+ it != boost::end(geometry) ; ++ it )\r
+ {\r
+ typename boost::range_reference<Geometry const>::type\r
+ ls = *it;\r
+\r
+ // empty or point - no boundary\r
+ if (boost::size(ls) < 2)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ typedef typename boost::range_reference\r
+ <\r
+ typename boost::range_value<Geometry const>::type const\r
+ >::type point_reference;\r
+\r
+ point_reference front_pt = range::front(ls);\r
+ point_reference back_pt = range::back(ls);\r
+\r
+ // linear ring or point - no boundary\r
+ if (! equals::equals_point_point(front_pt, back_pt))\r
+ {\r
+ // do not add points containing NaN coordinates\r
+ // because they cannot be reasonably compared, e.g. with MSVC\r
+ // an assertion failure is reported in std::equal_range()\r
+ if (! geometry::has_nan_coordinate(front_pt))\r
+ {\r
+ boundary_points.push_back(front_pt);\r
+ }\r
+ if (! geometry::has_nan_coordinate(back_pt))\r
+ {\r
+ boundary_points.push_back(back_pt);\r
+ }\r
+ }\r
+ }\r
+\r
+ std::sort(boundary_points.begin(),\r
+ boundary_points.end(),\r
+ geometry::less<point_type>());\r
+\r
+ is_filled = true;\r
+ }\r
+\r
+ std::size_t equal_points_count\r
+ = boost::size(\r
+ std::equal_range(boundary_points.begin(),\r
+ boundary_points.end(),\r
+ pt,\r
+ geometry::less<point_type>())\r
+ );\r
+\r
+ return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0\r
+ }\r
+\r
+private:\r
+ mutable bool is_filled;\r
+ // TODO: store references/pointers instead of points?\r
+ mutable std::vector<point_type> boundary_points;\r
+\r
+ Geometry const& geometry;\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP\r
+\r
+#include <boost/mpl/is_sequence.hpp>\r
+#include <boost/mpl/push_back.hpp>\r
+#include <boost/mpl/vector.hpp>\r
+#include <boost/mpl/vector_c.hpp>\r
+#include <boost/static_assert.hpp>\r
+#include <boost/tuple/tuple.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/result.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/core/topological_dimension.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+\r
+// TEMP - move this header to geometry/detail\r
+#include <boost/geometry/index/detail/tuples.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ \r
+namespace de9im\r
+{\r
+\r
+/*!\r
+\brief DE-9IM model intersection matrix.\r
+\ingroup de9im\r
+\details This matrix can be used to express spatial relations as defined in\r
+ Dimensionally Extended 9-Intersection Model.\r
+\r
+\qbk{[heading See also]}\r
+\qbk{* [link geometry.reference.algorithms.relation relation]}\r
+ */\r
+class matrix\r
+ : public detail::relate::matrix<3, 3>\r
+{\r
+#ifdef DOXYGEN_INVOKED\r
+public:\r
+ /*!\r
+ \brief Initializes all of the matrix elements to F\r
+ */\r
+ matrix();\r
+ /*!\r
+ \brief Subscript operator\r
+ \param index The index of the element\r
+ \return The element\r
+ */\r
+ char operator[](std::size_t index) const;\r
+ /*!\r
+ \brief Returns the iterator to the first element\r
+ \return const RandomAccessIterator\r
+ */\r
+ const_iterator begin() const;\r
+ /*!\r
+ \brief Returns the iterator past the last element\r
+ \return const RandomAccessIterator\r
+ */\r
+ const_iterator end() const;\r
+ /*!\r
+ \brief Returns the number of elements\r
+ \return 9\r
+ */\r
+ static std::size_t size();\r
+ /*!\r
+ \brief Returns raw pointer to elements\r
+ \return const pointer to array of elements\r
+ */\r
+ inline const char * data() const;\r
+ /*!\r
+ \brief Returns std::string containing elements\r
+ \return string containing elements\r
+ */\r
+ inline std::string str() const;\r
+#endif\r
+};\r
+\r
+/*!\r
+\brief DE-9IM model intersection mask.\r
+\ingroup de9im\r
+\details This mask can be used to check spatial relations as defined in\r
+ Dimensionally Extended 9-Intersection Model.\r
+\r
+\qbk{[heading See also]}\r
+\qbk{* [link geometry.reference.algorithms.relate relate]}\r
+ */\r
+class mask\r
+ : public detail::relate::mask<3, 3>\r
+{\r
+ typedef detail::relate::mask<3, 3> base_type;\r
+\r
+public:\r
+ /*!\r
+ \brief The constructor.\r
+ \param code The mask pattern.\r
+ */\r
+ inline explicit mask(const char* code)\r
+ : base_type(code)\r
+ {}\r
+ \r
+ /*!\r
+ \brief The constructor.\r
+ \param code The mask pattern.\r
+ */\r
+ inline explicit mask(std::string const& code)\r
+ : base_type(code.c_str(), code.size())\r
+ {}\r
+};\r
+\r
+// static_mask\r
+\r
+/*!\r
+\brief DE-9IM model intersection mask (static version).\r
+\ingroup de9im\r
+\details This mask can be used to check spatial relations as defined in\r
+ Dimensionally Extended 9-Intersection Model.\r
+\tparam II Interior/Interior intersection mask element\r
+\tparam IB Interior/Boundary intersection mask element\r
+\tparam IE Interior/Exterior intersection mask element\r
+\tparam BI Boundary/Interior intersection mask element\r
+\tparam BB Boundary/Boundary intersection mask element\r
+\tparam BE Boundary/Exterior intersection mask element\r
+\tparam EI Exterior/Interior intersection mask element\r
+\tparam EB Exterior/Boundary intersection mask element\r
+\tparam EE Exterior/Exterior intersection mask element\r
+\r
+\qbk{[heading See also]}\r
+\qbk{* [link geometry.reference.algorithms.relate relate]}\r
+ */\r
+template\r
+<\r
+ char II = '*', char IB = '*', char IE = '*',\r
+ char BI = '*', char BB = '*', char BE = '*',\r
+ char EI = '*', char EB = '*', char EE = '*'\r
+>\r
+class static_mask\r
+ : public detail::relate::static_mask\r
+ <\r
+ boost::mpl::vector_c\r
+ <\r
+ char, II, IB, IE, BI, BB, BE, EI, EB, EE\r
+ >,\r
+ 3, 3\r
+ >\r
+{};\r
+\r
+} // namespace de9im\r
+\r
+namespace detail { namespace de9im\r
+{\r
+\r
+// a small helper util for ORing static masks\r
+\r
+template\r
+<\r
+ typename Seq,\r
+ typename T,\r
+ bool IsSeq = boost::mpl::is_sequence<Seq>::value\r
+>\r
+struct push_back\r
+{\r
+ typedef typename boost::mpl::push_back\r
+ <\r
+ Seq,\r
+ T\r
+ >::type type;\r
+};\r
+\r
+template <typename Seq, typename T>\r
+struct push_back<Seq, T, false>\r
+{};\r
+\r
+}} // namespace detail::de9im\r
+\r
+namespace de9im\r
+{\r
+\r
+inline\r
+boost::tuples::cons\r
+ <\r
+ mask,\r
+ boost::tuples::cons<mask, boost::tuples::null_type>\r
+ >\r
+operator||(mask const& m1, mask const& m2)\r
+{\r
+ namespace bt = boost::tuples;\r
+\r
+ return bt::cons<mask, bt::cons<mask, bt::null_type> >\r
+ ( m1, bt::cons<mask, bt::null_type>(m2, bt::null_type()) );\r
+}\r
+\r
+template <typename Tail>\r
+inline\r
+typename index::detail::tuples::push_back\r
+ <\r
+ boost::tuples::cons<mask, Tail>,\r
+ mask\r
+ >::type\r
+operator||(boost::tuples::cons<mask, Tail> const& t, mask const& m)\r
+{\r
+ namespace bt = boost::tuples;\r
+\r
+ return index::detail::tuples::push_back\r
+ <\r
+ bt::cons<mask, Tail>,\r
+ mask\r
+ >::apply(t, m);\r
+}\r
+\r
+template\r
+<\r
+ char II1, char IB1, char IE1,\r
+ char BI1, char BB1, char BE1,\r
+ char EI1, char EB1, char EE1,\r
+ char II2, char IB2, char IE2,\r
+ char BI2, char BB2, char BE2,\r
+ char EI2, char EB2, char EE2\r
+>\r
+inline\r
+boost::mpl::vector<\r
+ static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,\r
+ static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>\r
+>\r
+operator||(static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1> const& ,\r
+ static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2> const& )\r
+{\r
+ return boost::mpl::vector\r
+ <\r
+ static_mask<II1, IB1, IE1, BI1, BB1, BE1, EI1, EB1, EE1>,\r
+ static_mask<II2, IB2, IE2, BI2, BB2, BE2, EI2, EB2, EE2>\r
+ >();\r
+}\r
+\r
+template\r
+<\r
+ typename Seq,\r
+ char II, char IB, char IE,\r
+ char BI, char BB, char BE,\r
+ char EI, char EB, char EE\r
+>\r
+inline\r
+typename detail::de9im::push_back\r
+ <\r
+ Seq,\r
+ static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>\r
+ >::type\r
+operator||(Seq const& ,\r
+ static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE> const& )\r
+{\r
+ return typename detail::de9im::push_back\r
+ <\r
+ Seq,\r
+ static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>\r
+ >::type();\r
+}\r
+\r
+} // namespace de9im\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace de9im\r
+{\r
+\r
+// PREDEFINED MASKS\r
+\r
+// TODO:\r
+// 1. specialize for simplified masks if available\r
+// e.g. for TOUCHES use 1 mask for A/A\r
+// 2. Think about dimensions > 2 e.g. should TOUCHES be true\r
+// if the interior of the Areal overlaps the boundary of the Volumetric\r
+// like it's true for Linear/Areal\r
+\r
+// EQUALS\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_equals_type\r
+{\r
+ typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia\r
+ //typedef geometry::de9im::static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC\r
+};\r
+\r
+// DISJOINT\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_disjoint_type\r
+{\r
+ typedef geometry::de9im::static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> type;\r
+};\r
+\r
+// TOUCHES - NOT P/P\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,\r
+ std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value\r
+>\r
+struct static_mask_touches_impl\r
+{\r
+ typedef boost::mpl::vector\r
+ <\r
+ geometry::de9im::static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>,\r
+ geometry::de9im::static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>,\r
+ geometry::de9im::static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'>\r
+ > type;\r
+};\r
+// According to OGC, doesn't apply to P/P\r
+// Using the above mask the result would be always false\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>\r
+ : not_implemented<typename geometry::tag<Geometry1>::type,\r
+ typename geometry::tag<Geometry2>::type>\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_touches_type\r
+ : static_mask_touches_impl<Geometry1, Geometry2>\r
+{};\r
+\r
+// WITHIN\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_within_type\r
+{\r
+ typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> type;\r
+};\r
+\r
+// COVERED_BY (non OGC)\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_covered_by_type\r
+{\r
+ typedef boost::mpl::vector\r
+ <\r
+ geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>,\r
+ geometry::de9im::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>,\r
+ geometry::de9im::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>,\r
+ geometry::de9im::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'>\r
+ > type;\r
+};\r
+\r
+// CROSSES\r
+// dim(G1) < dim(G2) - P/L P/A L/A\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,\r
+ std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value,\r
+ bool D1LessD2 = (Dim1 < Dim2)\r
+>\r
+struct static_mask_crosses_impl\r
+{\r
+ typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type;\r
+};\r
+// TODO: I'm not sure if this one below should be available!\r
+// dim(G1) > dim(G2) - L/P A/P A/L\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, std::size_t Dim1, std::size_t Dim2\r
+>\r
+struct static_mask_crosses_impl<Geometry1, Geometry2, Dim1, Dim2, false>\r
+{\r
+ typedef geometry::de9im::static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type;\r
+};\r
+// dim(G1) == dim(G2) - P/P A/A\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, std::size_t Dim\r
+>\r
+struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>\r
+ : not_implemented\r
+ <\r
+ typename geometry::tag<Geometry1>::type,\r
+ typename geometry::tag<Geometry2>::type\r
+ >\r
+{};\r
+// dim(G1) == 1 && dim(G2) == 1 - L/L\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>\r
+{\r
+ typedef geometry::de9im::static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_crosses_type\r
+ : static_mask_crosses_impl<Geometry1, Geometry2>\r
+{};\r
+\r
+// OVERLAPS\r
+\r
+// dim(G1) != dim(G2) - NOT P/P, L/L, A/A\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ std::size_t Dim1 = geometry::topological_dimension<Geometry1>::value,\r
+ std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value\r
+>\r
+struct static_mask_overlaps_impl\r
+ : not_implemented\r
+ <\r
+ typename geometry::tag<Geometry1>::type,\r
+ typename geometry::tag<Geometry2>::type\r
+ >\r
+{};\r
+// dim(G1) == D && dim(G2) == D - P/P A/A\r
+template <typename Geometry1, typename Geometry2, std::size_t Dim>\r
+struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>\r
+{\r
+ typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;\r
+};\r
+// dim(G1) == 1 && dim(G2) == 1 - L/L\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>\r
+{\r
+ typedef geometry::de9im::static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct static_mask_overlaps_type\r
+ : static_mask_overlaps_impl<Geometry1, Geometry2>\r
+{};\r
+\r
+}} // namespace detail::de9im\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+//#include <boost/geometry/algorithms/detail/sub_range.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+// NOTE: This iterates through single geometries for which turns were not generated.\r
+// It doesn't mean that the geometry is disjoint, only that no turns were detected.\r
+\r
+template <std::size_t OpId,\r
+ typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type,\r
+ bool IsMulti = boost::is_base_of<multi_tag, Tag>::value\r
+>\r
+struct for_each_disjoint_geometry_if\r
+ : public not_implemented<Tag>\r
+{};\r
+\r
+template <std::size_t OpId, typename Geometry, typename Tag>\r
+struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, false>\r
+{\r
+ template <typename TurnIt, typename Pred>\r
+ static inline bool apply(TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ Pred & pred)\r
+ {\r
+ if ( first != last )\r
+ return false;\r
+ pred(geometry);\r
+ return true;\r
+ }\r
+};\r
+\r
+template <std::size_t OpId, typename Geometry, typename Tag>\r
+struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>\r
+{\r
+ template <typename TurnIt, typename Pred>\r
+ static inline bool apply(TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ Pred & pred)\r
+ {\r
+ if ( first != last )\r
+ return for_turns(first, last, geometry, pred);\r
+ else\r
+ return for_empty(geometry, pred);\r
+ }\r
+\r
+ template <typename Pred>\r
+ static inline bool for_empty(Geometry const& geometry,\r
+ Pred & pred)\r
+ {\r
+ typedef typename boost::range_iterator<Geometry const>::type iterator;\r
+\r
+ // O(N)\r
+ // check predicate for each contained geometry without generated turn\r
+ for ( iterator it = boost::begin(geometry) ;\r
+ it != boost::end(geometry) ; ++it )\r
+ {\r
+ bool cont = pred(*it);\r
+ if ( !cont )\r
+ break;\r
+ }\r
+ \r
+ return !boost::empty(geometry);\r
+ }\r
+\r
+ template <typename TurnIt, typename Pred>\r
+ static inline bool for_turns(TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ Pred & pred)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(first != last);\r
+\r
+ const std::size_t count = boost::size(geometry);\r
+ boost::ignore_unused_variable_warning(count);\r
+\r
+ // O(I)\r
+ // gather info about turns generated for contained geometries\r
+ std::vector<bool> detected_intersections(count, false);\r
+ for ( TurnIt it = first ; it != last ; ++it )\r
+ {\r
+ signed_size_type multi_index = it->operations[OpId].seg_id.multi_index;\r
+ BOOST_GEOMETRY_ASSERT(multi_index >= 0);\r
+ std::size_t const index = static_cast<std::size_t>(multi_index);\r
+ BOOST_GEOMETRY_ASSERT(index < count);\r
+ detected_intersections[index] = true;\r
+ }\r
+\r
+ bool found = false;\r
+\r
+ // O(N)\r
+ // check predicate for each contained geometry without generated turn\r
+ for ( std::vector<bool>::iterator it = detected_intersections.begin() ;\r
+ it != detected_intersections.end() ; ++it )\r
+ {\r
+ // if there were no intersections for this multi_index\r
+ if ( *it == false )\r
+ {\r
+ found = true;\r
+ std::size_t const index = std::size_t(std::distance(detected_intersections.begin(), it));\r
+ bool cont = pred(range::at(geometry, index));\r
+ if ( !cont )\r
+ break;\r
+ }\r
+ }\r
+ \r
+ return found;\r
+ }\r
+};\r
+\r
+// WARNING! This class stores pointers!\r
+// Passing a reference to local variable will result in undefined behavior!\r
+template <typename Point>\r
+class point_info\r
+{\r
+public:\r
+ point_info() : sid_ptr(NULL), pt_ptr(NULL) {}\r
+ point_info(Point const& pt, segment_identifier const& sid)\r
+ : sid_ptr(boost::addressof(sid))\r
+ , pt_ptr(boost::addressof(pt))\r
+ {}\r
+ segment_identifier const& seg_id() const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(sid_ptr);\r
+ return *sid_ptr;\r
+ }\r
+ Point const& point() const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(pt_ptr);\r
+ return *pt_ptr;\r
+ }\r
+\r
+ //friend bool operator==(point_identifier const& l, point_identifier const& r)\r
+ //{\r
+ // return l.seg_id() == r.seg_id()\r
+ // && detail::equals::equals_point_point(l.point(), r.point());\r
+ //}\r
+\r
+private:\r
+ const segment_identifier * sid_ptr;\r
+ const Point * pt_ptr;\r
+};\r
+\r
+// WARNING! This class stores pointers!\r
+// Passing a reference to local variable will result in undefined behavior!\r
+class same_single\r
+{\r
+public:\r
+ same_single(segment_identifier const& sid)\r
+ : sid_ptr(boost::addressof(sid))\r
+ {}\r
+\r
+ bool operator()(segment_identifier const& sid) const\r
+ {\r
+ return sid.multi_index == sid_ptr->multi_index; \r
+ }\r
+\r
+ template <typename Point>\r
+ bool operator()(point_info<Point> const& pid) const\r
+ {\r
+ return operator()(pid.seg_id());\r
+ }\r
+\r
+private:\r
+ const segment_identifier * sid_ptr;\r
+};\r
+\r
+class same_ring\r
+{\r
+public:\r
+ same_ring(segment_identifier const& sid)\r
+ : sid_ptr(boost::addressof(sid))\r
+ {}\r
+\r
+ bool operator()(segment_identifier const& sid) const\r
+ {\r
+ return sid.multi_index == sid_ptr->multi_index\r
+ && sid.ring_index == sid_ptr->ring_index;\r
+ }\r
+\r
+private:\r
+ const segment_identifier * sid_ptr;\r
+};\r
+\r
+// WARNING! This class stores pointers!\r
+// Passing a reference to local variable will result in undefined behavior!\r
+template <typename SameRange = same_single>\r
+class segment_watcher\r
+{\r
+public:\r
+ segment_watcher()\r
+ : m_seg_id_ptr(NULL)\r
+ {}\r
+\r
+ bool update(segment_identifier const& seg_id)\r
+ {\r
+ bool result = m_seg_id_ptr == 0 || !SameRange(*m_seg_id_ptr)(seg_id);\r
+ m_seg_id_ptr = boost::addressof(seg_id);\r
+ return result;\r
+ }\r
+\r
+private:\r
+ const segment_identifier * m_seg_id_ptr;\r
+};\r
+\r
+// WARNING! This class stores pointers!\r
+// Passing a reference to local variable will result in undefined behavior!\r
+template <typename TurnInfo, std::size_t OpId>\r
+class exit_watcher\r
+{\r
+ static const std::size_t op_id = OpId;\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+\r
+ typedef typename TurnInfo::point_type point_type;\r
+ typedef detail::relate::point_info<point_type> point_info;\r
+\r
+public:\r
+ exit_watcher()\r
+ : m_exit_operation(overlay::operation_none)\r
+ , m_exit_turn_ptr(NULL)\r
+ {}\r
+\r
+ void enter(TurnInfo const& turn)\r
+ {\r
+ m_other_entry_points.push_back(\r
+ point_info(turn.point, turn.operations[other_op_id].seg_id) );\r
+ }\r
+\r
+ // TODO: exit_per_geometry parameter looks not very safe\r
+ // wrong value may be easily passed\r
+\r
+ void exit(TurnInfo const& turn, bool exit_per_geometry = true)\r
+ {\r
+ //segment_identifier const& seg_id = turn.operations[op_id].seg_id;\r
+ segment_identifier const& other_id = turn.operations[other_op_id].seg_id;\r
+ overlay::operation_type exit_op = turn.operations[op_id].operation;\r
+\r
+ typedef typename std::vector<point_info>::iterator point_iterator;\r
+ // search for the entry point in the same range of other geometry\r
+ point_iterator entry_it = std::find_if(m_other_entry_points.begin(),\r
+ m_other_entry_points.end(),\r
+ same_single(other_id));\r
+\r
+ // this end point has corresponding entry point\r
+ if ( entry_it != m_other_entry_points.end() )\r
+ {\r
+ // erase the corresponding entry point\r
+ m_other_entry_points.erase(entry_it);\r
+\r
+ if ( exit_per_geometry || m_other_entry_points.empty() )\r
+ {\r
+ // here we know that we possibly left LS\r
+ // we must still check if we didn't get back on the same point\r
+ m_exit_operation = exit_op;\r
+ m_exit_turn_ptr = boost::addressof(turn);\r
+ }\r
+ }\r
+ }\r
+\r
+ bool is_outside() const\r
+ {\r
+ // if we didn't entered anything in the past, we're outside\r
+ return m_other_entry_points.empty();\r
+ }\r
+\r
+ bool is_outside(TurnInfo const& turn) const\r
+ {\r
+ return m_other_entry_points.empty()\r
+ || std::find_if(m_other_entry_points.begin(),\r
+ m_other_entry_points.end(),\r
+ same_single(\r
+ turn.operations[other_op_id].seg_id))\r
+ == m_other_entry_points.end();\r
+ }\r
+\r
+ overlay::operation_type get_exit_operation() const\r
+ {\r
+ return m_exit_operation;\r
+ }\r
+\r
+ point_type const& get_exit_point() const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none);\r
+ BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr);\r
+ return m_exit_turn_ptr->point;\r
+ }\r
+\r
+ TurnInfo const& get_exit_turn() const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none);\r
+ BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr);\r
+ return *m_exit_turn_ptr;\r
+ }\r
+\r
+ void reset_detected_exit()\r
+ {\r
+ m_exit_operation = overlay::operation_none;\r
+ }\r
+\r
+ void reset()\r
+ {\r
+ m_exit_operation = overlay::operation_none;\r
+ m_other_entry_points.clear();\r
+ }\r
+\r
+private:\r
+ overlay::operation_type m_exit_operation;\r
+ const TurnInfo * m_exit_turn_ptr;\r
+ std::vector<point_info> m_other_entry_points; // TODO: use map here or sorted vector?\r
+};\r
+\r
+template <std::size_t OpId, typename Turn>\r
+inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn)\r
+{\r
+ segment_identifier const& prev_seg_id = prev_turn.operations[OpId].seg_id;\r
+ segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id;\r
+\r
+ if ( prev_seg_id.multi_index != curr_seg_id.multi_index\r
+ || prev_seg_id.ring_index != curr_seg_id.ring_index )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // TODO: will this work if between segments there will be some number of degenerated ones?\r
+\r
+ if ( prev_seg_id.segment_index != curr_seg_id.segment_index\r
+ && ( ! curr_turn.operations[OpId].fraction.is_zero()\r
+ || prev_seg_id.segment_index + 1 != curr_seg_id.segment_index ) )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return detail::equals::equals_point_point(prev_turn.point, curr_turn.point);\r
+}\r
+\r
+template <boundary_query BoundaryQuery,\r
+ typename Point,\r
+ typename BoundaryChecker>\r
+static inline bool is_endpoint_on_boundary(Point const& pt,\r
+ BoundaryChecker & boundary_checker)\r
+{\r
+ return boundary_checker.template is_endpoint_boundary<BoundaryQuery>(pt);\r
+}\r
+\r
+template <boundary_query BoundaryQuery,\r
+ typename IntersectionPoint,\r
+ typename OperationInfo,\r
+ typename BoundaryChecker>\r
+static inline bool is_ip_on_boundary(IntersectionPoint const& ip,\r
+ OperationInfo const& operation_info,\r
+ BoundaryChecker & boundary_checker,\r
+ segment_identifier const& seg_id)\r
+{\r
+ boost::ignore_unused_variable_warning(seg_id);\r
+\r
+ bool res = false;\r
+\r
+ // IP on the last point of the linestring\r
+ if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)\r
+ && operation_info.position == overlay::position_back )\r
+ {\r
+ // check if this point is a boundary\r
+ res = boundary_checker.template is_endpoint_boundary<boundary_back>(ip);\r
+ }\r
+ // IP on the last point of the linestring\r
+ else if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)\r
+ && operation_info.position == overlay::position_front )\r
+ {\r
+ // check if this point is a boundary\r
+ res = boundary_checker.template is_endpoint_boundary<boundary_front>(ip);\r
+ }\r
+ \r
+ return res;\r
+}\r
+\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP\r
+\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>\r
+\r
+\r
+namespace boost { namespace geometry {\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch {\r
+\r
+template <typename Point1, typename Point2>\r
+struct relate<Point1, Point2, point_tag, point_tag, 0, 0, false>\r
+ : detail::relate::point_point<Point1, Point2>\r
+{};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct relate<Point, MultiPoint, point_tag, multi_point_tag, 0, 0, false>\r
+ : detail::relate::point_multipoint<Point, MultiPoint>\r
+{};\r
+\r
+template <typename MultiPoint, typename Point>\r
+struct relate<MultiPoint, Point, multi_point_tag, point_tag, 0, 0, false>\r
+ : detail::relate::multipoint_point<MultiPoint, Point>\r
+{};\r
+\r
+template <typename MultiPoint1, typename MultiPoint2>\r
+struct relate<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, 0, 0, false>\r
+ : detail::relate::multipoint_multipoint<MultiPoint1, MultiPoint2>\r
+{};\r
+\r
+// TODO - for now commented out because before implementing it we must consider:\r
+// 1. how the Box degenerated to a Point should be treated\r
+// 2. what should be the definition of a Box degenerated to a Point\r
+// 3. what fields should the matrix/mask contain for dimension > 2 and dimension > 9\r
+//\r
+//template <typename Point, typename Box, int TopDim2>\r
+//struct relate<Point, Box, point_tag, box_tag, 0, TopDim2, false>\r
+// : detail::relate::point_box<Point, Box>\r
+//{};\r
+//\r
+//template <typename Box, typename Point, int TopDim1>\r
+//struct relate<Box, Point, box_tag, point_tag, TopDim1, 0, false>\r
+// : detail::relate::box_point<Box, Point>\r
+//{};\r
+\r
+\r
+template <typename Point, typename Geometry, typename Tag2, int TopDim2>\r
+struct relate<Point, Geometry, point_tag, Tag2, 0, TopDim2, true>\r
+ : detail::relate::point_geometry<Point, Geometry>\r
+{};\r
+\r
+template <typename Geometry, typename Point, typename Tag1, int TopDim1>\r
+struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true>\r
+ : detail::relate::geometry_point<Geometry, Point>\r
+{};\r
+\r
+\r
+template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>\r
+struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true>\r
+ : detail::relate::linear_linear<Linear1, Linear2>\r
+{};\r
+\r
+\r
+template <typename Linear, typename Areal, typename Tag1, typename Tag2>\r
+struct relate<Linear, Areal, Tag1, Tag2, 1, 2, true>\r
+ : detail::relate::linear_areal<Linear, Areal>\r
+{};\r
+\r
+template <typename Areal, typename Linear, typename Tag1, typename Tag2>\r
+struct relate<Areal, Linear, Tag1, Tag2, 2, 1, true>\r
+ : detail::relate::areal_linear<Areal, Linear>\r
+{};\r
+\r
+\r
+template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>\r
+struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true>\r
+ : detail::relate::areal_areal<Areal1, Areal2>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP\r
+\r
+\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/topological_dimension.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/de9im.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+\r
+\r
+namespace boost { namespace geometry {\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+// Those are used only to allow dispatch::relate to produce compile-time error\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type>\r
+struct is_supported_by_generic\r
+{\r
+ static const bool value\r
+ = boost::is_same<Tag, linestring_tag>::value\r
+ || boost::is_same<Tag, multi_linestring_tag>::value\r
+ || boost::is_same<Tag, ring_tag>::value\r
+ || boost::is_same<Tag, polygon_tag>::value\r
+ || boost::is_same<Tag, multi_polygon_tag>::value;\r
+};\r
+\r
+template <typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename geometry::tag<Geometry1>::type,\r
+ typename Tag2 = typename geometry::tag<Geometry2>::type>\r
+struct is_generic\r
+{\r
+ static const bool value = is_supported_by_generic<Geometry1>::value\r
+ && is_supported_by_generic<Geometry2>::value;\r
+};\r
+\r
+\r
+template <typename Point, typename Geometry, typename Tag>\r
+struct is_generic<Point, Geometry, point_tag, Tag>\r
+{\r
+ static const bool value = is_supported_by_generic<Geometry>::value;\r
+};\r
+\r
+template <typename Geometry, typename Point, typename Tag>\r
+struct is_generic<Geometry, Point, Tag, point_tag>\r
+{\r
+ static const bool value = is_supported_by_generic<Geometry>::value;\r
+};\r
+\r
+template <typename Point1, typename Point2>\r
+struct is_generic<Point1, Point2, point_tag, point_tag>\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch {\r
+\r
+\r
+template <typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename geometry::tag<Geometry1>::type,\r
+ typename Tag2 = typename geometry::tag<Geometry2>::type,\r
+ int TopDim1 = geometry::topological_dimension<Geometry1>::value,\r
+ int TopDim2 = geometry::topological_dimension<Geometry2>::value,\r
+ bool IsGeneric = detail::relate::is_generic<Geometry1, Geometry2>::value\r
+>\r
+struct relate : not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct interruption_enabled\r
+{\r
+ static const bool value =\r
+ dispatch::relate<Geometry1, Geometry2>::interruption_enabled;\r
+};\r
+\r
+template <typename Geometry1,\r
+ typename Geometry2,\r
+ typename Result,\r
+ bool IsSequence = boost::mpl::is_sequence<Result>::value>\r
+struct result_handler_type\r
+ : not_implemented<Result>\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct result_handler_type<Geometry1, Geometry2, geometry::de9im::mask, false>\r
+{\r
+ typedef mask_handler\r
+ <\r
+ geometry::de9im::mask,\r
+ interruption_enabled\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::value\r
+ > type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Head, typename Tail>\r
+struct result_handler_type<Geometry1, Geometry2, boost::tuples::cons<Head, Tail>, false>\r
+{\r
+ typedef mask_handler\r
+ <\r
+ boost::tuples::cons<Head, Tail>,\r
+ interruption_enabled\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::value\r
+ > type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2,\r
+ char II, char IB, char IE,\r
+ char BI, char BB, char BE,\r
+ char EI, char EB, char EE>\r
+struct result_handler_type\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,\r
+ false\r
+ >\r
+{\r
+ typedef static_mask_handler\r
+ <\r
+ geometry::de9im::static_mask<II, IB, IE, BI, BB, BE, EI, EB, EE>,\r
+ interruption_enabled\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::value\r
+ > type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename StaticSequence>\r
+struct result_handler_type<Geometry1, Geometry2, StaticSequence, true>\r
+{\r
+ typedef static_mask_handler\r
+ <\r
+ StaticSequence,\r
+ interruption_enabled\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::value\r
+ > type;\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct relate\r
+{\r
+ template <typename Mask>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Mask const& mask)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ assert_dimension_equal<Geometry1, Geometry2>();\r
+\r
+ typename detail::relate::result_handler_type\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ Mask\r
+ >::type handler(mask);\r
+\r
+ dispatch::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, handler);\r
+\r
+ return handler.result();\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename Mask>\r
+ struct visitor : boost::static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ Mask const& m_mask;\r
+\r
+ visitor(Geometry2 const& geometry2, Mask const& mask)\r
+ : m_geometry2(geometry2), m_mask(mask) {}\r
+\r
+ template <typename Geometry1>\r
+ bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return relate<Geometry1, Geometry2>\r
+ ::apply(geometry1, m_geometry2, m_mask);\r
+ }\r
+ };\r
+\r
+ template <typename Mask>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Mask const& mask)\r
+ {\r
+ return boost::apply_visitor(visitor<Mask>(geometry2, mask), geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Mask>\r
+ struct visitor : boost::static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ Mask const& m_mask;\r
+\r
+ visitor(Geometry1 const& geometry1, Mask const& mask)\r
+ : m_geometry1(geometry1), m_mask(mask) {}\r
+\r
+ template <typename Geometry2>\r
+ bool operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return relate<Geometry1, Geometry2>\r
+ ::apply(m_geometry1, geometry2, m_mask);\r
+ }\r
+ };\r
+\r
+ template <typename Mask>\r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,\r
+ Mask const& mask)\r
+ {\r
+ return boost::apply_visitor(visitor<Mask>(geometry1, mask), geometry2);\r
+ }\r
+};\r
+\r
+template <\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct relate<\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+>\r
+{\r
+ template <typename Mask>\r
+ struct visitor : boost::static_visitor<bool>\r
+ {\r
+ Mask const& m_mask;\r
+\r
+ visitor(Mask const& mask)\r
+ : m_mask(mask) {}\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ bool operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return relate<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2, m_mask);\r
+ }\r
+ };\r
+\r
+ template <typename Mask>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,\r
+ Mask const& mask)\r
+ {\r
+ return boost::apply_visitor(visitor<Mask>(mask), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+/*!\r
+\brief Checks relation between a pair of geometries defined by a mask.\r
+\ingroup relate\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Mask An intersection model Mask type.\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param mask An intersection model mask object.\r
+\return true if the relation is compatible with the mask, false otherwise.\r
+\r
+\qbk{[include reference/algorithms/relate.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2, typename Mask>\r
+inline bool relate(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Mask const& mask)\r
+{\r
+ return resolve_variant::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, mask);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP\r
+\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch { namespace relate {\r
+\r
+// TODO: Integrate it with geometry::less?\r
+\r
+template <typename Point1,\r
+ typename Point2,\r
+ std::size_t I = 0,\r
+ std::size_t D = geometry::dimension<Point1>::value>\r
+struct less\r
+{\r
+ static inline bool apply(Point1 const& left, Point2 const& right)\r
+ {\r
+ typename geometry::coordinate_type<Point1>::type\r
+ cleft = geometry::get<I>(left);\r
+ typename geometry::coordinate_type<Point2>::type\r
+ cright = geometry::get<I>(right);\r
+\r
+ if ( geometry::math::equals(cleft, cright) )\r
+ {\r
+ return less<Point1, Point2, I + 1, D>::apply(left, right);\r
+ }\r
+ else\r
+ {\r
+ return cleft < cright;\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Point1, typename Point2, std::size_t D>\r
+struct less<Point1, Point2, D, D>\r
+{\r
+ static inline bool apply(Point1 const&, Point2 const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+}} // namespace detail_dispatch::relate\r
+\r
+#endif\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+struct less\r
+{\r
+ template <typename Point1, typename Point2>\r
+ inline bool operator()(Point1 const& point1, Point2 const& point2) const\r
+ {\r
+ return detail_dispatch::relate::less<Point1, Point2>::apply(point1, point2);\r
+ }\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range/size.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/topological_dimension.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+#include <boost/geometry/algorithms/detail/sub_range.hpp>\r
+#include <boost/geometry/algorithms/detail/single_geometry.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/turns.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>\r
+\r
+#include <boost/geometry/views/detail/normalized_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+// WARNING!\r
+// TODO: In the worst case calling this Pred in a loop for MultiLinestring/MultiPolygon may take O(NM)\r
+// Use the rtree in this case!\r
+\r
+// may be used to set IE and BE for a Linear geometry for which no turns were generated\r
+template <typename Geometry2, typename Result, typename BoundaryChecker, bool TransposeResult>\r
+class no_turns_la_linestring_pred\r
+{\r
+public:\r
+ no_turns_la_linestring_pred(Geometry2 const& geometry2,\r
+ Result & res,\r
+ BoundaryChecker const& boundary_checker)\r
+ : m_geometry2(geometry2)\r
+ , m_result(res)\r
+ , m_boundary_checker(boundary_checker)\r
+ , m_interrupt_flags(0)\r
+ {\r
+ if ( ! may_update<interior, interior, '1', TransposeResult>(m_result) )\r
+ {\r
+ m_interrupt_flags |= 1;\r
+ }\r
+\r
+ if ( ! may_update<interior, exterior, '1', TransposeResult>(m_result) )\r
+ {\r
+ m_interrupt_flags |= 2;\r
+ }\r
+\r
+ if ( ! may_update<boundary, interior, '0', TransposeResult>(m_result) )\r
+ {\r
+ m_interrupt_flags |= 4;\r
+ }\r
+\r
+ if ( ! may_update<boundary, exterior, '0', TransposeResult>(m_result) )\r
+ {\r
+ m_interrupt_flags |= 8;\r
+ }\r
+ }\r
+\r
+ template <typename Linestring>\r
+ bool operator()(Linestring const& linestring)\r
+ {\r
+ std::size_t const count = boost::size(linestring);\r
+ \r
+ // invalid input\r
+ if ( count < 2 )\r
+ {\r
+ // ignore\r
+ // TODO: throw an exception?\r
+ return true;\r
+ }\r
+\r
+ // if those flags are set nothing will change\r
+ if ( m_interrupt_flags == 0xF )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2);\r
+ //BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs");\r
+\r
+ if ( pig > 0 )\r
+ {\r
+ update<interior, interior, '1', TransposeResult>(m_result);\r
+ m_interrupt_flags |= 1;\r
+ }\r
+ else\r
+ {\r
+ update<interior, exterior, '1', TransposeResult>(m_result);\r
+ m_interrupt_flags |= 2;\r
+ }\r
+\r
+ // check if there is a boundary\r
+ if ( ( m_interrupt_flags & 0xC ) != 0xC // if wasn't already set\r
+ && ( m_boundary_checker.template\r
+ is_endpoint_boundary<boundary_front>(range::front(linestring))\r
+ || m_boundary_checker.template\r
+ is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )\r
+ {\r
+ if ( pig > 0 )\r
+ {\r
+ update<boundary, interior, '0', TransposeResult>(m_result);\r
+ m_interrupt_flags |= 4;\r
+ }\r
+ else\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(m_result);\r
+ m_interrupt_flags |= 8;\r
+ }\r
+ }\r
+\r
+ return m_interrupt_flags != 0xF\r
+ && ! m_result.interrupt;\r
+ }\r
+\r
+private:\r
+ Geometry2 const& m_geometry2;\r
+ Result & m_result;\r
+ BoundaryChecker const& m_boundary_checker;\r
+ unsigned m_interrupt_flags;\r
+};\r
+\r
+// may be used to set EI and EB for an Areal geometry for which no turns were generated\r
+template <typename Result, bool TransposeResult>\r
+class no_turns_la_areal_pred\r
+{\r
+public:\r
+ no_turns_la_areal_pred(Result & res)\r
+ : m_result(res)\r
+ , interrupt(! may_update<interior, exterior, '2', TransposeResult>(m_result)\r
+ && ! may_update<boundary, exterior, '1', TransposeResult>(m_result) )\r
+ {}\r
+\r
+ template <typename Areal>\r
+ bool operator()(Areal const& areal)\r
+ {\r
+ if ( interrupt )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // TODO:\r
+ // handle empty/invalid geometries in a different way than below?\r
+\r
+ typedef typename geometry::point_type<Areal>::type point_type;\r
+ point_type dummy;\r
+ bool const ok = boost::geometry::point_on_border(dummy, areal);\r
+\r
+ // TODO: for now ignore, later throw an exception?\r
+ if ( !ok )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ update<interior, exterior, '2', TransposeResult>(m_result);\r
+ update<boundary, exterior, '1', TransposeResult>(m_result);\r
+ \r
+ return false;\r
+ }\r
+\r
+private:\r
+ Result & m_result;\r
+ bool const interrupt;\r
+};\r
+\r
+// The implementation of an algorithm calculating relate() for L/A\r
+template <typename Geometry1, typename Geometry2, bool TransposeResult = false>\r
+struct linear_areal\r
+{\r
+ // check Linear / Areal\r
+ BOOST_STATIC_ASSERT(topological_dimension<Geometry1>::value == 1\r
+ && topological_dimension<Geometry2>::value == 2);\r
+\r
+ static const bool interruption_enabled = true;\r
+\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+\r
+ template <typename Geometry>\r
+ struct is_multi\r
+ : boost::is_base_of\r
+ <\r
+ multi_tag,\r
+ typename tag<Geometry>::type\r
+ >\r
+ {};\r
+\r
+ template <typename Geom1, typename Geom2>\r
+ struct multi_turn_info\r
+ : turns::get_turns<Geom1, Geom2>::turn_info\r
+ {\r
+ multi_turn_info() : priority(0) {}\r
+ int priority; // single-geometry sorting priority\r
+ };\r
+\r
+ template <typename Geom1, typename Geom2>\r
+ struct turn_info_type\r
+ : boost::mpl::if_c\r
+ <\r
+ is_multi<Geometry2>::value,\r
+ multi_turn_info<Geom1, Geom2>,\r
+ typename turns::get_turns<Geom1, Geom2>::turn_info\r
+ >\r
+ {};\r
+ \r
+ template <typename Result>\r
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)\r
+ {\r
+// TODO: If Areal geometry may have infinite size, change the following line:\r
+\r
+ // The result should be FFFFFFFFF\r
+ relate::set<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ // get and analyse turns\r
+ typedef typename turn_info_type<Geometry1, Geometry2>::type turn_type;\r
+ std::vector<turn_type> turns;\r
+\r
+ interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);\r
+\r
+ turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy);\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ boundary_checker<Geometry1> boundary_checker1(geometry1);\r
+ no_turns_la_linestring_pred\r
+ <\r
+ Geometry2,\r
+ Result,\r
+ boundary_checker<Geometry1>,\r
+ TransposeResult\r
+ > pred1(geometry2, result, boundary_checker1);\r
+ for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ no_turns_la_areal_pred<Result, !TransposeResult> pred2(result);\r
+ for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+ \r
+ if ( turns.empty() )\r
+ return;\r
+\r
+ // This is set here because in the case if empty Areal geometry were passed\r
+ // those shouldn't be set\r
+ relate::set<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ {\r
+ sort_dispatch(turns.begin(), turns.end(), is_multi<Geometry2>());\r
+\r
+ turns_analyser<turn_type> analyser;\r
+ analyse_each_turn(result, analyser,\r
+ turns.begin(), turns.end(),\r
+ geometry1, geometry2,\r
+ boundary_checker1);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+ }\r
+\r
+ // If 'c' (insersection_boundary) was not found we know that any Ls isn't equal to one of the Rings\r
+ if ( !interrupt_policy.is_boundary_found )\r
+ {\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result);\r
+ }\r
+ // Don't calculate it if it's required\r
+ else if ( may_update<exterior, boundary, '1', TransposeResult>(result) )\r
+ {\r
+// TODO: REVISE THIS CODE AND PROBABLY REWRITE SOME PARTS TO BE MORE HUMAN-READABLE\r
+// IN GENERAL IT ANALYSES THE RINGS OF AREAL GEOMETRY AND DETECTS THE ONES THAT\r
+// MAY OVERLAP THE INTERIOR OF LINEAR GEOMETRY (NO IPs OR NON-FAKE 'u' OPERATION)\r
+// NOTE: For one case std::sort may be called again to sort data by operations for data already sorted by ring index\r
+// In the worst case scenario the complexity will be O( NlogN + R*(N/R)log(N/R) )\r
+// So always should remain O(NlogN) -> for R==1 <-> 1(N/1)log(N/1), for R==N <-> N(N/N)log(N/N)\r
+// Some benchmarking should probably be done to check if only one std::sort should be used\r
+\r
+ // sort by multi_index and rind_index\r
+ std::sort(turns.begin(), turns.end(), less_ring());\r
+\r
+ typedef typename std::vector<turn_type>::iterator turn_iterator;\r
+\r
+ turn_iterator it = turns.begin();\r
+ segment_identifier * prev_seg_id_ptr = NULL;\r
+ // for each ring\r
+ for ( ; it != turns.end() ; )\r
+ {\r
+ // it's the next single geometry\r
+ if ( prev_seg_id_ptr == NULL\r
+ || prev_seg_id_ptr->multi_index != it->operations[1].seg_id.multi_index )\r
+ {\r
+ // if the first ring has no IPs\r
+ if ( it->operations[1].seg_id.ring_index > -1 )\r
+ {\r
+ // we can be sure that the exterior overlaps the boundary\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result); \r
+ break;\r
+ }\r
+ // if there was some previous ring\r
+ if ( prev_seg_id_ptr != NULL )\r
+ {\r
+ signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;\r
+ BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);\r
+ \r
+ // if one of the last rings of previous single geometry was ommited\r
+ if ( static_cast<std::size_t>(next_ring_index)\r
+ < geometry::num_interior_rings(\r
+ single_geometry(geometry2, *prev_seg_id_ptr)) )\r
+ {\r
+ // we can be sure that the exterior overlaps the boundary\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ // if it's the same single geometry\r
+ else /*if ( previous_multi_index == it->operations[1].seg_id.multi_index )*/\r
+ {\r
+ // and we jumped over one of the rings\r
+ if ( prev_seg_id_ptr != NULL // just in case\r
+ && prev_seg_id_ptr->ring_index + 1 < it->operations[1].seg_id.ring_index )\r
+ {\r
+ // we can be sure that the exterior overlaps the boundary\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result); \r
+ break;\r
+ }\r
+ }\r
+\r
+ prev_seg_id_ptr = boost::addressof(it->operations[1].seg_id);\r
+\r
+ // find the next ring first iterator and check if the analysis should be performed\r
+ has_boundary_intersection has_boundary_inters;\r
+ turn_iterator next = find_next_ring(it, turns.end(), has_boundary_inters);\r
+\r
+ // if there is no 1d overlap with the boundary\r
+ if ( !has_boundary_inters.result )\r
+ {\r
+ // we can be sure that the exterior overlaps the boundary\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result); \r
+ break;\r
+ }\r
+ // else there is 1d overlap with the boundary so we must analyse the boundary\r
+ else\r
+ {\r
+ // u, c\r
+ typedef turns::less<1, turns::less_op_areal_linear<1> > less;\r
+ std::sort(it, next, less());\r
+\r
+ // analyse\r
+ areal_boundary_analyser<turn_type> analyser;\r
+ for ( turn_iterator rit = it ; rit != next ; ++rit )\r
+ {\r
+ // if the analyser requests, break the search\r
+ if ( !analyser.apply(it, rit, next) )\r
+ break;\r
+ }\r
+\r
+ // if the boundary of Areal goes out of the Linear\r
+ if ( analyser.is_union_detected )\r
+ {\r
+ // we can be sure that the boundary of Areal overlaps the exterior of Linear\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result);\r
+ break;\r
+ }\r
+ }\r
+\r
+ it = next;\r
+ }\r
+\r
+ // if there was some previous ring\r
+ if ( prev_seg_id_ptr != NULL )\r
+ {\r
+ signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;\r
+ BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);\r
+\r
+ // if one of the last rings of previous single geometry was ommited\r
+ if ( static_cast<std::size_t>(next_ring_index)\r
+ < geometry::num_interior_rings(\r
+ single_geometry(geometry2, *prev_seg_id_ptr)) )\r
+ {\r
+ // we can be sure that the exterior overlaps the boundary\r
+ relate::set<exterior, boundary, '1', TransposeResult>(result);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ template <typename It, typename Pred, typename Comp>\r
+ static void for_each_equal_range(It first, It last, Pred pred, Comp comp)\r
+ {\r
+ if ( first == last )\r
+ return;\r
+\r
+ It first_equal = first;\r
+ It prev = first;\r
+ for ( ++first ; ; ++first, ++prev )\r
+ {\r
+ if ( first == last || !comp(*prev, *first) )\r
+ {\r
+ pred(first_equal, first);\r
+ first_equal = first;\r
+ }\r
+ \r
+ if ( first == last )\r
+ break;\r
+ }\r
+ }\r
+\r
+ struct same_ip\r
+ {\r
+ template <typename Turn>\r
+ bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ return left.operations[0].seg_id == right.operations[0].seg_id\r
+ && left.operations[0].fraction == right.operations[0].fraction;\r
+ }\r
+ };\r
+\r
+ struct same_ip_and_multi_index\r
+ {\r
+ template <typename Turn>\r
+ bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ return same_ip()(left, right)\r
+ && left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index;\r
+ }\r
+ };\r
+\r
+ template <typename OpToPriority>\r
+ struct set_turns_group_priority\r
+ {\r
+ template <typename TurnIt>\r
+ void operator()(TurnIt first, TurnIt last) const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(first != last);\r
+ static OpToPriority op_to_priority;\r
+ // find the operation with the least priority\r
+ int least_priority = op_to_priority(first->operations[0]);\r
+ for ( TurnIt it = first + 1 ; it != last ; ++it )\r
+ {\r
+ int priority = op_to_priority(it->operations[0]);\r
+ if ( priority < least_priority )\r
+ least_priority = priority;\r
+ }\r
+ // set the least priority for all turns of the group\r
+ for ( TurnIt it = first ; it != last ; ++it )\r
+ {\r
+ it->priority = least_priority;\r
+ }\r
+ }\r
+ };\r
+\r
+ template <typename SingleLess>\r
+ struct sort_turns_group\r
+ {\r
+ struct less\r
+ {\r
+ template <typename Turn>\r
+ bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ return left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index ?\r
+ SingleLess()(left, right) :\r
+ left.priority < right.priority;\r
+ }\r
+ };\r
+\r
+ template <typename TurnIt>\r
+ void operator()(TurnIt first, TurnIt last) const\r
+ {\r
+ std::sort(first, last, less());\r
+ }\r
+ };\r
+\r
+ template <typename TurnIt>\r
+ static void sort_dispatch(TurnIt first, TurnIt last, boost::true_type const& /*is_multi*/)\r
+ {\r
+ // sort turns by Linear seg_id, then by fraction, then by other multi_index\r
+ typedef turns::less<0, turns::less_other_multi_index<0> > less;\r
+ std::sort(first, last, less());\r
+\r
+ // For the same IP and multi_index - the same other's single geometry\r
+ // set priorities as the least operation found for the whole single geometry\r
+ // so e.g. single geometries containing 'u' will always be before those only containing 'i'\r
+ typedef turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;\r
+ for_each_equal_range(first, last,\r
+ set_turns_group_priority<op_to_int_xuic>(), // least operation in xuic order\r
+ same_ip_and_multi_index()); // other's multi_index\r
+\r
+ // When priorities for single geometries are set now sort turns for the same IP\r
+ // if multi_index is the same sort them according to the single-less\r
+ // else use priority of the whole single-geometry set earlier\r
+ typedef turns::less<0, turns::less_op_linear_areal_single<0> > single_less;\r
+ for_each_equal_range(first, last,\r
+ sort_turns_group<single_less>(),\r
+ same_ip());\r
+ }\r
+\r
+ template <typename TurnIt>\r
+ static void sort_dispatch(TurnIt first, TurnIt last, boost::false_type const& /*is_multi*/)\r
+ {\r
+ // sort turns by Linear seg_id, then by fraction, then\r
+ // for same ring id: x, u, i, c\r
+ // for different ring id: c, i, u, x\r
+ typedef turns::less<0, turns::less_op_linear_areal_single<0> > less;\r
+ std::sort(first, last, less());\r
+ }\r
+ \r
+\r
+ // interrupt policy which may be passed to get_turns to interrupt the analysis\r
+ // based on the info in the passed result/mask\r
+ template <typename Areal, typename Result>\r
+ class interrupt_policy_linear_areal\r
+ {\r
+ public:\r
+ static bool const enabled = true;\r
+\r
+ interrupt_policy_linear_areal(Areal const& areal, Result & result)\r
+ : m_result(result), m_areal(areal)\r
+ , is_boundary_found(false)\r
+ {}\r
+\r
+// TODO: since we update result for some operations here, we may not do it in the analyser!\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& turns)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+ \r
+ for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)\r
+ {\r
+ if ( it->operations[0].operation == overlay::operation_intersection )\r
+ {\r
+ bool const no_interior_rings\r
+ = geometry::num_interior_rings(\r
+ single_geometry(m_areal, it->operations[1].seg_id)) == 0;\r
+\r
+ // WARNING! THIS IS TRUE ONLY IF THE POLYGON IS SIMPLE!\r
+ // OR WITHOUT INTERIOR RINGS (AND OF COURSE VALID)\r
+ if ( no_interior_rings )\r
+ update<interior, interior, '1', TransposeResult>(m_result);\r
+ }\r
+ else if ( it->operations[0].operation == overlay::operation_continue )\r
+ {\r
+ update<interior, boundary, '1', TransposeResult>(m_result);\r
+ is_boundary_found = true;\r
+ }\r
+ else if ( ( it->operations[0].operation == overlay::operation_union\r
+ || it->operations[0].operation == overlay::operation_blocked )\r
+ && it->operations[0].position == overlay::position_middle )\r
+ {\r
+// TODO: here we could also check the boundaries and set BB at this point\r
+ update<interior, boundary, '0', TransposeResult>(m_result);\r
+ }\r
+ }\r
+\r
+ return m_result.interrupt;\r
+ }\r
+\r
+ private:\r
+ Result & m_result;\r
+ Areal const& m_areal;\r
+\r
+ public:\r
+ bool is_boundary_found;\r
+ };\r
+\r
+ // This analyser should be used like Input or SinglePass Iterator\r
+ // IMPORTANT! It should be called also for the end iterator - last\r
+ template <typename TurnInfo>\r
+ class turns_analyser\r
+ {\r
+ typedef typename TurnInfo::point_type turn_point_type;\r
+\r
+ static const std::size_t op_id = 0;\r
+ static const std::size_t other_op_id = 1;\r
+\r
+ public:\r
+ turns_analyser()\r
+ : m_previous_turn_ptr(NULL)\r
+ , m_previous_operation(overlay::operation_none)\r
+ , m_boundary_counter(0)\r
+ , m_interior_detected(false)\r
+ , m_first_interior_other_id_ptr(NULL)\r
+ , m_first_from_unknown(false)\r
+ , m_first_from_unknown_boundary_detected(false)\r
+ {}\r
+\r
+ template <typename Result,\r
+ typename TurnIt,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker>\r
+ void apply(Result & res, TurnIt it,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& other_geometry,\r
+ BoundaryChecker const& boundary_checker)\r
+ {\r
+ overlay::operation_type op = it->operations[op_id].operation;\r
+\r
+ if ( op != overlay::operation_union\r
+ && op != overlay::operation_intersection\r
+ && op != overlay::operation_blocked\r
+ && op != overlay::operation_continue ) // operation_boundary / operation_boundary_intersection\r
+ {\r
+ return;\r
+ }\r
+\r
+ segment_identifier const& seg_id = it->operations[op_id].seg_id;\r
+ segment_identifier const& other_id = it->operations[other_op_id].seg_id;\r
+\r
+ const bool first_in_range = m_seg_watcher.update(seg_id);\r
+\r
+ // TODO: should apply() for the post-last ip be called if first_in_range ?\r
+ // this would unify how last points in ranges are handled\r
+ // possibly replacing parts of the code below\r
+ // e.g. for is_multi and m_interior_detected\r
+\r
+ // handle possible exit\r
+ bool fake_enter_detected = false;\r
+ if ( m_exit_watcher.get_exit_operation() == overlay::operation_union )\r
+ {\r
+ // real exit point - may be multiple\r
+ // we know that we entered and now we exit\r
+ if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )\r
+ {\r
+ m_exit_watcher.reset_detected_exit();\r
+ \r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+\r
+ // next single geometry\r
+ if ( first_in_range && m_previous_turn_ptr )\r
+ {\r
+ // NOTE: similar code is in the post-last-ip-apply()\r
+ segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;\r
+\r
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(\r
+ range::back(sub_range(geometry, prev_seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the last point\r
+ if ( prev_back_b )\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+ }\r
+ // fake exit point, reset state\r
+ else if ( op == overlay::operation_intersection\r
+ || op == overlay::operation_continue ) // operation_boundary\r
+ {\r
+ m_exit_watcher.reset_detected_exit();\r
+ fake_enter_detected = true;\r
+ }\r
+ }\r
+ else if ( m_exit_watcher.get_exit_operation() == overlay::operation_blocked )\r
+ {\r
+ // ignore multiple BLOCKs for this same single geometry1\r
+ if ( op == overlay::operation_blocked\r
+ && seg_id.multi_index == m_previous_turn_ptr->operations[op_id].seg_id.multi_index )\r
+ {\r
+ return;\r
+ }\r
+\r
+ if ( ( op == overlay::operation_intersection\r
+ || op == overlay::operation_continue )\r
+ && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )\r
+ {\r
+ fake_enter_detected = true;\r
+ }\r
+\r
+ m_exit_watcher.reset_detected_exit();\r
+ }\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )\r
+ && m_first_from_unknown )\r
+ {\r
+ // For MultiPolygon many x/u operations may be generated as a first IP\r
+ // if for all turns x/u was generated and any of the Polygons doesn't contain the LineString\r
+ // then we know that the LineString is outside\r
+ // Similar with the u/u turns, if it was the first one it doesn't mean that the\r
+ // Linestring came from the exterior\r
+ if ( ( m_previous_operation == overlay::operation_blocked\r
+ && ( op != overlay::operation_blocked // operation different than block\r
+ || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry\r
+ || ( m_previous_operation == overlay::operation_union\r
+ && ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )\r
+ )\r
+ {\r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+ if ( m_first_from_unknown_boundary_detected )\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+\r
+ m_first_from_unknown = false;\r
+ m_first_from_unknown_boundary_detected = false;\r
+ }\r
+ }\r
+\r
+// NOTE: THE WHOLE m_interior_detected HANDLING IS HERE BECAUSE WE CAN'T EFFICIENTLY SORT TURNS (CORRECTLY)\r
+// BECAUSE THE SAME IP MAY BE REPRESENTED BY TWO SEGMENTS WITH DIFFERENT DISTANCES\r
+// IT WOULD REQUIRE THE CALCULATION OF MAX DISTANCE\r
+// TODO: WE COULD GET RID OF THE TEST IF THE DISTANCES WERE NORMALIZED\r
+\r
+// UPDATE: THEY SHOULD BE NORMALIZED NOW\r
+\r
+// TODO: THIS IS POTENTIALLY ERROREOUS!\r
+// THIS ALGORITHM DEPENDS ON SOME SPECIFIC SEQUENCE OF OPERATIONS\r
+// IT WOULD GIVE WRONG RESULTS E.G.\r
+// IN THE CASE OF SELF-TOUCHING POINT WHEN 'i' WOULD BE BEFORE 'u' \r
+\r
+ // handle the interior overlap\r
+ if ( m_interior_detected )\r
+ {\r
+ BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected");\r
+\r
+ // real interior overlap\r
+ if ( ! turn_on_the_same_ip<op_id>(*m_previous_turn_ptr, *it) )\r
+ {\r
+ update<interior, interior, '1', TransposeResult>(res);\r
+ m_interior_detected = false;\r
+\r
+ // new range detected - reset previous state and check the boundary\r
+ if ( first_in_range )\r
+ {\r
+ segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;\r
+\r
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(\r
+ range::back(sub_range(geometry, prev_seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the last point\r
+ if ( prev_back_b )\r
+ {\r
+ update<boundary, interior, '0', TransposeResult>(res);\r
+ }\r
+\r
+ // The exit_watcher is reset below\r
+ // m_exit_watcher.reset();\r
+ }\r
+ }\r
+ // fake interior overlap\r
+ else if ( op == overlay::operation_continue )\r
+ {\r
+ m_interior_detected = false;\r
+ }\r
+ else if ( op == overlay::operation_union )\r
+ {\r
+// TODO: this probably is not a good way of handling the interiors/enters\r
+// the solution similar to exit_watcher would be more robust\r
+// all enters should be kept and handled.\r
+// maybe integrate it with the exit_watcher -> enter_exit_watcher\r
+ if ( m_first_interior_other_id_ptr\r
+ && m_first_interior_other_id_ptr->multi_index == other_id.multi_index )\r
+ {\r
+ m_interior_detected = false;\r
+ }\r
+ }\r
+ }\r
+\r
+ // NOTE: If post-last-ip apply() was called this wouldn't be needed\r
+ if ( first_in_range )\r
+ {\r
+ m_exit_watcher.reset();\r
+ m_boundary_counter = 0;\r
+ m_first_from_unknown = false;\r
+ m_first_from_unknown_boundary_detected = false;\r
+ }\r
+\r
+ // i/u, c/u\r
+ if ( op == overlay::operation_intersection\r
+ || op == overlay::operation_continue ) // operation_boundary/operation_boundary_intersection\r
+ {\r
+ bool const first_point = first_in_range || m_first_from_unknown;\r
+ bool no_enters_detected = m_exit_watcher.is_outside();\r
+ m_exit_watcher.enter(*it);\r
+\r
+ if ( op == overlay::operation_intersection )\r
+ {\r
+ if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear )\r
+ --m_boundary_counter;\r
+\r
+ if ( m_boundary_counter == 0 )\r
+ {\r
+ // interiors overlaps\r
+ //update<interior, interior, '1', TransposeResult>(res);\r
+\r
+// TODO: think about the implementation of the more robust version\r
+// this way only the first enter will be handled\r
+ if ( !m_interior_detected )\r
+ {\r
+ // don't update now\r
+ // we might enter a boundary of some other ring on the same IP\r
+ m_interior_detected = true;\r
+ m_first_interior_other_id_ptr = boost::addressof(other_id);\r
+ }\r
+ }\r
+ }\r
+ else // operation_boundary\r
+ {\r
+ // don't add to the count for all met boundaries\r
+ // only if this is the "new" boundary\r
+ if ( first_point || !it->operations[op_id].is_collinear )\r
+ ++m_boundary_counter;\r
+\r
+ update<interior, boundary, '1', TransposeResult>(res);\r
+ }\r
+\r
+ bool const this_b\r
+ = is_ip_on_boundary<boundary_front>(it->point,\r
+ it->operations[op_id],\r
+ boundary_checker,\r
+ seg_id);\r
+ // going inside on boundary point\r
+ if ( this_b )\r
+ {\r
+ update<boundary, boundary, '0', TransposeResult>(res);\r
+ }\r
+ // going inside on non-boundary point\r
+ else\r
+ {\r
+ update<interior, boundary, '0', TransposeResult>(res);\r
+\r
+ // if we didn't enter in the past, we were outside\r
+ if ( no_enters_detected\r
+ && ! fake_enter_detected\r
+ && it->operations[op_id].position != overlay::position_front )\r
+ {\r
+// TODO: calculate_from_inside() is only needed if the current Linestring is not closed\r
+ bool const from_inside = first_point\r
+ && calculate_from_inside(geometry,\r
+ other_geometry,\r
+ *it);\r
+\r
+ if ( from_inside )\r
+ update<interior, interior, '1', TransposeResult>(res);\r
+ else\r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+\r
+ // if it's the first IP then the first point is outside\r
+ if ( first_point )\r
+ {\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(sub_range(geometry, seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the first point\r
+ if ( front_b )\r
+ {\r
+ if ( from_inside )\r
+ update<boundary, interior, '0', TransposeResult>(res);\r
+ else\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value ) )\r
+ {\r
+ m_first_from_unknown = false;\r
+ m_first_from_unknown_boundary_detected = false;\r
+ }\r
+ }\r
+ // u/u, x/u\r
+ else if ( op == overlay::operation_union || op == overlay::operation_blocked )\r
+ {\r
+ bool const op_blocked = op == overlay::operation_blocked;\r
+ bool const no_enters_detected = m_exit_watcher.is_outside()\r
+// TODO: is this condition ok?\r
+// TODO: move it into the exit_watcher?\r
+ && m_exit_watcher.get_exit_operation() == overlay::operation_none;\r
+ \r
+ if ( op == overlay::operation_union )\r
+ {\r
+ if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear )\r
+ --m_boundary_counter;\r
+ }\r
+ else // overlay::operation_blocked\r
+ {\r
+ m_boundary_counter = 0;\r
+ }\r
+\r
+ // we're inside, possibly going out right now\r
+ if ( ! no_enters_detected )\r
+ {\r
+ if ( op_blocked\r
+ && it->operations[op_id].position == overlay::position_back ) // ignore spikes!\r
+ {\r
+ // check if this is indeed the boundary point\r
+ // NOTE: is_ip_on_boundary<>() should be called here but the result will be the same\r
+ if ( is_endpoint_on_boundary<boundary_back>(it->point, boundary_checker) )\r
+ {\r
+ update<boundary, boundary, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+ // union, inside, but no exit -> collinear on self-intersection point\r
+ // not needed since we're already inside the boundary\r
+ /*else if ( !exit_detected )\r
+ {\r
+ update<interior, boundary, '0', TransposeResult>(res);\r
+ }*/\r
+ }\r
+ // we're outside or inside and this is the first turn\r
+ else\r
+ {\r
+ bool const this_b = is_ip_on_boundary<boundary_any>(it->point,\r
+ it->operations[op_id],\r
+ boundary_checker,\r
+ seg_id);\r
+ // if current IP is on boundary of the geometry\r
+ if ( this_b )\r
+ {\r
+ update<boundary, boundary, '0', TransposeResult>(res);\r
+ }\r
+ // if current IP is not on boundary of the geometry\r
+ else\r
+ {\r
+ update<interior, boundary, '0', TransposeResult>(res);\r
+ }\r
+\r
+ // TODO: very similar code is used in the handling of intersection\r
+ if ( it->operations[op_id].position != overlay::position_front )\r
+ {\r
+// TODO: calculate_from_inside() is only needed if the current Linestring is not closed\r
+ // NOTE: this is not enough for MultiPolygon and operation_blocked\r
+ // For LS/MultiPolygon multiple x/u turns may be generated\r
+ // the first checked Polygon may be the one which LS is outside for.\r
+ bool const first_point = first_in_range || m_first_from_unknown;\r
+ bool const first_from_inside = first_point\r
+ && calculate_from_inside(geometry,\r
+ other_geometry,\r
+ *it);\r
+ if ( first_from_inside )\r
+ {\r
+ update<interior, interior, '1', TransposeResult>(res);\r
+\r
+ // notify the exit_watcher that we started inside\r
+ m_exit_watcher.enter(*it);\r
+ // and reset unknown flags since we know that we started inside\r
+ m_first_from_unknown = false;\r
+ m_first_from_unknown_boundary_detected = false;\r
+ }\r
+ else\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )\r
+ /*&& ( op == overlay::operation_blocked\r
+ || op == overlay::operation_union )*/ ) // if we're here it's u or x\r
+ {\r
+ m_first_from_unknown = true;\r
+ }\r
+ else\r
+ {\r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+ }\r
+ }\r
+\r
+ // first IP on the last segment point - this means that the first point is outside or inside\r
+ if ( first_point && ( !this_b || op_blocked ) )\r
+ {\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(sub_range(geometry, seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the first point\r
+ if ( front_b )\r
+ {\r
+ if ( first_from_inside )\r
+ {\r
+ update<boundary, interior, '0', TransposeResult>(res);\r
+ }\r
+ else\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )\r
+ /*&& ( op == overlay::operation_blocked\r
+ || op == overlay::operation_union )*/ ) // if we're here it's u or x\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(m_first_from_unknown);\r
+ m_first_from_unknown_boundary_detected = true;\r
+ }\r
+ else\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // if we're going along a boundary, we exit only if the linestring was collinear\r
+ if ( m_boundary_counter == 0\r
+ || it->operations[op_id].is_collinear )\r
+ {\r
+ // notify the exit watcher about the possible exit\r
+ m_exit_watcher.exit(*it);\r
+ }\r
+ }\r
+\r
+ // store ref to previously analysed (valid) turn\r
+ m_previous_turn_ptr = boost::addressof(*it);\r
+ // and previously analysed (valid) operation\r
+ m_previous_operation = op;\r
+ }\r
+\r
+ // it == last\r
+ template <typename Result,\r
+ typename TurnIt,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker>\r
+ void apply(Result & res,\r
+ TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& /*other_geometry*/,\r
+ BoundaryChecker const& boundary_checker)\r
+ {\r
+ boost::ignore_unused(first, last);\r
+ //BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ // For MultiPolygon many x/u operations may be generated as a first IP\r
+ // if for all turns x/u was generated and any of the Polygons doesn't contain the LineString\r
+ // then we know that the LineString is outside\r
+ if ( BOOST_GEOMETRY_CONDITION( is_multi<OtherGeometry>::value )\r
+ && m_first_from_unknown )\r
+ {\r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+ if ( m_first_from_unknown_boundary_detected )\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+\r
+ // done below\r
+ //m_first_from_unknown = false;\r
+ //m_first_from_unknown_boundary_detected = false;\r
+ }\r
+\r
+ // here, the possible exit is the real one\r
+ // we know that we entered and now we exit\r
+ if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT\r
+ ||*/ m_previous_operation == overlay::operation_union\r
+ && !m_interior_detected )\r
+ {\r
+ // for sure\r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+\r
+ BOOST_GEOMETRY_ASSERT(first != last);\r
+ BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr);\r
+\r
+ segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;\r
+\r
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(\r
+ range::back(sub_range(geometry, prev_seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the last point\r
+ if ( prev_back_b )\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+ // we might enter some Areal and didn't go out,\r
+ else if ( m_previous_operation == overlay::operation_intersection\r
+ || m_interior_detected )\r
+ {\r
+ // just in case\r
+ update<interior, interior, '1', TransposeResult>(res);\r
+ m_interior_detected = false;\r
+\r
+ BOOST_GEOMETRY_ASSERT(first != last);\r
+ BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr);\r
+\r
+ segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;\r
+\r
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(\r
+ range::back(sub_range(geometry, prev_seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the last point\r
+ if ( prev_back_b )\r
+ {\r
+ update<boundary, interior, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+\r
+ // This condition may be false if the Linestring is lying on the Polygon's collinear spike\r
+ // if Polygon's spikes are not handled in get_turns() or relate() (they currently aren't)\r
+ //BOOST_GEOMETRY_ASSERT_MSG(m_previous_operation != overlay::operation_continue,\r
+ // "Unexpected operation! Probably the error in get_turns(L,A) or relate(L,A)");\r
+ // Currently one c/c turn is generated for the exit\r
+ // when a Linestring is going out on a collinear spike\r
+ // When a Linestring is going in on a collinear spike\r
+ // the turn is not generated for the entry\r
+ // So assume it's the former\r
+ if ( m_previous_operation == overlay::operation_continue )\r
+ {\r
+ update<interior, exterior, '1', TransposeResult>(res);\r
+\r
+ segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;\r
+\r
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(\r
+ range::back(sub_range(geometry, prev_seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the last point\r
+ if ( prev_back_b )\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(res);\r
+ }\r
+ }\r
+\r
+ // Reset exit watcher before the analysis of the next Linestring\r
+ m_exit_watcher.reset();\r
+ m_boundary_counter = 0;\r
+ m_first_from_unknown = false;\r
+ m_first_from_unknown_boundary_detected = false;\r
+ }\r
+\r
+ // check if the passed turn's segment of Linear geometry arrived\r
+ // from the inside or the outside of the Areal geometry\r
+ template <typename Turn>\r
+ static inline bool calculate_from_inside(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Turn const& turn)\r
+ {\r
+ typedef typename cs_tag<typename Turn::point_type>::type cs_tag;\r
+\r
+ if ( turn.operations[op_id].position == overlay::position_front )\r
+ return false;\r
+\r
+ typename sub_range_return_type<Geometry1 const>::type\r
+ range1 = sub_range(geometry1, turn.operations[op_id].seg_id);\r
+ \r
+ typedef detail::normalized_view<Geometry2 const> const range2_type;\r
+ typedef typename boost::range_iterator<range2_type>::type range2_iterator;\r
+ range2_type range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));\r
+ \r
+ BOOST_GEOMETRY_ASSERT(boost::size(range1));\r
+ std::size_t const s2 = boost::size(range2);\r
+ BOOST_GEOMETRY_ASSERT(s2 > 2);\r
+ std::size_t const seg_count2 = s2 - 1;\r
+\r
+ std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);\r
+ std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);\r
+\r
+ BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));\r
+ BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);\r
+\r
+ point1_type const& pi = range::at(range1, p_seg_ij);\r
+ point2_type const& qi = range::at(range2, q_seg_ij);\r
+ point2_type const& qj = range::at(range2, q_seg_ij + 1);\r
+ point1_type qi_conv;\r
+ geometry::convert(qi, qi_conv);\r
+ bool const is_ip_qj = equals::equals_point_point(turn.point, qj);\r
+// TODO: test this!\r
+// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));\r
+// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));\r
+ point1_type new_pj;\r
+ geometry::convert(turn.point, new_pj);\r
+\r
+ if ( is_ip_qj )\r
+ {\r
+ std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2;\r
+// TODO: the following function should return immediately, however the worst case complexity is O(N)\r
+// It would be good to replace it with some O(1) mechanism\r
+ range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),\r
+ range::pos(range2, q_seg_jk),\r
+ boost::end(range2));\r
+\r
+ // Will this sequence of points be always correct?\r
+ overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it);\r
+\r
+ return calculate_from_inside_sides(side_calc);\r
+ }\r
+ else\r
+ {\r
+ point1_type new_qj;\r
+ geometry::convert(turn.point, new_qj);\r
+\r
+ overlay::side_calculator<cs_tag, point1_type, point2_type> side_calc(qi_conv, new_pj, pi, qi, new_qj, qj);\r
+\r
+ return calculate_from_inside_sides(side_calc);\r
+ }\r
+ }\r
+\r
+ template <typename It>\r
+ static inline It find_next_non_duplicated(It first, It current, It last)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( current != last );\r
+\r
+ It it = current;\r
+\r
+ for ( ++it ; it != last ; ++it )\r
+ {\r
+ if ( !equals::equals_point_point(*current, *it) )\r
+ return it;\r
+ }\r
+\r
+ // if not found start from the beginning\r
+ for ( it = first ; it != current ; ++it )\r
+ {\r
+ if ( !equals::equals_point_point(*current, *it) )\r
+ return it;\r
+ }\r
+\r
+ return current;\r
+ }\r
+\r
+ // calculate inside or outside based on side_calc\r
+ // this is simplified version of a check from equal<>\r
+ template <typename SideCalc>\r
+ static inline bool calculate_from_inside_sides(SideCalc const& side_calc)\r
+ {\r
+ int const side_pk_p = side_calc.pk_wrt_p1();\r
+ int const side_qk_p = side_calc.qk_wrt_p1();\r
+ // If they turn to same side (not opposite sides)\r
+ if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p))\r
+ {\r
+ int const side_pk_q2 = side_calc.pk_wrt_q2();\r
+ return side_pk_q2 == -1;\r
+ }\r
+ else\r
+ {\r
+ return side_pk_p == -1;\r
+ }\r
+ }\r
+\r
+ private:\r
+ exit_watcher<TurnInfo, op_id> m_exit_watcher;\r
+ segment_watcher<same_single> m_seg_watcher;\r
+ TurnInfo * m_previous_turn_ptr;\r
+ overlay::operation_type m_previous_operation;\r
+ unsigned m_boundary_counter;\r
+ bool m_interior_detected;\r
+ const segment_identifier * m_first_interior_other_id_ptr;\r
+ bool m_first_from_unknown;\r
+ bool m_first_from_unknown_boundary_detected;\r
+ };\r
+\r
+ // call analyser.apply() for each turn in range\r
+ // IMPORTANT! The analyser is also called for the end iterator - last\r
+ template <typename Result,\r
+ typename TurnIt,\r
+ typename Analyser,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker>\r
+ static inline void analyse_each_turn(Result & res,\r
+ Analyser & analyser,\r
+ TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& other_geometry,\r
+ BoundaryChecker const& boundary_checker)\r
+ {\r
+ if ( first == last )\r
+ return;\r
+\r
+ for ( TurnIt it = first ; it != last ; ++it )\r
+ {\r
+ analyser.apply(res, it,\r
+ geometry, other_geometry,\r
+ boundary_checker);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )\r
+ return;\r
+ }\r
+\r
+ analyser.apply(res, first, last,\r
+ geometry, other_geometry,\r
+ boundary_checker);\r
+ }\r
+\r
+ // less comparator comparing multi_index then ring_index\r
+ // may be used to sort turns by ring\r
+ struct less_ring\r
+ {\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ return left.operations[1].seg_id.multi_index < right.operations[1].seg_id.multi_index\r
+ || ( left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index\r
+ && left.operations[1].seg_id.ring_index < right.operations[1].seg_id.ring_index );\r
+ }\r
+ };\r
+\r
+ // policy/functor checking if a turn's operation is operation_continue\r
+ struct has_boundary_intersection\r
+ {\r
+ has_boundary_intersection()\r
+ : result(false) {}\r
+\r
+ template <typename Turn>\r
+ inline void operator()(Turn const& turn)\r
+ {\r
+ if ( turn.operations[1].operation == overlay::operation_continue )\r
+ result = true;\r
+ }\r
+\r
+ bool result;\r
+ };\r
+\r
+ // iterate through the range and search for the different multi_index or ring_index\r
+ // also call fun for each turn in the current range\r
+ template <typename It, typename Fun>\r
+ static inline It find_next_ring(It first, It last, Fun & fun)\r
+ {\r
+ if ( first == last )\r
+ return last;\r
+\r
+ signed_size_type const multi_index = first->operations[1].seg_id.multi_index;\r
+ signed_size_type const ring_index = first->operations[1].seg_id.ring_index;\r
+\r
+ fun(*first);\r
+ ++first;\r
+\r
+ for ( ; first != last ; ++first )\r
+ {\r
+ if ( multi_index != first->operations[1].seg_id.multi_index\r
+ || ring_index != first->operations[1].seg_id.ring_index )\r
+ {\r
+ return first;\r
+ }\r
+\r
+ fun(*first);\r
+ }\r
+\r
+ return last;\r
+ }\r
+\r
+ // analyser which called for turns sorted by seg/distance/operation\r
+ // checks if the boundary of Areal geometry really got out\r
+ // into the exterior of Linear geometry\r
+ template <typename TurnInfo>\r
+ class areal_boundary_analyser\r
+ {\r
+ public:\r
+ areal_boundary_analyser()\r
+ : is_union_detected(false)\r
+ , m_previous_turn_ptr(NULL)\r
+ {}\r
+\r
+ template <typename TurnIt>\r
+ bool apply(TurnIt /*first*/, TurnIt it, TurnIt last)\r
+ {\r
+ overlay::operation_type op = it->operations[1].operation;\r
+\r
+ if ( it != last )\r
+ {\r
+ if ( op != overlay::operation_union\r
+ && op != overlay::operation_continue )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if ( is_union_detected )\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL);\r
+ if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point) )\r
+ {\r
+ // break\r
+ return false;\r
+ }\r
+ else if ( op == overlay::operation_continue ) // operation_boundary\r
+ {\r
+ is_union_detected = false;\r
+ }\r
+ }\r
+\r
+ if ( op == overlay::operation_union )\r
+ {\r
+ is_union_detected = true;\r
+ m_previous_turn_ptr = boost::addressof(*it);\r
+ }\r
+\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ return false;\r
+ } \r
+ }\r
+\r
+ bool is_union_detected;\r
+\r
+ private:\r
+ const TurnInfo * m_previous_turn_ptr;\r
+ };\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct areal_linear\r
+{\r
+ typedef linear_areal<Geometry2, Geometry1, true> linear_areal_type;\r
+\r
+ static const bool interruption_enabled = linear_areal_type::interruption_enabled;\r
+\r
+ template <typename Result>\r
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)\r
+ {\r
+ linear_areal_type::apply(geometry2, geometry1, result);\r
+ }\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range/size.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/sub_range.hpp>\r
+#include <boost/geometry/algorithms/detail/single_geometry.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/result.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/turns.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+template <typename Result, typename BoundaryChecker, bool TransposeResult>\r
+class disjoint_linestring_pred\r
+{\r
+public:\r
+ disjoint_linestring_pred(Result & res,\r
+ BoundaryChecker const& boundary_checker)\r
+ : m_result(res)\r
+ , m_boundary_checker(boundary_checker)\r
+ , m_flags(0)\r
+ {\r
+ if ( ! may_update<interior, exterior, '1', TransposeResult>(m_result) )\r
+ {\r
+ m_flags |= 1;\r
+ }\r
+ if ( ! may_update<boundary, exterior, '0', TransposeResult>(m_result) )\r
+ {\r
+ m_flags |= 2;\r
+ }\r
+ }\r
+\r
+ template <typename Linestring>\r
+ bool operator()(Linestring const& linestring)\r
+ {\r
+ if ( m_flags == 3 )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ std::size_t const count = boost::size(linestring);\r
+ \r
+ // invalid input\r
+ if ( count < 2 )\r
+ {\r
+ // ignore\r
+ // TODO: throw an exception?\r
+ return true;\r
+ }\r
+\r
+ // point-like linestring\r
+ if ( count == 2\r
+ && equals::equals_point_point(range::front(linestring),\r
+ range::back(linestring)) )\r
+ {\r
+ update<interior, exterior, '0', TransposeResult>(m_result);\r
+ }\r
+ else\r
+ {\r
+ update<interior, exterior, '1', TransposeResult>(m_result);\r
+ m_flags |= 1;\r
+\r
+ // check if there is a boundary\r
+ if ( m_flags < 2\r
+ && ( m_boundary_checker.template\r
+ is_endpoint_boundary<boundary_front>(range::front(linestring))\r
+ || m_boundary_checker.template\r
+ is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )\r
+ {\r
+ update<boundary, exterior, '0', TransposeResult>(m_result);\r
+ m_flags |= 2;\r
+ }\r
+ }\r
+\r
+ return m_flags != 3\r
+ && ! m_result.interrupt;\r
+ }\r
+\r
+private:\r
+ Result & m_result;\r
+ BoundaryChecker const& m_boundary_checker;\r
+ unsigned m_flags;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct linear_linear\r
+{\r
+ static const bool interruption_enabled = true;\r
+\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+\r
+ template <typename Result>\r
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result)\r
+ {\r
+ // The result should be FFFFFFFFF\r
+ relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ // get and analyse turns\r
+ typedef typename turns::get_turns<Geometry1, Geometry2>::turn_info turn_type;\r
+ std::vector<turn_type> turns;\r
+\r
+ interrupt_policy_linear_linear<Result> interrupt_policy(result);\r
+\r
+ turns::get_turns\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ detail::get_turns::get_turn_info_type<Geometry1, Geometry2, turns::assign_policy<true> >\r
+ >::apply(turns, geometry1, geometry2, interrupt_policy);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ boundary_checker<Geometry1> boundary_checker1(geometry1);\r
+ disjoint_linestring_pred<Result, boundary_checker<Geometry1>, false> pred1(result, boundary_checker1);\r
+ for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+\r
+ boundary_checker<Geometry2> boundary_checker2(geometry2);\r
+ disjoint_linestring_pred<Result, boundary_checker<Geometry2>, true> pred2(result, boundary_checker2);\r
+ for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+ \r
+ if ( turns.empty() )\r
+ return;\r
+\r
+ // TODO: turns must be sorted and followed only if it's possible to go out and in on the same point\r
+ // for linear geometries union operation must be detected which I guess would be quite often\r
+\r
+ if ( may_update<interior, interior, '1'>(result)\r
+ || may_update<interior, boundary, '0'>(result)\r
+ || may_update<interior, exterior, '1'>(result)\r
+ || may_update<boundary, interior, '0'>(result)\r
+ || may_update<boundary, boundary, '0'>(result)\r
+ || may_update<boundary, exterior, '0'>(result) )\r
+ {\r
+ typedef turns::less<0, turns::less_op_linear_linear<0> > less;\r
+ std::sort(turns.begin(), turns.end(), less());\r
+\r
+ turns_analyser<turn_type, 0> analyser;\r
+ analyse_each_turn(result, analyser,\r
+ turns.begin(), turns.end(),\r
+ geometry1, geometry2,\r
+ boundary_checker1, boundary_checker2);\r
+ }\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )\r
+ return;\r
+ \r
+ if ( may_update<interior, interior, '1', true>(result)\r
+ || may_update<interior, boundary, '0', true>(result)\r
+ || may_update<interior, exterior, '1', true>(result)\r
+ || may_update<boundary, interior, '0', true>(result)\r
+ || may_update<boundary, boundary, '0', true>(result)\r
+ || may_update<boundary, exterior, '0', true>(result) )\r
+ {\r
+ typedef turns::less<1, turns::less_op_linear_linear<1> > less;\r
+ std::sort(turns.begin(), turns.end(), less());\r
+\r
+ turns_analyser<turn_type, 1> analyser;\r
+ analyse_each_turn(result, analyser,\r
+ turns.begin(), turns.end(),\r
+ geometry2, geometry1,\r
+ boundary_checker2, boundary_checker1);\r
+ }\r
+ }\r
+\r
+ template <typename Result>\r
+ class interrupt_policy_linear_linear\r
+ {\r
+ public:\r
+ static bool const enabled = true;\r
+\r
+ explicit interrupt_policy_linear_linear(Result & result)\r
+ : m_result(result)\r
+ {}\r
+\r
+// TODO: since we update result for some operations here, we may not do it in the analyser!\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& turns)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+ \r
+ for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)\r
+ {\r
+ if ( it->operations[0].operation == overlay::operation_intersection\r
+ || it->operations[1].operation == overlay::operation_intersection )\r
+ {\r
+ update<interior, interior, '1'>(m_result);\r
+ }\r
+ else if ( ( it->operations[0].operation == overlay::operation_union\r
+ || it->operations[0].operation == overlay::operation_blocked\r
+ || it->operations[1].operation == overlay::operation_union\r
+ || it->operations[1].operation == overlay::operation_blocked )\r
+ && it->operations[0].position == overlay::position_middle\r
+ && it->operations[1].position == overlay::position_middle )\r
+ {\r
+// TODO: here we could also check the boundaries and set IB,BI,BB at this point\r
+ update<interior, interior, '0'>(m_result);\r
+ }\r
+ }\r
+\r
+ return m_result.interrupt;\r
+ }\r
+\r
+ private:\r
+ Result & m_result;\r
+ };\r
+\r
+ // This analyser should be used like Input or SinglePass Iterator\r
+ template <typename TurnInfo, std::size_t OpId>\r
+ class turns_analyser\r
+ {\r
+ typedef typename TurnInfo::point_type turn_point_type;\r
+\r
+ static const std::size_t op_id = OpId;\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+ static const bool transpose_result = OpId != 0;\r
+\r
+ public:\r
+ turns_analyser()\r
+ : m_previous_turn_ptr(NULL)\r
+ , m_previous_operation(overlay::operation_none)\r
+ , m_degenerated_turn_ptr(NULL)\r
+ , m_collinear_spike_exit(false)\r
+ {}\r
+\r
+ template <typename Result,\r
+ typename TurnIt,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker,\r
+ typename OtherBoundaryChecker>\r
+ void apply(Result & res, TurnIt it,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& other_geometry,\r
+ BoundaryChecker const& boundary_checker,\r
+ OtherBoundaryChecker const& other_boundary_checker)\r
+ {\r
+ overlay::operation_type const op = it->operations[op_id].operation;\r
+\r
+ segment_identifier const& seg_id = it->operations[op_id].seg_id;\r
+ segment_identifier const& other_id = it->operations[other_op_id].seg_id;\r
+\r
+ bool const first_in_range = m_seg_watcher.update(seg_id);\r
+\r
+ if ( op != overlay::operation_union\r
+ && op != overlay::operation_intersection\r
+ && op != overlay::operation_blocked )\r
+ {\r
+ // degenerated turn\r
+ if ( op == overlay::operation_continue\r
+ && it->method == overlay::method_none\r
+ && m_exit_watcher.is_outside(*it) \r
+ /*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none \r
+ || ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )*/ )\r
+ {\r
+ // TODO: rewrite the above condition\r
+\r
+ // WARNING! For spikes the above condition may be TRUE\r
+ // When degenerated turns are be marked in a different way than c,c/c\r
+ // different condition will be checked\r
+\r
+ handle_degenerated(res, *it,\r
+ geometry, other_geometry,\r
+ boundary_checker, other_boundary_checker,\r
+ first_in_range);\r
+\r
+ // TODO: not elegant solution! should be rewritten.\r
+ if ( it->operations[op_id].position == overlay::position_back )\r
+ {\r
+ m_previous_operation = overlay::operation_blocked;\r
+ m_exit_watcher.reset_detected_exit();\r
+ }\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+ // reset\r
+ m_degenerated_turn_ptr = NULL;\r
+\r
+ // handle possible exit\r
+ bool fake_enter_detected = false;\r
+ if ( m_exit_watcher.get_exit_operation() == overlay::operation_union )\r
+ {\r
+ // real exit point - may be multiple\r
+ // we know that we entered and now we exit\r
+ if ( ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )\r
+ {\r
+ m_exit_watcher.reset_detected_exit();\r
+ \r
+ // not the last IP\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+ }\r
+ // fake exit point, reset state\r
+ else if ( op == overlay::operation_intersection )\r
+ {\r
+ m_exit_watcher.reset_detected_exit();\r
+ fake_enter_detected = true;\r
+ }\r
+ }\r
+ else if ( m_exit_watcher.get_exit_operation() == overlay::operation_blocked )\r
+ {\r
+ // ignore multiple BLOCKs\r
+ if ( op == overlay::operation_blocked )\r
+ return;\r
+\r
+ if ( op == overlay::operation_intersection\r
+ && turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )\r
+ {\r
+ fake_enter_detected = true;\r
+ }\r
+\r
+ m_exit_watcher.reset_detected_exit();\r
+ }\r
+\r
+ // i/i, i/x, i/u\r
+ if ( op == overlay::operation_intersection )\r
+ {\r
+ bool const was_outside = m_exit_watcher.is_outside();\r
+ m_exit_watcher.enter(*it);\r
+\r
+ // interiors overlaps\r
+ update<interior, interior, '1', transpose_result>(res);\r
+\r
+ bool const this_b = it->operations[op_id].position == overlay::position_front // ignore spikes!\r
+ && is_ip_on_boundary<boundary_front>(it->point,\r
+ it->operations[op_id],\r
+ boundary_checker,\r
+ seg_id);\r
+\r
+ // going inside on boundary point\r
+ // may be front only\r
+ if ( this_b )\r
+ {\r
+ // may be front and back\r
+ bool const other_b = is_ip_on_boundary<boundary_any>(it->point,\r
+ it->operations[other_op_id],\r
+ other_boundary_checker,\r
+ other_id);\r
+\r
+ // it's also the boundary of the other geometry\r
+ if ( other_b )\r
+ {\r
+ update<boundary, boundary, '0', transpose_result>(res);\r
+ }\r
+ else\r
+ {\r
+ update<boundary, interior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ // going inside on non-boundary point\r
+ else\r
+ {\r
+ // if we didn't enter in the past, we were outside\r
+ if ( was_outside\r
+ && ! fake_enter_detected\r
+ && it->operations[op_id].position != overlay::position_front\r
+ && ! m_collinear_spike_exit )\r
+ {\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+\r
+ // if it's the first IP then the first point is outside\r
+ if ( first_in_range )\r
+ {\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(sub_range(geometry, seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the first point\r
+ if ( front_b )\r
+ {\r
+ update<boundary, exterior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ m_collinear_spike_exit = false;\r
+ }\r
+ // u/i, u/u, u/x, x/i, x/u, x/x\r
+ else if ( op == overlay::operation_union || op == overlay::operation_blocked )\r
+ {\r
+ // TODO: is exit watcher still needed?\r
+ // couldn't is_collinear and some going inside counter be used instead?\r
+\r
+ bool const is_collinear = it->operations[op_id].is_collinear;\r
+ bool const was_outside = m_exit_watcher.is_outside()\r
+ && m_exit_watcher.get_exit_operation() == overlay::operation_none;\r
+// TODO: move the above condition into the exit_watcher?\r
+\r
+ // to exit we must be currently inside and the current segment must be collinear\r
+ if ( !was_outside && is_collinear )\r
+ {\r
+ m_exit_watcher.exit(*it, false);\r
+ // if the position is not set to back it must be a spike\r
+ if ( it->operations[op_id].position != overlay::position_back )\r
+ {\r
+ m_collinear_spike_exit = true;\r
+ }\r
+ }\r
+\r
+ bool const op_blocked = op == overlay::operation_blocked;\r
+\r
+ // we're inside and going out from inside\r
+ // possibly going out right now\r
+ if ( ! was_outside && is_collinear )\r
+ {\r
+ if ( op_blocked\r
+ && it->operations[op_id].position == overlay::position_back ) // ignore spikes!\r
+ {\r
+ // check if this is indeed the boundary point\r
+ // NOTE: is_ip_on_boundary<>() should be called here but the result will be the same\r
+ if ( is_endpoint_on_boundary<boundary_back>(it->point, boundary_checker) )\r
+ {\r
+ // may be front and back\r
+ bool const other_b = is_ip_on_boundary<boundary_any>(it->point,\r
+ it->operations[other_op_id],\r
+ other_boundary_checker,\r
+ other_id);\r
+ // it's also the boundary of the other geometry\r
+ if ( other_b )\r
+ {\r
+ update<boundary, boundary, '0', transpose_result>(res);\r
+ }\r
+ else\r
+ {\r
+ update<boundary, interior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ // we're outside or intersects some segment from the outside\r
+ else\r
+ {\r
+ // if we are truly outside\r
+ if ( was_outside\r
+ && it->operations[op_id].position != overlay::position_front\r
+ && ! m_collinear_spike_exit\r
+ /*&& !is_collinear*/ )\r
+ {\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+ }\r
+\r
+ // boundaries don't overlap - just an optimization\r
+ if ( it->method == overlay::method_crosses )\r
+ {\r
+ // the L1 is going from one side of the L2 to the other through the point\r
+ update<interior, interior, '0', transpose_result>(res);\r
+\r
+ // it's the first point in range\r
+ if ( first_in_range )\r
+ {\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(sub_range(geometry, seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the first point\r
+ if ( front_b )\r
+ {\r
+ update<boundary, exterior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ }\r
+ // method other than crosses, check more conditions\r
+ else\r
+ {\r
+ bool const this_b = is_ip_on_boundary<boundary_any>(it->point,\r
+ it->operations[op_id],\r
+ boundary_checker,\r
+ seg_id);\r
+\r
+ bool const other_b = is_ip_on_boundary<boundary_any>(it->point,\r
+ it->operations[other_op_id],\r
+ other_boundary_checker,\r
+ other_id);\r
+ \r
+ // if current IP is on boundary of the geometry\r
+ if ( this_b )\r
+ {\r
+ // it's also the boundary of the other geometry\r
+ if ( other_b )\r
+ {\r
+ update<boundary, boundary, '0', transpose_result>(res);\r
+ }\r
+ else\r
+ {\r
+ update<boundary, interior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ // if current IP is not on boundary of the geometry\r
+ else\r
+ {\r
+ // it's also the boundary of the other geometry\r
+ if ( other_b )\r
+ {\r
+ update<interior, boundary, '0', transpose_result>(res);\r
+ }\r
+ else\r
+ {\r
+ update<interior, interior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+\r
+ // first IP on the last segment point - this means that the first point is outside\r
+ if ( first_in_range\r
+ && ( !this_b || op_blocked )\r
+ && was_outside\r
+ && it->operations[op_id].position != overlay::position_front\r
+ && ! m_collinear_spike_exit\r
+ /*&& !is_collinear*/ )\r
+ {\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(sub_range(geometry, seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the first point\r
+ if ( front_b )\r
+ {\r
+ update<boundary, exterior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+\r
+ // store ref to previously analysed (valid) turn\r
+ m_previous_turn_ptr = boost::addressof(*it);\r
+ // and previously analysed (valid) operation\r
+ m_previous_operation = op;\r
+ }\r
+\r
+ // Called for last\r
+ template <typename Result,\r
+ typename TurnIt,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker,\r
+ typename OtherBoundaryChecker>\r
+ void apply(Result & res,\r
+ TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& /*other_geometry*/,\r
+ BoundaryChecker const& boundary_checker,\r
+ OtherBoundaryChecker const& /*other_boundary_checker*/)\r
+ {\r
+ boost::ignore_unused(first, last);\r
+ //BOOST_GEOMETRY_ASSERT( first != last );\r
+\r
+ // here, the possible exit is the real one\r
+ // we know that we entered and now we exit\r
+ if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT\r
+ ||*/ m_previous_operation == overlay::operation_union\r
+ || m_degenerated_turn_ptr )\r
+ {\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+\r
+ BOOST_GEOMETRY_ASSERT(first != last);\r
+\r
+ const TurnInfo * turn_ptr = NULL;\r
+ if ( m_degenerated_turn_ptr )\r
+ turn_ptr = m_degenerated_turn_ptr;\r
+ else if ( m_previous_turn_ptr )\r
+ turn_ptr = m_previous_turn_ptr;\r
+ \r
+ if ( turn_ptr )\r
+ {\r
+ segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id;\r
+\r
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id)));\r
+ bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(\r
+ range::back(sub_range(geometry, prev_seg_id)),\r
+ boundary_checker);\r
+\r
+ // if there is a boundary on the last point\r
+ if ( prev_back_b )\r
+ {\r
+ update<boundary, exterior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ }\r
+\r
+ // Just in case,\r
+ // reset exit watcher before the analysis of the next Linestring\r
+ // note that if there are some enters stored there may be some error above\r
+ m_exit_watcher.reset();\r
+\r
+ m_previous_turn_ptr = NULL;\r
+ m_previous_operation = overlay::operation_none;\r
+ m_degenerated_turn_ptr = NULL;\r
+\r
+ // actually if this is set to true here there is some error\r
+ // in get_turns_ll or relate_ll, an assert could be checked here\r
+ m_collinear_spike_exit = false;\r
+ }\r
+\r
+ template <typename Result,\r
+ typename Turn,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker,\r
+ typename OtherBoundaryChecker>\r
+ void handle_degenerated(Result & res,\r
+ Turn const& turn,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& other_geometry,\r
+ BoundaryChecker const& boundary_checker,\r
+ OtherBoundaryChecker const& /*other_boundary_checker*/,\r
+ bool first_in_range)\r
+ {\r
+ typename detail::single_geometry_return_type<Geometry const>::type\r
+ ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id);\r
+ typename detail::single_geometry_return_type<OtherGeometry const>::type\r
+ ls2_ref = detail::single_geometry(other_geometry, turn.operations[other_op_id].seg_id);\r
+\r
+ // only one of those should be true:\r
+\r
+ if ( turn.operations[op_id].position == overlay::position_front )\r
+ {\r
+ // valid, point-sized\r
+ if ( boost::size(ls2_ref) == 2 )\r
+ {\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(turn.point, boundary_checker);\r
+\r
+ if ( front_b )\r
+ {\r
+ update<boundary, interior, '0', transpose_result>(res);\r
+ }\r
+ else\r
+ {\r
+ update<interior, interior, '0', transpose_result>(res);\r
+ }\r
+\r
+ // operation 'c' should be last for the same IP so we know that the next point won't be the same\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+\r
+ m_degenerated_turn_ptr = boost::addressof(turn);\r
+ }\r
+ }\r
+ else if ( turn.operations[op_id].position == overlay::position_back )\r
+ {\r
+ // valid, point-sized\r
+ if ( boost::size(ls2_ref) == 2 )\r
+ {\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+\r
+ bool const back_b = is_endpoint_on_boundary<boundary_back>(turn.point, boundary_checker);\r
+\r
+ if ( back_b )\r
+ {\r
+ update<boundary, interior, '0', transpose_result>(res);\r
+ }\r
+ else\r
+ {\r
+ update<interior, interior, '0', transpose_result>(res);\r
+ }\r
+\r
+ if ( first_in_range )\r
+ {\r
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(ls1_ref), boundary_checker);\r
+ if ( front_b )\r
+ {\r
+ update<boundary, exterior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else if ( turn.operations[op_id].position == overlay::position_middle\r
+ && turn.operations[other_op_id].position == overlay::position_middle )\r
+ {\r
+ update<interior, interior, '0', transpose_result>(res);\r
+\r
+ // here we don't know which one is degenerated\r
+\r
+ bool const is_point1 = boost::size(ls1_ref) == 2\r
+ && equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref));\r
+ bool const is_point2 = boost::size(ls2_ref) == 2\r
+ && equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref));\r
+\r
+ // if the second one is degenerated\r
+ if ( !is_point1 && is_point2 )\r
+ {\r
+ update<interior, exterior, '1', transpose_result>(res);\r
+\r
+ if ( first_in_range )\r
+ {\r
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));\r
+ bool const front_b = is_endpoint_on_boundary<boundary_front>(\r
+ range::front(ls1_ref), boundary_checker);\r
+ if ( front_b )\r
+ {\r
+ update<boundary, exterior, '0', transpose_result>(res);\r
+ }\r
+ }\r
+\r
+ m_degenerated_turn_ptr = boost::addressof(turn);\r
+ }\r
+ }\r
+\r
+ // NOTE: other.position == front and other.position == back\r
+ // will be handled later, for the other geometry\r
+ }\r
+\r
+ private:\r
+ exit_watcher<TurnInfo, OpId> m_exit_watcher;\r
+ segment_watcher<same_single> m_seg_watcher;\r
+ const TurnInfo * m_previous_turn_ptr;\r
+ overlay::operation_type m_previous_operation;\r
+ const TurnInfo * m_degenerated_turn_ptr;\r
+ bool m_collinear_spike_exit;\r
+ };\r
+\r
+ template <typename Result,\r
+ typename TurnIt,\r
+ typename Analyser,\r
+ typename Geometry,\r
+ typename OtherGeometry,\r
+ typename BoundaryChecker,\r
+ typename OtherBoundaryChecker>\r
+ static inline void analyse_each_turn(Result & res,\r
+ Analyser & analyser,\r
+ TurnIt first, TurnIt last,\r
+ Geometry const& geometry,\r
+ OtherGeometry const& other_geometry,\r
+ BoundaryChecker const& boundary_checker,\r
+ OtherBoundaryChecker const& other_boundary_checker)\r
+ {\r
+ if ( first == last )\r
+ return;\r
+\r
+ for ( TurnIt it = first ; it != last ; ++it )\r
+ {\r
+ analyser.apply(res, it,\r
+ geometry, other_geometry,\r
+ boundary_checker, other_boundary_checker);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )\r
+ return;\r
+ }\r
+\r
+ analyser.apply(res, first, last,\r
+ geometry, other_geometry,\r
+ boundary_checker, other_boundary_checker);\r
+ }\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>\r
+//#include <boost/geometry/algorithms/within.hpp>\r
+//#include <boost/geometry/algorithms/covered_by.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/result.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+// non-point geometry\r
+template <typename Point, typename Geometry, bool Transpose = false>\r
+struct point_geometry\r
+{\r
+ // TODO: interrupt only if the topology check is complex\r
+\r
+ static const bool interruption_enabled = true;\r
+\r
+ template <typename Result>\r
+ static inline void apply(Point const& point, Geometry const& geometry, Result & result)\r
+ {\r
+ int pig = detail::within::point_in_geometry(point, geometry);\r
+\r
+ if ( pig > 0 ) // within\r
+ {\r
+ relate::set<interior, interior, '0', Transpose>(result);\r
+ }\r
+ else if ( pig == 0 )\r
+ {\r
+ relate::set<interior, boundary, '0', Transpose>(result);\r
+ }\r
+ else // pig < 0 - not within\r
+ {\r
+ relate::set<interior, exterior, '0', Transpose>(result);\r
+ }\r
+\r
+ relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);\r
+\r
+ if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )\r
+ return;\r
+\r
+ // the point is on the boundary\r
+ if ( pig == 0 )\r
+ {\r
+ // NOTE: even for MLs, if there is at least one boundary point,\r
+ // somewhere there must be another one\r
+\r
+ // check if there are other boundaries outside\r
+ typedef detail::relate::topology_check<Geometry> tc_t;\r
+ //tc_t tc(geometry, point);\r
+ //if ( tc.has_interior )\r
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);\r
+ //if ( tc.has_boundary )\r
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);\r
+ }\r
+ else\r
+ {\r
+ // check if there is a boundary in Geometry\r
+ typedef detail::relate::topology_check<Geometry> tc_t;\r
+ tc_t tc(geometry);\r
+ if ( tc.has_interior )\r
+ relate::set<exterior, interior, tc_t::interior, Transpose>(result);\r
+ if ( tc.has_boundary )\r
+ relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);\r
+ }\r
+ }\r
+};\r
+\r
+// transposed result of point_geometry\r
+template <typename Geometry, typename Point>\r
+struct geometry_point\r
+{\r
+ // TODO: interrupt only if the topology check is complex\r
+\r
+ static const bool interruption_enabled = true;\r
+\r
+ template <typename Result>\r
+ static inline void apply(Geometry const& geometry, Point const& point, Result & result)\r
+ {\r
+ point_geometry<Point, Geometry, true>::apply(point, geometry, result);\r
+ }\r
+};\r
+\r
+// TODO: rewrite the folowing:\r
+\r
+//// NOTE: Those tests should be consistent with within(Point, Box) and covered_by(Point, Box)\r
+//// There is no EPS used in those functions, values are compared using < or <=\r
+//// so comparing MIN and MAX in the same way should be fine\r
+//\r
+//template <typename Box, std::size_t I = 0, std::size_t D = geometry::dimension<Box>::value>\r
+//struct box_has_interior\r
+//{\r
+// static inline bool apply(Box const& box)\r
+// {\r
+// return geometry::get<min_corner, I>(box) < geometry::get<max_corner, I>(box)\r
+// && box_has_interior<Box, I + 1, D>::apply(box);\r
+// }\r
+//};\r
+//\r
+//template <typename Box, std::size_t D>\r
+//struct box_has_interior<Box, D, D>\r
+//{\r
+// static inline bool apply(Box const&) { return true; }\r
+//};\r
+//\r
+//// NOTE: especially important here (see the NOTE above).\r
+//\r
+//template <typename Box, std::size_t I = 0, std::size_t D = geometry::dimension<Box>::value>\r
+//struct box_has_equal_min_max\r
+//{\r
+// static inline bool apply(Box const& box)\r
+// {\r
+// return geometry::get<min_corner, I>(box) == geometry::get<max_corner, I>(box)\r
+// && box_has_equal_min_max<Box, I + 1, D>::apply(box);\r
+// }\r
+//};\r
+//\r
+//template <typename Box, std::size_t D>\r
+//struct box_has_equal_min_max<Box, D, D>\r
+//{\r
+// static inline bool apply(Box const&) { return true; }\r
+//};\r
+//\r
+//template <typename Point, typename Box>\r
+//struct point_box\r
+//{\r
+// static inline result apply(Point const& point, Box const& box)\r
+// {\r
+// result res;\r
+//\r
+// if ( geometry::within(point, box) ) // this also means that the box has interior\r
+// {\r
+// return result("0FFFFFTTT");\r
+// }\r
+// else if ( geometry::covered_by(point, box) ) // point is on the boundary\r
+// {\r
+// //if ( box_has_interior<Box>::apply(box) )\r
+// //{\r
+// // return result("F0FFFFTTT");\r
+// //}\r
+// //else if ( box_has_equal_min_max<Box>::apply(box) ) // no boundary outside point\r
+// //{\r
+// // return result("F0FFFFFFT");\r
+// //}\r
+// //else // no interior outside point\r
+// //{\r
+// // return result("F0FFFFFTT");\r
+// //}\r
+// return result("F0FFFF**T");\r
+// }\r
+// else \r
+// {\r
+// /*if ( box_has_interior<Box>::apply(box) )\r
+// {\r
+// return result("FF0FFFTTT");\r
+// }\r
+// else\r
+// {\r
+// return result("FF0FFFFTT");\r
+// }*/\r
+// return result("FF0FFF*TT");\r
+// }\r
+//\r
+// return res;\r
+// }\r
+//};\r
+//\r
+//template <typename Box, typename Point>\r
+//struct box_point\r
+//{\r
+// static inline result apply(Box const& box, Point const& point)\r
+// {\r
+// if ( geometry::within(point, box) )\r
+// return result("0FTFFTFFT");\r
+// else if ( geometry::covered_by(point, box) )\r
+// return result("FF*0F*FFT");\r
+// else \r
+// return result("FF*FFT0FT");\r
+// }\r
+//};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP\r
+\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/range/empty.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/less.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/result.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+template <typename Point1, typename Point2>\r
+struct point_point\r
+{\r
+ static const bool interruption_enabled = false;\r
+\r
+ template <typename Result>\r
+ static inline void apply(Point1 const& point1, Point2 const& point2, Result & result)\r
+ {\r
+ bool equal = detail::equals::equals_point_point(point1, point2);\r
+ if ( equal )\r
+ {\r
+ relate::set<interior, interior, '0'>(result);\r
+ }\r
+ else\r
+ {\r
+ relate::set<interior, exterior, '0'>(result);\r
+ relate::set<exterior, interior, '0'>(result);\r
+ }\r
+\r
+ relate::set<exterior, exterior, result_dimension<Point1>::value>(result);\r
+ }\r
+};\r
+\r
+template <typename Point, typename MultiPoint>\r
+std::pair<bool, bool> point_multipoint_check(Point const& point, MultiPoint const& multi_point)\r
+{\r
+ bool found_inside = false;\r
+ bool found_outside = false;\r
+\r
+ // point_in_geometry could be used here but why iterate over MultiPoint twice?\r
+ // we must search for a point in the exterior because all points in MultiPoint can be equal\r
+\r
+ typedef typename boost::range_iterator<MultiPoint const>::type iterator;\r
+ iterator it = boost::begin(multi_point);\r
+ iterator last = boost::end(multi_point);\r
+ for ( ; it != last ; ++it )\r
+ {\r
+ bool ii = detail::equals::equals_point_point(point, *it);\r
+\r
+ if ( ii )\r
+ found_inside = true;\r
+ else\r
+ found_outside = true;\r
+\r
+ if ( found_inside && found_outside )\r
+ break;\r
+ }\r
+\r
+ return std::make_pair(found_inside, found_outside);\r
+}\r
+\r
+template <typename Point, typename MultiPoint, bool Transpose = false>\r
+struct point_multipoint\r
+{\r
+ static const bool interruption_enabled = false;\r
+\r
+ template <typename Result>\r
+ static inline void apply(Point const& point, MultiPoint const& multi_point, Result & result)\r
+ {\r
+ if ( boost::empty(multi_point) )\r
+ {\r
+ // TODO: throw on empty input?\r
+ relate::set<interior, exterior, '0', Transpose>(result);\r
+ return;\r
+ }\r
+\r
+ std::pair<bool, bool> rel = point_multipoint_check(point, multi_point);\r
+\r
+ if ( rel.first ) // some point of MP is equal to P\r
+ {\r
+ relate::set<interior, interior, '0', Transpose>(result);\r
+\r
+ if ( rel.second ) // a point of MP was found outside P\r
+ {\r
+ relate::set<exterior, interior, '0', Transpose>(result);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ relate::set<interior, exterior, '0', Transpose>(result);\r
+ relate::set<exterior, interior, '0', Transpose>(result);\r
+ }\r
+\r
+ relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);\r
+ }\r
+};\r
+\r
+template <typename MultiPoint, typename Point>\r
+struct multipoint_point\r
+{\r
+ static const bool interruption_enabled = false;\r
+\r
+ template <typename Result>\r
+ static inline void apply(MultiPoint const& multi_point, Point const& point, Result & result)\r
+ {\r
+ point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result);\r
+ }\r
+};\r
+\r
+template <typename MultiPoint1, typename MultiPoint2>\r
+struct multipoint_multipoint\r
+{\r
+ static const bool interruption_enabled = true;\r
+\r
+ template <typename Result>\r
+ static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2, Result & result)\r
+ {\r
+ {\r
+ // TODO: throw on empty input?\r
+ bool empty1 = boost::empty(multi_point1);\r
+ bool empty2 = boost::empty(multi_point2);\r
+ if ( empty1 && empty2 )\r
+ {\r
+ return;\r
+ }\r
+ else if ( empty1 )\r
+ {\r
+ relate::set<exterior, interior, '0'>(result);\r
+ return;\r
+ }\r
+ else if ( empty2 )\r
+ {\r
+ relate::set<interior, exterior, '0'>(result);\r
+ return;\r
+ }\r
+ }\r
+\r
+// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED\r
+\r
+// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed\r
+// so if e.g. only I/I must be analysed we musn't check the other MPt\r
+\r
+// TODO: Also, the geometry with the smaller number of points may be analysed first\r
+ //if ( boost::size(multi_point1) < boost::size(multi_point2) )\r
+\r
+ // NlogN + MlogN\r
+ bool all_handled = search<false>(multi_point1, multi_point2, result);\r
+ \r
+ if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) )\r
+ return;\r
+\r
+ // MlogM + NlogM\r
+ search<true>(multi_point2, multi_point1, result);\r
+ }\r
+\r
+ template <bool Transpose,\r
+ typename SortedMultiPoint,\r
+ typename IteratedMultiPoint,\r
+ typename Result>\r
+ static inline bool search(SortedMultiPoint const& sorted_mpt,\r
+ IteratedMultiPoint const& iterated_mpt,\r
+ Result & result)\r
+ {\r
+ // sort points from the 1 MPt\r
+ typedef typename geometry::point_type<SortedMultiPoint>::type point_type;\r
+ std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));\r
+ std::sort(points.begin(), points.end(), less());\r
+\r
+ bool found_inside = false;\r
+ bool found_outside = false;\r
+\r
+ // for each point in the second MPt\r
+ typedef typename boost::range_iterator<IteratedMultiPoint const>::type iterator;\r
+ for ( iterator it = boost::begin(iterated_mpt) ;\r
+ it != boost::end(iterated_mpt) ; ++it )\r
+ {\r
+ bool ii =\r
+ std::binary_search(points.begin(), points.end(), *it, less());\r
+ if ( ii )\r
+ found_inside = true;\r
+ else\r
+ found_outside = true;\r
+\r
+ if ( found_inside && found_outside )\r
+ break;\r
+ }\r
+\r
+ // an optimization\r
+ bool all_handled = false;\r
+\r
+ if ( found_inside ) // some point of MP2 is equal to some of MP1\r
+ {\r
+// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed\r
+// so if e.g. only I/I must be analysed we musn't check the other MPt\r
+\r
+ relate::set<interior, interior, '0', Transpose>(result);\r
+\r
+ if ( found_outside ) // some point of MP2 was found outside of MP1\r
+ {\r
+ relate::set<exterior, interior, '0', Transpose>(result);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ relate::set<interior, exterior, '0', Transpose>(result);\r
+ relate::set<exterior, interior, '0', Transpose>(result);\r
+\r
+ // if no point is intersecting the other MPt then we musn't analyse the reversed case\r
+ all_handled = true;\r
+ }\r
+\r
+ relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);\r
+\r
+ return all_handled;\r
+ }\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/or.hpp>\r
+#include <boost/type_traits/is_base_of.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+struct implemented_tag {};\r
+\r
+template <template <typename, typename> class StaticMaskTrait,\r
+ typename Geometry1,\r
+ typename Geometry2>\r
+struct relate_impl\r
+ : boost::mpl::if_\r
+ <\r
+ boost::mpl::or_\r
+ <\r
+ boost::is_base_of\r
+ <\r
+ nyi::not_implemented_tag,\r
+ StaticMaskTrait<Geometry1, Geometry2>\r
+ >,\r
+ boost::is_base_of\r
+ <\r
+ nyi::not_implemented_tag,\r
+ dispatch::relate<Geometry1, Geometry2>\r
+ >\r
+ >,\r
+ not_implemented\r
+ <\r
+ typename geometry::tag<Geometry1>::type,\r
+ typename geometry::tag<Geometry2>::type\r
+ >,\r
+ implemented_tag\r
+ >::type\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ typename detail::relate::result_handler_type\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename StaticMaskTrait<Geometry1, Geometry2>::type\r
+ >::type handler;\r
+\r
+ dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler);\r
+\r
+ return handler.result();\r
+ }\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013-2016.\r
+// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/at.hpp>\r
+#include <boost/mpl/begin.hpp>\r
+#include <boost/mpl/deref.hpp>\r
+#include <boost/mpl/end.hpp>\r
+#include <boost/mpl/is_sequence.hpp>\r
+#include <boost/mpl/next.hpp>\r
+#include <boost/static_assert.hpp>\r
+#include <boost/tuple/tuple.hpp>\r
+#include <boost/type_traits/integral_constant.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/exception.hpp>\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+enum field { interior = 0, boundary = 1, exterior = 2 };\r
+\r
+// TODO: IF THE RESULT IS UPDATED WITH THE MAX POSSIBLE VALUE FOR SOME PAIR OF GEOEMTRIES\r
+// THE VALUE ALREADY STORED MUSN'T BE CHECKED\r
+// update() calls chould be replaced with set() in those cases\r
+// but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that\r
+// so some additional function could be added, e.g. set_dim()\r
+\r
+// --------------- MATRIX ----------------\r
+\r
+// matrix\r
+\r
+template <std::size_t Height, std::size_t Width = Height>\r
+class matrix\r
+{\r
+public:\r
+ typedef char value_type;\r
+ typedef std::size_t size_type;\r
+ typedef const char * const_iterator;\r
+ typedef const_iterator iterator;\r
+\r
+ static const std::size_t static_width = Width;\r
+ static const std::size_t static_height = Height;\r
+ static const std::size_t static_size = Width * Height;\r
+ \r
+ inline matrix()\r
+ {\r
+ ::memset(m_array, 'F', static_size);\r
+ }\r
+\r
+ template <field F1, field F2>\r
+ inline char get() const\r
+ {\r
+ BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);\r
+ static const std::size_t index = F1 * Width + F2;\r
+ BOOST_STATIC_ASSERT(index < static_size);\r
+ return m_array[index];\r
+ }\r
+\r
+ template <field F1, field F2, char V>\r
+ inline void set()\r
+ {\r
+ BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);\r
+ static const std::size_t index = F1 * Width + F2;\r
+ BOOST_STATIC_ASSERT(index < static_size);\r
+ m_array[index] = V;\r
+ }\r
+\r
+ inline char operator[](std::size_t index) const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(index < static_size);\r
+ return m_array[index];\r
+ }\r
+\r
+ inline const_iterator begin() const\r
+ {\r
+ return m_array;\r
+ }\r
+\r
+ inline const_iterator end() const\r
+ {\r
+ return m_array + static_size;\r
+ }\r
+\r
+ inline static std::size_t size()\r
+ {\r
+ return static_size;\r
+ }\r
+ \r
+ inline const char * data() const\r
+ {\r
+ return m_array;\r
+ }\r
+\r
+ inline std::string str() const\r
+ {\r
+ return std::string(m_array, static_size);\r
+ }\r
+\r
+private:\r
+ char m_array[static_size];\r
+};\r
+\r
+// matrix_handler\r
+\r
+template <typename Matrix>\r
+class matrix_handler\r
+{\r
+public:\r
+ typedef Matrix result_type;\r
+\r
+ static const bool interrupt = false;\r
+\r
+ matrix_handler()\r
+ {}\r
+\r
+ result_type const& result() const\r
+ {\r
+ return m_matrix;\r
+ }\r
+\r
+ result_type const& matrix() const\r
+ {\r
+ return m_matrix;\r
+ }\r
+\r
+ result_type & matrix()\r
+ {\r
+ return m_matrix;\r
+ }\r
+\r
+ template <field F1, field F2, char D>\r
+ inline bool may_update() const\r
+ {\r
+ BOOST_STATIC_ASSERT('0' <= D && D <= '9');\r
+\r
+ char const c = m_matrix.template get<F1, F2>();\r
+ return D > c || c > '9';\r
+ }\r
+\r
+ template <field F1, field F2, char V>\r
+ inline void set()\r
+ {\r
+ static const bool in_bounds = F1 < Matrix::static_height\r
+ && F2 < Matrix::static_width;\r
+ typedef boost::integral_constant<bool, in_bounds> in_bounds_t;\r
+ set_dispatch<F1, F2, V>(in_bounds_t());\r
+ }\r
+\r
+ template <field F1, field F2, char D>\r
+ inline void update()\r
+ {\r
+ static const bool in_bounds = F1 < Matrix::static_height\r
+ && F2 < Matrix::static_width;\r
+ typedef boost::integral_constant<bool, in_bounds> in_bounds_t;\r
+ update_dispatch<F1, F2, D>(in_bounds_t());\r
+ }\r
+\r
+private:\r
+ template <field F1, field F2, char V>\r
+ inline void set_dispatch(integral_constant<bool, true>)\r
+ {\r
+ static const std::size_t index = F1 * Matrix::static_width + F2;\r
+ BOOST_STATIC_ASSERT(index < Matrix::static_size);\r
+ BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');\r
+ m_matrix.template set<F1, F2, V>();\r
+ }\r
+ template <field F1, field F2, char V>\r
+ inline void set_dispatch(integral_constant<bool, false>)\r
+ {}\r
+\r
+ template <field F1, field F2, char D>\r
+ inline void update_dispatch(integral_constant<bool, true>)\r
+ {\r
+ static const std::size_t index = F1 * Matrix::static_width + F2;\r
+ BOOST_STATIC_ASSERT(index < Matrix::static_size);\r
+ BOOST_STATIC_ASSERT('0' <= D && D <= '9');\r
+ char const c = m_matrix.template get<F1, F2>();\r
+ if ( D > c || c > '9')\r
+ m_matrix.template set<F1, F2, D>();\r
+ }\r
+ template <field F1, field F2, char D>\r
+ inline void update_dispatch(integral_constant<bool, false>)\r
+ {}\r
+\r
+ Matrix m_matrix;\r
+};\r
+\r
+// --------------- RUN-TIME MASK ----------------\r
+\r
+// run-time mask\r
+\r
+template <std::size_t Height, std::size_t Width = Height>\r
+class mask\r
+{\r
+public:\r
+ static const std::size_t static_width = Width;\r
+ static const std::size_t static_height = Height;\r
+ static const std::size_t static_size = Width * Height;\r
+\r
+ inline mask(const char * s)\r
+ {\r
+ char * it = m_array;\r
+ char * const last = m_array + static_size;\r
+ for ( ; it != last && *s != '\0' ; ++it, ++s )\r
+ {\r
+ char c = *s;\r
+ check_char(c);\r
+ *it = c;\r
+ }\r
+ if ( it != last )\r
+ {\r
+ ::memset(it, '*', last - it);\r
+ }\r
+ }\r
+\r
+ inline mask(const char * s, std::size_t count)\r
+ {\r
+ if ( count > static_size )\r
+ {\r
+ count = static_size;\r
+ }\r
+ if ( count > 0 )\r
+ {\r
+ std::for_each(s, s + count, check_char);\r
+ ::memcpy(m_array, s, count);\r
+ }\r
+ if ( count < static_size )\r
+ {\r
+ ::memset(m_array + count, '*', static_size - count);\r
+ }\r
+ }\r
+\r
+ template <field F1, field F2>\r
+ inline char get() const\r
+ {\r
+ BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);\r
+ static const std::size_t index = F1 * Width + F2;\r
+ BOOST_STATIC_ASSERT(index < static_size);\r
+ return m_array[index];\r
+ }\r
+\r
+private:\r
+ static inline void check_char(char c)\r
+ {\r
+ bool const is_valid = c == '*' || c == 'T' || c == 'F'\r
+ || ( c >= '0' && c <= '9' );\r
+ if ( !is_valid )\r
+ {\r
+ throw geometry::invalid_input_exception();\r
+ }\r
+ }\r
+\r
+ char m_array[static_size];\r
+};\r
+\r
+// interrupt()\r
+\r
+template <typename Mask, bool InterruptEnabled>\r
+struct interrupt_dispatch\r
+{\r
+ template <field F1, field F2, char V>\r
+ static inline bool apply(Mask const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Mask>\r
+struct interrupt_dispatch<Mask, true>\r
+{\r
+ template <field F1, field F2, char V>\r
+ static inline bool apply(Mask const& mask)\r
+ {\r
+ char m = mask.template get<F1, F2>();\r
+ return check_element<V>(m);\r
+ }\r
+\r
+ template <char V>\r
+ static inline bool check_element(char m)\r
+ {\r
+ if ( BOOST_GEOMETRY_CONDITION(V >= '0' && V <= '9') )\r
+ {\r
+ return m == 'F' || ( m < V && m >= '0' && m <= '9' );\r
+ }\r
+ else if ( BOOST_GEOMETRY_CONDITION(V == 'T') )\r
+ {\r
+ return m == 'F';\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Masks, int I = 0, int N = boost::tuples::length<Masks>::value>\r
+struct interrupt_dispatch_tuple\r
+{\r
+ template <field F1, field F2, char V>\r
+ static inline bool apply(Masks const& masks)\r
+ {\r
+ typedef typename boost::tuples::element<I, Masks>::type mask_type;\r
+ mask_type const& mask = boost::get<I>(masks);\r
+ return interrupt_dispatch<mask_type, true>::template apply<F1, F2, V>(mask)\r
+ && interrupt_dispatch_tuple<Masks, I+1>::template apply<F1, F2, V>(masks);\r
+ }\r
+};\r
+\r
+template <typename Masks, int N>\r
+struct interrupt_dispatch_tuple<Masks, N, N>\r
+{\r
+ template <field F1, field F2, char V>\r
+ static inline bool apply(Masks const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+//template <typename T0, typename T1, typename T2, typename T3, typename T4,\r
+// typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct interrupt_dispatch<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, true>\r
+//{\r
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;\r
+\r
+// template <field F1, field F2, char V>\r
+// static inline bool apply(mask_type const& mask)\r
+// {\r
+// return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);\r
+// }\r
+//};\r
+\r
+template <typename Head, typename Tail>\r
+struct interrupt_dispatch<boost::tuples::cons<Head, Tail>, true>\r
+{\r
+ typedef boost::tuples::cons<Head, Tail> mask_type;\r
+\r
+ template <field F1, field F2, char V>\r
+ static inline bool apply(mask_type const& mask)\r
+ {\r
+ return interrupt_dispatch_tuple<mask_type>::template apply<F1, F2, V>(mask);\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char V, bool InterruptEnabled, typename Mask>\r
+inline bool interrupt(Mask const& mask)\r
+{\r
+ return interrupt_dispatch<Mask, InterruptEnabled>\r
+ ::template apply<F1, F2, V>(mask);\r
+}\r
+\r
+// may_update()\r
+\r
+template <typename Mask>\r
+struct may_update_dispatch\r
+{\r
+ template <field F1, field F2, char D, typename Matrix>\r
+ static inline bool apply(Mask const& mask, Matrix const& matrix)\r
+ {\r
+ BOOST_STATIC_ASSERT('0' <= D && D <= '9');\r
+\r
+ char const m = mask.template get<F1, F2>();\r
+ \r
+ if ( m == 'F' )\r
+ {\r
+ return true;\r
+ }\r
+ else if ( m == 'T' )\r
+ {\r
+ char const c = matrix.template get<F1, F2>();\r
+ return c == 'F'; // if it's T or between 0 and 9, the result will be the same\r
+ }\r
+ else if ( m >= '0' && m <= '9' )\r
+ {\r
+ char const c = matrix.template get<F1, F2>();\r
+ return D > c || c > '9';\r
+ }\r
+\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Masks, int I = 0, int N = boost::tuples::length<Masks>::value>\r
+struct may_update_dispatch_tuple\r
+{\r
+ template <field F1, field F2, char D, typename Matrix>\r
+ static inline bool apply(Masks const& masks, Matrix const& matrix)\r
+ {\r
+ typedef typename boost::tuples::element<I, Masks>::type mask_type;\r
+ mask_type const& mask = boost::get<I>(masks);\r
+ return may_update_dispatch<mask_type>::template apply<F1, F2, D>(mask, matrix)\r
+ || may_update_dispatch_tuple<Masks, I+1>::template apply<F1, F2, D>(masks, matrix);\r
+ }\r
+};\r
+\r
+template <typename Masks, int N>\r
+struct may_update_dispatch_tuple<Masks, N, N>\r
+{\r
+ template <field F1, field F2, char D, typename Matrix>\r
+ static inline bool apply(Masks const& , Matrix const& )\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+//template <typename T0, typename T1, typename T2, typename T3, typename T4,\r
+// typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct may_update_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >\r
+//{\r
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;\r
+\r
+// template <field F1, field F2, char D, typename Matrix>\r
+// static inline bool apply(mask_type const& mask, Matrix const& matrix)\r
+// {\r
+// return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);\r
+// }\r
+//};\r
+\r
+template <typename Head, typename Tail>\r
+struct may_update_dispatch< boost::tuples::cons<Head, Tail> >\r
+{\r
+ typedef boost::tuples::cons<Head, Tail> mask_type;\r
+\r
+ template <field F1, field F2, char D, typename Matrix>\r
+ static inline bool apply(mask_type const& mask, Matrix const& matrix)\r
+ {\r
+ return may_update_dispatch_tuple<mask_type>::template apply<F1, F2, D>(mask, matrix);\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char D, typename Mask, typename Matrix>\r
+inline bool may_update(Mask const& mask, Matrix const& matrix)\r
+{\r
+ return may_update_dispatch<Mask>\r
+ ::template apply<F1, F2, D>(mask, matrix);\r
+}\r
+\r
+// check_matrix()\r
+\r
+template <typename Mask>\r
+struct check_dispatch\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Mask const& mask, Matrix const& matrix)\r
+ {\r
+ return per_one<interior, interior>(mask, matrix)\r
+ && per_one<interior, boundary>(mask, matrix)\r
+ && per_one<interior, exterior>(mask, matrix)\r
+ && per_one<boundary, interior>(mask, matrix)\r
+ && per_one<boundary, boundary>(mask, matrix)\r
+ && per_one<boundary, exterior>(mask, matrix)\r
+ && per_one<exterior, interior>(mask, matrix)\r
+ && per_one<exterior, boundary>(mask, matrix)\r
+ && per_one<exterior, exterior>(mask, matrix);\r
+ }\r
+\r
+ template <field F1, field F2, typename Matrix>\r
+ static inline bool per_one(Mask const& mask, Matrix const& matrix)\r
+ {\r
+ const char mask_el = mask.template get<F1, F2>();\r
+ const char el = matrix.template get<F1, F2>();\r
+\r
+ if ( mask_el == 'F' )\r
+ {\r
+ return el == 'F';\r
+ }\r
+ else if ( mask_el == 'T' )\r
+ {\r
+ return el == 'T' || ( el >= '0' && el <= '9' );\r
+ }\r
+ else if ( mask_el >= '0' && mask_el <= '9' )\r
+ {\r
+ return el == mask_el;\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Masks, int I = 0, int N = boost::tuples::length<Masks>::value>\r
+struct check_dispatch_tuple\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Masks const& masks, Matrix const& matrix)\r
+ {\r
+ typedef typename boost::tuples::element<I, Masks>::type mask_type;\r
+ mask_type const& mask = boost::get<I>(masks);\r
+ return check_dispatch<mask_type>::apply(mask, matrix)\r
+ || check_dispatch_tuple<Masks, I+1>::apply(masks, matrix);\r
+ }\r
+};\r
+\r
+template <typename Masks, int N>\r
+struct check_dispatch_tuple<Masks, N, N>\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Masks const&, Matrix const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+//template <typename T0, typename T1, typename T2, typename T3, typename T4,\r
+// typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct check_dispatch< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >\r
+//{\r
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> mask_type;\r
+\r
+// template <typename Matrix>\r
+// static inline bool apply(mask_type const& mask, Matrix const& matrix)\r
+// {\r
+// return check_dispatch_tuple<mask_type>::apply(mask, matrix);\r
+// }\r
+//};\r
+\r
+template <typename Head, typename Tail>\r
+struct check_dispatch< boost::tuples::cons<Head, Tail> >\r
+{\r
+ typedef boost::tuples::cons<Head, Tail> mask_type;\r
+\r
+ template <typename Matrix>\r
+ static inline bool apply(mask_type const& mask, Matrix const& matrix)\r
+ {\r
+ return check_dispatch_tuple<mask_type>::apply(mask, matrix);\r
+ }\r
+};\r
+\r
+template <typename Mask, typename Matrix>\r
+inline bool check_matrix(Mask const& mask, Matrix const& matrix)\r
+{\r
+ return check_dispatch<Mask>::apply(mask, matrix);\r
+}\r
+\r
+// matrix_width\r
+\r
+template <typename MatrixOrMask>\r
+struct matrix_width\r
+{\r
+ static const std::size_t value = MatrixOrMask::static_width;\r
+};\r
+\r
+template <typename Tuple,\r
+ int I = 0,\r
+ int N = boost::tuples::length<Tuple>::value>\r
+struct matrix_width_tuple\r
+{\r
+ static const std::size_t\r
+ current = matrix_width<typename boost::tuples::element<I, Tuple>::type>::value;\r
+ static const std::size_t\r
+ next = matrix_width_tuple<Tuple, I+1>::value;\r
+\r
+ static const std::size_t\r
+ value = current > next ? current : next;\r
+};\r
+\r
+template <typename Tuple, int N>\r
+struct matrix_width_tuple<Tuple, N, N>\r
+{\r
+ static const std::size_t value = 0;\r
+};\r
+\r
+template <typename Head, typename Tail>\r
+struct matrix_width< boost::tuples::cons<Head, Tail> >\r
+{\r
+ static const std::size_t\r
+ value = matrix_width_tuple< boost::tuples::cons<Head, Tail> >::value;\r
+};\r
+\r
+// mask_handler\r
+\r
+template <typename Mask, bool Interrupt>\r
+class mask_handler\r
+ : private matrix_handler\r
+ <\r
+ relate::matrix<matrix_width<Mask>::value>\r
+ >\r
+{\r
+ typedef matrix_handler\r
+ <\r
+ relate::matrix<matrix_width<Mask>::value>\r
+ > base_t;\r
+\r
+public:\r
+ typedef bool result_type;\r
+\r
+ bool interrupt;\r
+\r
+ inline explicit mask_handler(Mask const& m)\r
+ : interrupt(false)\r
+ , m_mask(m)\r
+ {}\r
+\r
+ result_type result() const\r
+ {\r
+ return !interrupt\r
+ && check_matrix(m_mask, base_t::matrix());\r
+ }\r
+\r
+ template <field F1, field F2, char D>\r
+ inline bool may_update() const\r
+ {\r
+ return detail::relate::may_update<F1, F2, D>(\r
+ m_mask, base_t::matrix()\r
+ );\r
+ }\r
+\r
+ template <field F1, field F2, char V>\r
+ inline void set()\r
+ {\r
+ if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )\r
+ {\r
+ interrupt = true;\r
+ }\r
+ else\r
+ {\r
+ base_t::template set<F1, F2, V>();\r
+ }\r
+ }\r
+\r
+ template <field F1, field F2, char V>\r
+ inline void update()\r
+ {\r
+ if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )\r
+ {\r
+ interrupt = true;\r
+ }\r
+ else\r
+ {\r
+ base_t::template update<F1, F2, V>();\r
+ }\r
+ }\r
+\r
+private:\r
+ Mask const& m_mask;\r
+};\r
+\r
+// --------------- COMPILE-TIME MASK ----------------\r
+\r
+// static_check_characters\r
+template\r
+<\r
+ typename Seq,\r
+ typename First = typename boost::mpl::begin<Seq>::type,\r
+ typename Last = typename boost::mpl::end<Seq>::type\r
+>\r
+struct static_check_characters\r
+ : static_check_characters\r
+ <\r
+ Seq,\r
+ typename boost::mpl::next<First>::type\r
+ >\r
+{\r
+ typedef typename boost::mpl::deref<First>::type type;\r
+ static const char value = type::value;\r
+ static const bool is_valid = (value >= '0' && value <= '9')\r
+ || value == 'T' || value == 'F' || value == '*';\r
+ BOOST_MPL_ASSERT_MSG((is_valid),\r
+ INVALID_STATIC_MASK_CHARACTER,\r
+ (type));\r
+};\r
+\r
+template <typename Seq, typename Last>\r
+struct static_check_characters<Seq, Last, Last>\r
+{};\r
+\r
+// static_mask\r
+\r
+template\r
+<\r
+ typename Seq,\r
+ std::size_t Height,\r
+ std::size_t Width = Height\r
+>\r
+struct static_mask\r
+{\r
+ static const std::size_t static_width = Width;\r
+ static const std::size_t static_height = Height;\r
+ static const std::size_t static_size = Width * Height;\r
+\r
+ BOOST_STATIC_ASSERT(\r
+ std::size_t(boost::mpl::size<Seq>::type::value) == static_size);\r
+ \r
+ template <detail::relate::field F1, detail::relate::field F2>\r
+ struct static_get\r
+ {\r
+ BOOST_STATIC_ASSERT(std::size_t(F1) < static_height);\r
+ BOOST_STATIC_ASSERT(std::size_t(F2) < static_width);\r
+\r
+ static const char value\r
+ = boost::mpl::at_c<Seq, F1 * static_width + F2>::type::value;\r
+ };\r
+\r
+private:\r
+ // check static_mask characters\r
+ enum { mask_check = sizeof(static_check_characters<Seq>) };\r
+};\r
+\r
+// static_should_handle_element\r
+\r
+template <typename StaticMask, field F1, field F2, bool IsSequence>\r
+struct static_should_handle_element_dispatch\r
+{\r
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;\r
+ static const bool value = mask_el == 'F'\r
+ || mask_el == 'T'\r
+ || ( mask_el >= '0' && mask_el <= '9' );\r
+};\r
+\r
+template <typename First, typename Last, field F1, field F2>\r
+struct static_should_handle_element_sequence\r
+{\r
+ typedef typename boost::mpl::deref<First>::type StaticMask;\r
+\r
+ static const bool value\r
+ = static_should_handle_element_dispatch\r
+ <\r
+ StaticMask,\r
+ F1, F2,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::value\r
+ || static_should_handle_element_sequence\r
+ <\r
+ typename boost::mpl::next<First>::type,\r
+ Last,\r
+ F1, F2\r
+ >::value;\r
+};\r
+\r
+template <typename Last, field F1, field F2>\r
+struct static_should_handle_element_sequence<Last, Last, F1, F2>\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+template <typename StaticMask, field F1, field F2>\r
+struct static_should_handle_element_dispatch<StaticMask, F1, F2, true>\r
+{\r
+ static const bool value\r
+ = static_should_handle_element_sequence\r
+ <\r
+ typename boost::mpl::begin<StaticMask>::type,\r
+ typename boost::mpl::end<StaticMask>::type,\r
+ F1, F2\r
+ >::value;\r
+};\r
+\r
+template <typename StaticMask, field F1, field F2>\r
+struct static_should_handle_element\r
+{\r
+ static const bool value\r
+ = static_should_handle_element_dispatch\r
+ <\r
+ StaticMask,\r
+ F1, F2,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::value;\r
+};\r
+\r
+// static_interrupt\r
+\r
+template <typename StaticMask, char V, field F1, field F2, bool InterruptEnabled, bool IsSequence>\r
+struct static_interrupt_dispatch\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+template <typename StaticMask, char V, field F1, field F2, bool IsSequence>\r
+struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>\r
+{\r
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;\r
+\r
+ static const bool value\r
+ = ( V >= '0' && V <= '9' ) ? \r
+ ( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :\r
+ ( ( V == 'T' ) ? mask_el == 'F' : false );\r
+};\r
+\r
+template <typename First, typename Last, char V, field F1, field F2>\r
+struct static_interrupt_sequence\r
+{\r
+ typedef typename boost::mpl::deref<First>::type StaticMask;\r
+\r
+ static const bool value\r
+ = static_interrupt_dispatch\r
+ <\r
+ StaticMask,\r
+ V, F1, F2,\r
+ true,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::value\r
+ && static_interrupt_sequence\r
+ <\r
+ typename boost::mpl::next<First>::type,\r
+ Last,\r
+ V, F1, F2\r
+ >::value;\r
+};\r
+\r
+template <typename Last, char V, field F1, field F2>\r
+struct static_interrupt_sequence<Last, Last, V, F1, F2>\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+template <typename StaticMask, char V, field F1, field F2>\r
+struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, true>\r
+{\r
+ static const bool value\r
+ = static_interrupt_sequence\r
+ <\r
+ typename boost::mpl::begin<StaticMask>::type,\r
+ typename boost::mpl::end<StaticMask>::type,\r
+ V, F1, F2\r
+ >::value;\r
+};\r
+\r
+template <typename StaticMask, char V, field F1, field F2, bool EnableInterrupt>\r
+struct static_interrupt\r
+{\r
+ static const bool value\r
+ = static_interrupt_dispatch\r
+ <\r
+ StaticMask,\r
+ V, F1, F2,\r
+ EnableInterrupt,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::value;\r
+};\r
+\r
+// static_may_update\r
+\r
+template <typename StaticMask, char D, field F1, field F2, bool IsSequence>\r
+struct static_may_update_dispatch\r
+{\r
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;\r
+ static const int version\r
+ = mask_el == 'F' ? 0\r
+ : mask_el == 'T' ? 1\r
+ : mask_el >= '0' && mask_el <= '9' ? 2\r
+ : 3;\r
+\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return apply_dispatch(matrix, integral_constant<int, version>());\r
+ }\r
+\r
+ // mask_el == 'F'\r
+ template <typename Matrix>\r
+ static inline bool apply_dispatch(Matrix const& , integral_constant<int, 0>)\r
+ {\r
+ return true;\r
+ }\r
+ // mask_el == 'T'\r
+ template <typename Matrix>\r
+ static inline bool apply_dispatch(Matrix const& matrix, integral_constant<int, 1>)\r
+ {\r
+ char const c = matrix.template get<F1, F2>();\r
+ return c == 'F'; // if it's T or between 0 and 9, the result will be the same\r
+ }\r
+ // mask_el >= '0' && mask_el <= '9'\r
+ template <typename Matrix>\r
+ static inline bool apply_dispatch(Matrix const& matrix, integral_constant<int, 2>)\r
+ {\r
+ char const c = matrix.template get<F1, F2>();\r
+ return D > c || c > '9';\r
+ }\r
+ // else\r
+ template <typename Matrix>\r
+ static inline bool apply_dispatch(Matrix const&, integral_constant<int, 3>)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename First, typename Last, char D, field F1, field F2>\r
+struct static_may_update_sequence\r
+{\r
+ typedef typename boost::mpl::deref<First>::type StaticMask;\r
+\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return static_may_update_dispatch\r
+ <\r
+ StaticMask,\r
+ D, F1, F2,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::apply(matrix)\r
+ || static_may_update_sequence\r
+ <\r
+ typename boost::mpl::next<First>::type,\r
+ Last,\r
+ D, F1, F2\r
+ >::apply(matrix);\r
+ }\r
+};\r
+\r
+template <typename Last, char D, field F1, field F2>\r
+struct static_may_update_sequence<Last, Last, D, F1, F2>\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& /*matrix*/)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename StaticMask, char D, field F1, field F2>\r
+struct static_may_update_dispatch<StaticMask, D, F1, F2, true>\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return static_may_update_sequence\r
+ <\r
+ typename boost::mpl::begin<StaticMask>::type,\r
+ typename boost::mpl::end<StaticMask>::type,\r
+ D, F1, F2\r
+ >::apply(matrix);\r
+ }\r
+};\r
+\r
+template <typename StaticMask, char D, field F1, field F2>\r
+struct static_may_update\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return static_may_update_dispatch\r
+ <\r
+ StaticMask,\r
+ D, F1, F2,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::apply(matrix);\r
+ }\r
+};\r
+\r
+// static_check_matrix\r
+\r
+template <typename StaticMask, bool IsSequence>\r
+struct static_check_dispatch\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return per_one<interior, interior>::apply(matrix)\r
+ && per_one<interior, boundary>::apply(matrix)\r
+ && per_one<interior, exterior>::apply(matrix)\r
+ && per_one<boundary, interior>::apply(matrix)\r
+ && per_one<boundary, boundary>::apply(matrix)\r
+ && per_one<boundary, exterior>::apply(matrix)\r
+ && per_one<exterior, interior>::apply(matrix)\r
+ && per_one<exterior, boundary>::apply(matrix)\r
+ && per_one<exterior, exterior>::apply(matrix);\r
+ }\r
+ \r
+ template <field F1, field F2>\r
+ struct per_one\r
+ {\r
+ static const char mask_el = StaticMask::template static_get<F1, F2>::value;\r
+ static const int version\r
+ = mask_el == 'F' ? 0\r
+ : mask_el == 'T' ? 1\r
+ : mask_el >= '0' && mask_el <= '9' ? 2\r
+ : 3;\r
+\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ const char el = matrix.template get<F1, F2>();\r
+ return apply_dispatch(el, integral_constant<int, version>());\r
+ }\r
+\r
+ // mask_el == 'F'\r
+ static inline bool apply_dispatch(char el, integral_constant<int, 0>)\r
+ {\r
+ return el == 'F';\r
+ }\r
+ // mask_el == 'T'\r
+ static inline bool apply_dispatch(char el, integral_constant<int, 1>)\r
+ {\r
+ return el == 'T' || ( el >= '0' && el <= '9' );\r
+ }\r
+ // mask_el >= '0' && mask_el <= '9'\r
+ static inline bool apply_dispatch(char el, integral_constant<int, 2>)\r
+ {\r
+ return el == mask_el;\r
+ }\r
+ // else\r
+ static inline bool apply_dispatch(char /*el*/, integral_constant<int, 3>)\r
+ {\r
+ return true;\r
+ }\r
+ };\r
+};\r
+\r
+template <typename First, typename Last>\r
+struct static_check_sequence\r
+{\r
+ typedef typename boost::mpl::deref<First>::type StaticMask;\r
+\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return static_check_dispatch\r
+ <\r
+ StaticMask,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::apply(matrix)\r
+ || static_check_sequence\r
+ <\r
+ typename boost::mpl::next<First>::type,\r
+ Last\r
+ >::apply(matrix);\r
+ }\r
+};\r
+\r
+template <typename Last>\r
+struct static_check_sequence<Last, Last>\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& /*matrix*/)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename StaticMask>\r
+struct static_check_dispatch<StaticMask, true>\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return static_check_sequence\r
+ <\r
+ typename boost::mpl::begin<StaticMask>::type,\r
+ typename boost::mpl::end<StaticMask>::type\r
+ >::apply(matrix);\r
+ }\r
+};\r
+\r
+template <typename StaticMask>\r
+struct static_check_matrix\r
+{\r
+ template <typename Matrix>\r
+ static inline bool apply(Matrix const& matrix)\r
+ {\r
+ return static_check_dispatch\r
+ <\r
+ StaticMask,\r
+ boost::mpl::is_sequence<StaticMask>::value\r
+ >::apply(matrix);\r
+ }\r
+};\r
+\r
+// static_mask_handler\r
+\r
+template <typename StaticMask, bool Interrupt>\r
+class static_mask_handler\r
+ : private matrix_handler< matrix<3> >\r
+{\r
+ typedef matrix_handler< relate::matrix<3> > base_type;\r
+\r
+public:\r
+ typedef bool result_type;\r
+\r
+ bool interrupt;\r
+\r
+ inline static_mask_handler()\r
+ : interrupt(false)\r
+ {}\r
+\r
+ inline explicit static_mask_handler(StaticMask const& /*dummy*/)\r
+ : interrupt(false)\r
+ {}\r
+\r
+ result_type result() const\r
+ {\r
+ return (!Interrupt || !interrupt)\r
+ && static_check_matrix<StaticMask>::apply(base_type::matrix());\r
+ }\r
+\r
+ template <field F1, field F2, char D>\r
+ inline bool may_update() const\r
+ {\r
+ return static_may_update<StaticMask, D, F1, F2>::\r
+ apply(base_type::matrix());\r
+ }\r
+\r
+ template <field F1, field F2>\r
+ static inline bool expects()\r
+ {\r
+ return static_should_handle_element<StaticMask, F1, F2>::value;\r
+ }\r
+\r
+ template <field F1, field F2, char V>\r
+ inline void set()\r
+ {\r
+ static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;\r
+ static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;\r
+ static const int version = interrupt_c ? 0\r
+ : should_handle ? 1\r
+ : 2;\r
+\r
+ set_dispatch<F1, F2, V>(integral_constant<int, version>());\r
+ }\r
+\r
+ template <field F1, field F2, char V>\r
+ inline void update()\r
+ {\r
+ static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;\r
+ static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;\r
+ static const int version = interrupt_c ? 0\r
+ : should_handle ? 1\r
+ : 2;\r
+\r
+ update_dispatch<F1, F2, V>(integral_constant<int, version>());\r
+ }\r
+\r
+private:\r
+ // Interrupt && interrupt\r
+ template <field F1, field F2, char V>\r
+ inline void set_dispatch(integral_constant<int, 0>)\r
+ {\r
+ interrupt = true;\r
+ }\r
+ // else should_handle\r
+ template <field F1, field F2, char V>\r
+ inline void set_dispatch(integral_constant<int, 1>)\r
+ {\r
+ base_type::template set<F1, F2, V>();\r
+ }\r
+ // else\r
+ template <field F1, field F2, char V>\r
+ inline void set_dispatch(integral_constant<int, 2>)\r
+ {}\r
+\r
+ // Interrupt && interrupt\r
+ template <field F1, field F2, char V>\r
+ inline void update_dispatch(integral_constant<int, 0>)\r
+ {\r
+ interrupt = true;\r
+ }\r
+ // else should_handle\r
+ template <field F1, field F2, char V>\r
+ inline void update_dispatch(integral_constant<int, 1>)\r
+ {\r
+ base_type::template update<F1, F2, V>();\r
+ }\r
+ // else\r
+ template <field F1, field F2, char V>\r
+ inline void update_dispatch(integral_constant<int, 2>)\r
+ {}\r
+};\r
+\r
+// --------------- UTIL FUNCTIONS ----------------\r
+\r
+// set\r
+\r
+template <field F1, field F2, char V, typename Result>\r
+inline void set(Result & res)\r
+{\r
+ res.template set<F1, F2, V>();\r
+}\r
+\r
+template <field F1, field F2, char V, bool Transpose>\r
+struct set_dispatch\r
+{\r
+ template <typename Result>\r
+ static inline void apply(Result & res)\r
+ {\r
+ res.template set<F1, F2, V>();\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char V>\r
+struct set_dispatch<F1, F2, V, true>\r
+{\r
+ template <typename Result>\r
+ static inline void apply(Result & res)\r
+ {\r
+ res.template set<F2, F1, V>();\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char V, bool Transpose, typename Result>\r
+inline void set(Result & res)\r
+{\r
+ set_dispatch<F1, F2, V, Transpose>::apply(res);\r
+}\r
+\r
+// update\r
+\r
+template <field F1, field F2, char D, typename Result>\r
+inline void update(Result & res)\r
+{\r
+ res.template update<F1, F2, D>();\r
+}\r
+\r
+template <field F1, field F2, char D, bool Transpose>\r
+struct update_result_dispatch\r
+{\r
+ template <typename Result>\r
+ static inline void apply(Result & res)\r
+ {\r
+ update<F1, F2, D>(res);\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char D>\r
+struct update_result_dispatch<F1, F2, D, true>\r
+{\r
+ template <typename Result>\r
+ static inline void apply(Result & res)\r
+ {\r
+ update<F2, F1, D>(res);\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char D, bool Transpose, typename Result>\r
+inline void update(Result & res)\r
+{\r
+ update_result_dispatch<F1, F2, D, Transpose>::apply(res);\r
+}\r
+\r
+// may_update\r
+\r
+template <field F1, field F2, char D, typename Result>\r
+inline bool may_update(Result const& res)\r
+{\r
+ return res.template may_update<F1, F2, D>();\r
+}\r
+\r
+template <field F1, field F2, char D, bool Transpose>\r
+struct may_update_result_dispatch\r
+{\r
+ template <typename Result>\r
+ static inline bool apply(Result const& res)\r
+ {\r
+ return may_update<F1, F2, D>(res);\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char D>\r
+struct may_update_result_dispatch<F1, F2, D, true>\r
+{\r
+ template <typename Result>\r
+ static inline bool apply(Result const& res)\r
+ {\r
+ return may_update<F2, F1, D>(res);\r
+ }\r
+};\r
+\r
+template <field F1, field F2, char D, bool Transpose, typename Result>\r
+inline bool may_update(Result const& res)\r
+{\r
+ return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);\r
+}\r
+\r
+// result_dimension\r
+\r
+template <typename Geometry>\r
+struct result_dimension\r
+{\r
+ BOOST_STATIC_ASSERT(geometry::dimension<Geometry>::value >= 0);\r
+ static const char value\r
+ = ( geometry::dimension<Geometry>::value <= 9 ) ?\r
+ ( '0' + geometry::dimension<Geometry>::value ) :\r
+ 'T';\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/util/has_nan_coordinate.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate {\r
+\r
+// TODO: change the name for e.g. something with the word "exterior"\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type>\r
+struct topology_check\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+//template <typename Point>\r
+//struct topology_check<Point, point_tag>\r
+//{\r
+// static const char interior = '0';\r
+// static const char boundary = 'F';\r
+//\r
+// static const bool has_interior = true;\r
+// static const bool has_boundary = false;\r
+//\r
+// topology_check(Point const&) {}\r
+// template <typename IgnoreBoundaryPoint>\r
+// topology_check(Point const&, IgnoreBoundaryPoint const&) {}\r
+//};\r
+\r
+template <typename Linestring>\r
+struct topology_check<Linestring, linestring_tag>\r
+{\r
+ static const char interior = '1';\r
+ static const char boundary = '0';\r
+\r
+ bool has_interior;\r
+ bool has_boundary;\r
+\r
+ topology_check(Linestring const& ls)\r
+ {\r
+ init(ls, 0); /*dummy param*/\r
+ }\r
+\r
+ template <typename IgnoreBoundaryPoint>\r
+ topology_check(Linestring const& ls, IgnoreBoundaryPoint const& ibp)\r
+ {\r
+ init(ls, ibp); /*dummy param, won't be used*/\r
+ }\r
+\r
+ // Even if some point is on the boundary, if the Linestring has the boundary,\r
+ // there will be second boundary point different than IgnoreBoundaryPoint\r
+ template <typename IgnoreBoundaryPoint>\r
+ void init(Linestring const& ls, IgnoreBoundaryPoint const&)\r
+ {\r
+ std::size_t count = boost::size(ls);\r
+ has_interior = count > 0;\r
+ // NOTE: Linestring with all points equal is treated as 1d linear ring\r
+ has_boundary = count > 1\r
+ && ! detail::equals::equals_point_point(range::front(ls), range::back(ls));\r
+ }\r
+};\r
+\r
+template <typename MultiLinestring>\r
+struct topology_check<MultiLinestring, multi_linestring_tag>\r
+{\r
+ static const char interior = '1';\r
+ static const char boundary = '0';\r
+\r
+ bool has_interior;\r
+ bool has_boundary;\r
+\r
+ topology_check(MultiLinestring const& mls)\r
+ {\r
+ init(mls, not_ignoring_counter());\r
+ }\r
+\r
+ template <typename IgnoreBoundaryPoint>\r
+ topology_check(MultiLinestring const& mls, IgnoreBoundaryPoint const& ibp)\r
+ {\r
+ init(mls, ignoring_counter<IgnoreBoundaryPoint>(ibp));\r
+ }\r
+\r
+ template <typename OddCounter>\r
+ void init(MultiLinestring const& mls, OddCounter const& odd_counter)\r
+ {\r
+ typedef typename geometry::point_type<MultiLinestring>::type point_type;\r
+ std::vector<point_type> endpoints;\r
+ endpoints.reserve(boost::size(mls) * 2);\r
+\r
+ typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;\r
+ for ( ls_iterator it = boost::begin(mls) ; it != boost::end(mls) ; ++it )\r
+ {\r
+ typename boost::range_reference<MultiLinestring const>::type\r
+ ls = *it;\r
+\r
+ std::size_t count = boost::size(ls);\r
+\r
+ if (count > 0)\r
+ {\r
+ has_interior = true;\r
+ }\r
+\r
+ if (count > 1)\r
+ {\r
+ typedef typename boost::range_reference\r
+ <\r
+ typename boost::range_value<MultiLinestring const>::type const\r
+ >::type point_reference;\r
+ \r
+ point_reference front_pt = range::front(ls);\r
+ point_reference back_pt = range::back(ls);\r
+\r
+ // don't store boundaries of linear rings, this doesn't change anything\r
+ if (! equals::equals_point_point(front_pt, back_pt))\r
+ {\r
+ // do not add points containing NaN coordinates\r
+ // because they cannot be reasonably compared, e.g. with MSVC\r
+ // an assertion failure is reported in std::equal_range()\r
+ // NOTE: currently ignoring_counter calling std::equal_range()\r
+ // is not used anywhere in the code, still it's safer this way\r
+ if (! geometry::has_nan_coordinate(front_pt))\r
+ {\r
+ endpoints.push_back(front_pt);\r
+ }\r
+ if (! geometry::has_nan_coordinate(back_pt))\r
+ {\r
+ endpoints.push_back(back_pt);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ has_boundary = false;\r
+\r
+ if ( !endpoints.empty() )\r
+ {\r
+ std::sort(endpoints.begin(), endpoints.end(), geometry::less<point_type>());\r
+ has_boundary = odd_counter(endpoints.begin(), endpoints.end());\r
+ }\r
+ }\r
+\r
+ struct not_ignoring_counter\r
+ {\r
+ template <typename It>\r
+ bool operator()(It first, It last) const\r
+ {\r
+ return find_odd_count(first, last);\r
+ }\r
+ };\r
+\r
+ template <typename Point>\r
+ struct ignoring_counter\r
+ {\r
+ ignoring_counter(Point const& pt) : m_pt(pt) {}\r
+\r
+ template <typename It>\r
+ bool operator()(It first, It last) const\r
+ {\r
+ typedef typename std::iterator_traits<It>::value_type point_type;\r
+\r
+ std::pair<It, It> ignore_range\r
+ = std::equal_range(first, last, m_pt,\r
+ geometry::less<point_type>());\r
+\r
+ if ( find_odd_count(first, ignore_range.first) )\r
+ return true;\r
+\r
+ return find_odd_count(ignore_range.second, last);\r
+ }\r
+\r
+ Point const& m_pt;\r
+ };\r
+\r
+ template <typename It>\r
+ static inline bool find_odd_count(It first, It last)\r
+ {\r
+ if ( first == last )\r
+ return false;\r
+\r
+ std::size_t count = 1;\r
+ It prev = first;\r
+ ++first;\r
+ for ( ; first != last ; ++first, ++prev )\r
+ {\r
+ // the end of the equal points subrange\r
+ if ( ! equals::equals_point_point(*first, *prev) )\r
+ {\r
+ if ( count % 2 != 0 )\r
+ return true;\r
+\r
+ count = 1;\r
+ }\r
+ else\r
+ {\r
+ ++count;\r
+ }\r
+ }\r
+\r
+ return count % 2 != 0;\r
+ }\r
+};\r
+\r
+template <typename Ring>\r
+struct topology_check<Ring, ring_tag>\r
+{\r
+ static const char interior = '2';\r
+ static const char boundary = '1';\r
+ static const bool has_interior = true;\r
+ static const bool has_boundary = true;\r
+\r
+ topology_check(Ring const&) {}\r
+ template <typename P>\r
+ topology_check(Ring const&, P const&) {}\r
+};\r
+\r
+template <typename Polygon>\r
+struct topology_check<Polygon, polygon_tag>\r
+{\r
+ static const char interior = '2';\r
+ static const char boundary = '1';\r
+ static const bool has_interior = true;\r
+ static const bool has_boundary = true;\r
+\r
+ topology_check(Polygon const&) {}\r
+ template <typename P>\r
+ topology_check(Polygon const&, P const&) {}\r
+};\r
+\r
+template <typename MultiPolygon>\r
+struct topology_check<MultiPolygon, multi_polygon_tag>\r
+{\r
+ static const char interior = '2';\r
+ static const char boundary = '1';\r
+ static const bool has_interior = true;\r
+ static const bool has_boundary = true;\r
+\r
+ topology_check(MultiPolygon const&) {}\r
+ template <typename P>\r
+ topology_check(MultiPolygon const&, P const&) {}\r
+};\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+\r
+#include <boost/type_traits/is_base_of.hpp>\r
+\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate { namespace turns {\r
+\r
+template <bool IncludeDegenerate = false>\r
+struct assign_policy\r
+ : overlay::assign_null_policy\r
+{\r
+ static bool const include_degenerate = IncludeDegenerate;\r
+};\r
+\r
+// GET_TURNS\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename GetTurnPolicy = detail::get_turns::get_turn_info_type\r
+ <\r
+ Geometry1, Geometry2, assign_policy<>\r
+ >,\r
+ typename RobustPolicy = detail::no_rescale_policy\r
+>\r
+struct get_turns\r
+{\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+\r
+ typedef overlay::turn_info\r
+ <\r
+ point1_type,\r
+ typename segment_ratio_type<point1_type, RobustPolicy>::type,\r
+ typename detail::get_turns::turn_operation_type\r
+ <\r
+ Geometry1, Geometry2,\r
+ typename segment_ratio_type\r
+ <\r
+ point1_type, RobustPolicy\r
+ >::type\r
+ >::type\r
+ > turn_info;\r
+\r
+ template <typename Turns>\r
+ static inline void apply(Turns & turns,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ detail::get_turns::no_interrupt_policy interrupt_policy;\r
+\r
+ apply(turns, geometry1, geometry2, interrupt_policy);\r
+ }\r
+\r
+ template <typename Turns, typename InterruptPolicy>\r
+ static inline void apply(Turns & turns,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ InterruptPolicy & interrupt_policy)\r
+ {\r
+ RobustPolicy robust_policy = geometry::get_rescale_policy\r
+ <\r
+ RobustPolicy\r
+ >(geometry1, geometry2);\r
+\r
+ apply(turns, geometry1, geometry2, interrupt_policy, robust_policy);\r
+ }\r
+\r
+ template <typename Turns, typename InterruptPolicy>\r
+ static inline void apply(Turns & turns,\r
+ Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ InterruptPolicy & interrupt_policy,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ static const bool reverse1 = detail::overlay::do_reverse\r
+ <\r
+ geometry::point_order<Geometry1>::value\r
+ >::value;\r
+\r
+ static const bool reverse2 = detail::overlay::do_reverse\r
+ <\r
+ geometry::point_order<Geometry2>::value\r
+ >::value;\r
+\r
+ dispatch::get_turns\r
+ <\r
+ typename geometry::tag<Geometry1>::type,\r
+ typename geometry::tag<Geometry2>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ reverse1,\r
+ reverse2,\r
+ GetTurnPolicy\r
+ >::apply(0, geometry1, 1, geometry2,\r
+ robust_policy, turns, interrupt_policy);\r
+ }\r
+};\r
+\r
+// TURNS SORTING AND SEARCHING\r
+\r
+template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>\r
+struct op_to_int\r
+{\r
+ template <typename Operation>\r
+ inline int operator()(Operation const& op) const\r
+ {\r
+ switch(op.operation)\r
+ {\r
+ case detail::overlay::operation_none : return N;\r
+ case detail::overlay::operation_union : return U;\r
+ case detail::overlay::operation_intersection : return I;\r
+ case detail::overlay::operation_blocked : return B;\r
+ case detail::overlay::operation_continue : return C;\r
+ case detail::overlay::operation_opposite : return O;\r
+ }\r
+ return -1;\r
+ }\r
+};\r
+\r
+template <std::size_t OpId, typename OpToInt>\r
+struct less_op_xxx_linear\r
+{\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ static OpToInt op_to_int;\r
+ return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]);\r
+ }\r
+};\r
+\r
+template <std::size_t OpId>\r
+struct less_op_linear_linear\r
+ : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >\r
+{};\r
+\r
+template <std::size_t OpId>\r
+struct less_op_linear_areal_single\r
+{\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+ static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;\r
+ static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;\r
+\r
+ segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;\r
+ segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;\r
+\r
+ typedef typename Turn::turn_operation_type operation_type;\r
+ operation_type const& left_operation = left.operations[OpId];\r
+ operation_type const& right_operation = right.operations[OpId];\r
+\r
+ if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )\r
+ {\r
+ return op_to_int_xuic(left_operation)\r
+ < op_to_int_xuic(right_operation);\r
+ }\r
+ else\r
+ {\r
+ return op_to_int_xiuc(left_operation)\r
+ < op_to_int_xiuc(right_operation);\r
+ }\r
+ }\r
+};\r
+\r
+template <std::size_t OpId>\r
+struct less_op_areal_linear\r
+ : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> >\r
+{};\r
+\r
+template <std::size_t OpId>\r
+struct less_op_areal_areal\r
+{\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+ static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc;\r
+ static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc;\r
+\r
+ segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;\r
+ segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;\r
+\r
+ typedef typename Turn::turn_operation_type operation_type;\r
+ operation_type const& left_operation = left.operations[OpId];\r
+ operation_type const& right_operation = right.operations[OpId];\r
+\r
+ if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )\r
+ {\r
+ if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )\r
+ {\r
+ return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);\r
+ }\r
+ else\r
+ {\r
+ if ( left_other_seg_id.ring_index == -1 )\r
+ {\r
+ if ( left_operation.operation == overlay::operation_union )\r
+ return false;\r
+ else if ( left_operation.operation == overlay::operation_intersection )\r
+ return true;\r
+ }\r
+ else if ( right_other_seg_id.ring_index == -1 )\r
+ {\r
+ if ( right_operation.operation == overlay::operation_union )\r
+ return true;\r
+ else if ( right_operation.operation == overlay::operation_intersection )\r
+ return false;\r
+ }\r
+ \r
+ return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);\r
+ }\r
+ }\r
+};\r
+\r
+template <std::size_t OpId>\r
+struct less_other_multi_index\r
+{\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ return left.operations[other_op_id].seg_id.multi_index\r
+ < right.operations[other_op_id].seg_id.multi_index;\r
+ }\r
+};\r
+\r
+// sort turns by G1 - source_index == 0 by:\r
+// seg_id -> distance -> operation\r
+template <std::size_t OpId = 0,\r
+ typename LessOp = less_op_xxx_linear< OpId, op_to_int<> > >\r
+struct less\r
+{\r
+ BOOST_STATIC_ASSERT(OpId < 2);\r
+\r
+ template <typename Turn>\r
+ static inline bool use_fraction(Turn const& left, Turn const& right)\r
+ {\r
+ static LessOp less_op;\r
+\r
+ return\r
+ geometry::math::equals(left.operations[OpId].fraction,\r
+ right.operations[OpId].fraction)\r
+ ?\r
+ less_op(left, right)\r
+ :\r
+ (left.operations[OpId].fraction < right.operations[OpId].fraction)\r
+ ;\r
+ }\r
+\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ segment_identifier const& sl = left.operations[OpId].seg_id;\r
+ segment_identifier const& sr = right.operations[OpId].seg_id;\r
+\r
+ return sl < sr || ( sl == sr && use_fraction(left, right) );\r
+ }\r
+};\r
+\r
+}}} // namespace detail::relate::turns\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATION_INTERFACE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace relate\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix, false>\r
+{\r
+ typedef matrix_handler<geometry::de9im::matrix> type;\r
+};\r
+\r
+\r
+}} // namespace detail::relate\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct relation\r
+{\r
+ template <typename Matrix>\r
+ static inline Matrix apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ assert_dimension_equal<Geometry1, Geometry2>();\r
+\r
+ typename detail::relate::result_handler_type\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ Matrix\r
+ >::type handler;\r
+\r
+ dispatch::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, handler);\r
+\r
+ return handler.result();\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename Matrix>\r
+ struct visitor : boost::static_visitor<Matrix>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+\r
+ visitor(Geometry2 const& geometry2)\r
+ : m_geometry2(geometry2) {}\r
+\r
+ template <typename Geometry1>\r
+ Matrix operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return relation<Geometry1, Geometry2>\r
+ ::template apply<Matrix>(geometry1, m_geometry2);\r
+ }\r
+ };\r
+\r
+ template <typename Matrix>\r
+ static inline Matrix\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor<Matrix>(geometry2), geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Matrix>\r
+ struct visitor : boost::static_visitor<Matrix>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+\r
+ visitor(Geometry1 const& geometry1)\r
+ : m_geometry1(geometry1) {}\r
+\r
+ template <typename Geometry2>\r
+ Matrix operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return relation<Geometry1, Geometry2>\r
+ ::template apply<Matrix>(m_geometry1, geometry2);\r
+ }\r
+ };\r
+\r
+ template <typename Matrix>\r
+ static inline Matrix\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor<Matrix>(geometry1), geometry2);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct relation\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+ >\r
+{\r
+ template <typename Matrix>\r
+ struct visitor : boost::static_visitor<Matrix>\r
+ {\r
+ template <typename Geometry1, typename Geometry2>\r
+ Matrix operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return relation<Geometry1, Geometry2>\r
+ ::template apply<Matrix>(geometry1, geometry2);\r
+ }\r
+ };\r
+\r
+ template <typename Matrix>\r
+ static inline Matrix\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor<Matrix>(), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Calculates the relation between a pair of geometries as defined in DE-9IM.\r
+\ingroup relation\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return The DE-9IM matrix expressing the relation between geometries.\r
+\r
+\qbk{[include reference/algorithms/relation.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline de9im::matrix relation(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::relation\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::template apply<de9im::matrix>(geometry1, geometry2);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP\r
+\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/flattening.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace detail\r
+{\r
+\r
+template <typename T>\r
+struct result_inverse\r
+{\r
+ void set(T const& d, T const& a)\r
+ {\r
+ distance = d;\r
+ azimuth = a;\r
+ }\r
+\r
+ T distance;\r
+ T azimuth;\r
+};\r
+\r
+}}} // namespace boost::geometry::detail\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RESULT_INVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP\r
+\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER)\r
+#include <iostream>\r
+#endif\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+// Ring Identifier. It is currently: source,multi,ring\r
+struct ring_identifier\r
+{\r
+\r
+ inline ring_identifier()\r
+ : source_index(-1)\r
+ , multi_index(-1)\r
+ , ring_index(-1)\r
+ {}\r
+\r
+ inline ring_identifier(signed_size_type src,\r
+ signed_size_type mul,\r
+ signed_size_type rin)\r
+ : source_index(src)\r
+ , multi_index(mul)\r
+ , ring_index(rin)\r
+ {}\r
+\r
+ inline bool operator<(ring_identifier const& other) const\r
+ {\r
+ return source_index != other.source_index ? source_index < other.source_index\r
+ : multi_index !=other.multi_index ? multi_index < other.multi_index\r
+ : ring_index < other.ring_index\r
+ ;\r
+ }\r
+\r
+ inline bool operator==(ring_identifier const& other) const\r
+ {\r
+ return source_index == other.source_index\r
+ && ring_index == other.ring_index\r
+ && multi_index == other.multi_index\r
+ ;\r
+ }\r
+\r
+ inline bool operator!=(ring_identifier const& other) const\r
+ {\r
+ return ! operator==(other);\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER)\r
+ friend std::ostream& operator<<(std::ostream &os, ring_identifier const& ring_id)\r
+ {\r
+ os << "(s:" << ring_id.source_index;\r
+ if (ring_id.ring_index >= 0) os << ", r:" << ring_id.ring_index;\r
+ if (ring_id.multi_index >= 0) os << ", m:" << ring_id.multi_index;\r
+ os << ")";\r
+ return os;\r
+ }\r
+#endif\r
+\r
+\r
+ signed_size_type source_index;\r
+ signed_size_type multi_index;\r
+ signed_size_type ring_index;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace section\r
+{\r
+\r
+\r
+template <typename Range, typename Section>\r
+struct full_section_range\r
+{\r
+ static inline Range const& apply(Range const& range, Section const& )\r
+ {\r
+ return range;\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon, typename Section>\r
+struct full_section_polygon\r
+{\r
+ static inline typename ring_return_type<Polygon const>::type apply(Polygon const& polygon, Section const& section)\r
+ {\r
+ return section.ring_id.ring_index < 0\r
+ ? geometry::exterior_ring(polygon)\r
+ : range::at(geometry::interior_rings(polygon),\r
+ static_cast<std::size_t>(section.ring_id.ring_index));\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename MultiGeometry,\r
+ typename Section,\r
+ typename Policy\r
+>\r
+struct full_section_multi\r
+{\r
+ static inline typename ring_return_type<MultiGeometry const>::type apply(\r
+ MultiGeometry const& multi, Section const& section)\r
+ {\r
+ typedef typename boost::range_size<MultiGeometry>::type size_type;\r
+\r
+ BOOST_GEOMETRY_ASSERT\r
+ (\r
+ section.ring_id.multi_index >= 0\r
+ && size_type(section.ring_id.multi_index) < boost::size(multi)\r
+ );\r
+\r
+ return Policy::apply(range::at(multi, size_type(section.ring_id.multi_index)), section);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::section\r
+#endif\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Geometry,\r
+ typename Section\r
+>\r
+struct range_by_section\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+template <typename LineString, typename Section>\r
+struct range_by_section<linestring_tag, LineString, Section>\r
+ : detail::section::full_section_range<LineString, Section>\r
+{};\r
+\r
+\r
+template <typename Ring, typename Section>\r
+struct range_by_section<ring_tag, Ring, Section>\r
+ : detail::section::full_section_range<Ring, Section>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Section>\r
+struct range_by_section<polygon_tag, Polygon, Section>\r
+ : detail::section::full_section_polygon<Polygon, Section>\r
+{};\r
+\r
+\r
+template <typename MultiPolygon, typename Section>\r
+struct range_by_section<multi_polygon_tag, MultiPolygon, Section>\r
+ : detail::section::full_section_multi\r
+ <\r
+ MultiPolygon,\r
+ Section,\r
+ detail::section::full_section_polygon\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type,\r
+ Section\r
+ >\r
+ >\r
+{};\r
+\r
+template <typename MultiLinestring, typename Section>\r
+struct range_by_section<multi_linestring_tag, MultiLinestring, Section>\r
+ : detail::section::full_section_multi\r
+ <\r
+ MultiLinestring,\r
+ Section,\r
+ detail::section::full_section_range\r
+ <\r
+ typename boost::range_value<MultiLinestring>::type,\r
+ Section\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+ \brief Get full ring (exterior, one of interiors, one from multi)\r
+ indicated by the specified section\r
+ \ingroup sectionalize\r
+ \tparam Geometry type\r
+ \tparam Section type of section to get from\r
+ \param geometry geometry to take section of\r
+ \param section structure with section\r
+ */\r
+template <typename Geometry, typename Section>\r
+inline typename ring_return_type<Geometry const>::type\r
+ range_by_section(Geometry const& geometry, Section const& section)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::range_by_section\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ Section\r
+ >::apply(geometry, section);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace section\r
+{\r
+\r
+struct get_section_box\r
+{\r
+ template <typename Box, typename Section>\r
+ static inline void apply(Box& total, Section const& section)\r
+ {\r
+ geometry::expand(total, section.bounding_box);\r
+ }\r
+};\r
+\r
+struct overlaps_section_box\r
+{\r
+ template <typename Box, typename Section>\r
+ static inline bool apply(Box const& box, Section const& section)\r
+ {\r
+ return ! detail::disjoint::disjoint_box_box(box, section.bounding_box);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::section\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTION_BOX_POLICIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace section\r
+{\r
+\r
+template\r
+<\r
+ std::size_t Dimension,\r
+ typename Point,\r
+ typename RobustBox,\r
+ typename RobustPolicy\r
+>\r
+static inline bool preceding(int dir, Point const& point,\r
+ RobustBox const& robust_box,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+ typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;\r
+ geometry::recalculate(robust_point, point, robust_policy);\r
+ return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box))\r
+ || (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));\r
+}\r
+\r
+template\r
+<\r
+ std::size_t Dimension,\r
+ typename Point,\r
+ typename RobustBox,\r
+ typename RobustPolicy\r
+>\r
+static inline bool exceeding(int dir, Point const& point,\r
+ RobustBox const& robust_box,\r
+ RobustPolicy const& robust_policy)\r
+{\r
+ typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;\r
+ geometry::recalculate(robust_point, point, robust_policy);\r
+ return (dir == 1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box))\r
+ || (dir == -1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box));\r
+}\r
+\r
+\r
+}} // namespace detail::section\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_FUNCTIONS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP\r
+\r
+#include <cstddef>\r
+#include <vector>\r
+\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/vector_c.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/static_assert.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>\r
+#include <boost/geometry/algorithms/detail/signed_size_type.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Structure containing section information\r
+ \details Section information consists of a bounding box, direction\r
+ information (if it is increasing or decreasing, per dimension),\r
+ index information (begin-end, ring, multi) and the number of\r
+ segments in this section\r
+\r
+ \tparam Box box-type\r
+ \tparam DimensionCount number of dimensions for this section\r
+ \ingroup sectionalize\r
+ */\r
+template\r
+<\r
+ typename Box,\r
+ std::size_t DimensionCount\r
+>\r
+struct section\r
+{\r
+ typedef Box box_type;\r
+ static std::size_t const dimension_count = DimensionCount;\r
+\r
+ int directions[DimensionCount];\r
+ ring_identifier ring_id;\r
+ Box bounding_box;\r
+\r
+ // NOTE: size_type could be passed as template parameter\r
+ // NOTE: these probably also could be of type std::size_t\r
+ signed_size_type begin_index;\r
+ signed_size_type end_index;\r
+ std::size_t count;\r
+ std::size_t range_count;\r
+ bool duplicate;\r
+ signed_size_type non_duplicate_index;\r
+\r
+ bool is_non_duplicate_first;\r
+ bool is_non_duplicate_last;\r
+\r
+ inline section()\r
+ : begin_index(-1)\r
+ , end_index(-1)\r
+ , count(0)\r
+ , range_count(0)\r
+ , duplicate(false)\r
+ , non_duplicate_index(-1)\r
+ , is_non_duplicate_first(false)\r
+ , is_non_duplicate_last(false)\r
+ {\r
+ assign_inverse(bounding_box);\r
+ for (std::size_t i = 0; i < DimensionCount; i++)\r
+ {\r
+ directions[i] = 0;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Structure containing a collection of sections\r
+ \note Derived from a vector, proves to be faster than of deque\r
+ \note vector might be templated in the future\r
+ \ingroup sectionalize\r
+ */\r
+template <typename Box, std::size_t DimensionCount>\r
+struct sections : std::vector<section<Box, DimensionCount> >\r
+{\r
+ typedef Box box_type;\r
+ static std::size_t const value = DimensionCount;\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace sectionalize\r
+{\r
+\r
+template\r
+<\r
+ typename DimensionVector,\r
+ std::size_t Index,\r
+ std::size_t Count\r
+>\r
+struct get_direction_loop\r
+{\r
+ typedef typename boost::mpl::at_c<DimensionVector, Index>::type dimension;\r
+\r
+ template <typename Segment>\r
+ static inline void apply(Segment const& seg,\r
+ int directions[Count])\r
+ {\r
+ typedef typename coordinate_type<Segment>::type coordinate_type;\r
+\r
+ coordinate_type const diff =\r
+ geometry::get<1, dimension::value>(seg)\r
+ - geometry::get<0, dimension::value>(seg);\r
+\r
+ coordinate_type zero = coordinate_type();\r
+ directions[Index] = diff > zero ? 1 : diff < zero ? -1 : 0;\r
+\r
+ get_direction_loop\r
+ <\r
+ DimensionVector,\r
+ Index + 1,\r
+ Count\r
+ >::apply(seg, directions);\r
+ }\r
+};\r
+\r
+template <typename DimensionVector, std::size_t Count>\r
+struct get_direction_loop<DimensionVector, Count, Count>\r
+{\r
+ template <typename Segment>\r
+ static inline void apply(Segment const&, int [Count])\r
+ {}\r
+};\r
+\r
+//! Copy one static array to another\r
+template <typename T, std::size_t Index, std::size_t Count>\r
+struct copy_loop\r
+{\r
+ static inline void apply(T const source[Count], T target[Count])\r
+ {\r
+ target[Index] = source[Index];\r
+ copy_loop<T, Index + 1, Count>::apply(source, target);\r
+ }\r
+};\r
+\r
+template <typename T, std::size_t Count>\r
+struct copy_loop<T, Count, Count>\r
+{\r
+ static inline void apply(T const [Count], T [Count])\r
+ {}\r
+};\r
+\r
+//! Compare two static arrays\r
+template <typename T, std::size_t Index, std::size_t Count>\r
+struct compare_loop\r
+{\r
+ static inline bool apply(T const array1[Count], T const array2[Count])\r
+ {\r
+ return array1[Index] != array2[Index]\r
+ ? false\r
+ : compare_loop\r
+ <\r
+ T, Index + 1, Count\r
+ >::apply(array1, array2);\r
+ }\r
+};\r
+\r
+template <typename T, std::size_t Count>\r
+struct compare_loop<T, Count, Count>\r
+{\r
+ static inline bool apply(T const [Count], T const [Count])\r
+ {\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template <std::size_t Dimension, std::size_t DimensionCount>\r
+struct check_duplicate_loop\r
+{\r
+ template <typename Segment>\r
+ static inline bool apply(Segment const& seg)\r
+ {\r
+ if (! geometry::math::equals\r
+ (\r
+ geometry::get<0, Dimension>(seg),\r
+ geometry::get<1, Dimension>(seg)\r
+ )\r
+ )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return check_duplicate_loop\r
+ <\r
+ Dimension + 1, DimensionCount\r
+ >::apply(seg);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct check_duplicate_loop<DimensionCount, DimensionCount>\r
+{\r
+ template <typename Segment>\r
+ static inline bool apply(Segment const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+//! Assign a value to a static array\r
+template <typename T, std::size_t Index, std::size_t Count>\r
+struct assign_loop\r
+{\r
+ static inline void apply(T dims[Count], T const value)\r
+ {\r
+ dims[Index] = value;\r
+ assign_loop<T, Index + 1, Count>::apply(dims, value);\r
+ }\r
+};\r
+\r
+template <typename T, std::size_t Count>\r
+struct assign_loop<T, Count, Count>\r
+{\r
+ static inline void apply(T [Count], T const)\r
+ {\r
+ }\r
+};\r
+\r
+template <typename CSTag>\r
+struct box_first_in_section\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box & box, Point const& prev, Point const& curr)\r
+ {\r
+ geometry::model::referring_segment<Point const> seg(prev, curr);\r
+ geometry::envelope(seg, box);\r
+ }\r
+};\r
+\r
+template <>\r
+struct box_first_in_section<cartesian_tag>\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box & box, Point const& prev, Point const& curr)\r
+ {\r
+ geometry::envelope(prev, box);\r
+ geometry::expand(box, curr);\r
+ }\r
+};\r
+\r
+template <typename CSTag>\r
+struct box_next_in_section\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box & box, Point const& prev, Point const& curr)\r
+ {\r
+ geometry::model::referring_segment<Point const> seg(prev, curr);\r
+ geometry::expand(box, seg);\r
+ }\r
+};\r
+\r
+template <>\r
+struct box_next_in_section<cartesian_tag>\r
+{\r
+ template <typename Box, typename Point>\r
+ static inline void apply(Box & box, Point const& , Point const& curr)\r
+ {\r
+ geometry::expand(box, curr);\r
+ }\r
+};\r
+\r
+/// @brief Helper class to create sections of a part of a range, on the fly\r
+template\r
+<\r
+ typename Point,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize_part\r
+{\r
+ static const std::size_t dimension_count\r
+ = boost::mpl::size<DimensionVector>::value;\r
+\r
+ template\r
+ <\r
+ typename Iterator,\r
+ typename RobustPolicy,\r
+ typename Sections\r
+ >\r
+ static inline void apply(Sections& sections,\r
+ Iterator begin, Iterator end,\r
+ RobustPolicy const& robust_policy,\r
+ ring_identifier ring_id,\r
+ std::size_t max_count)\r
+ {\r
+ boost::ignore_unused_variable_warning(robust_policy);\r
+\r
+ typedef typename boost::range_value<Sections>::type section_type;\r
+ BOOST_STATIC_ASSERT\r
+ (\r
+ (static_cast<std::size_t>(section_type::dimension_count)\r
+ == static_cast<std::size_t>(boost::mpl::size<DimensionVector>::value))\r
+ );\r
+\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ Point,\r
+ RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ std::size_t const count = std::distance(begin, end);\r
+ if (count == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ signed_size_type index = 0;\r
+ signed_size_type ndi = 0; // non duplicate index\r
+ section_type section;\r
+\r
+ bool mark_first_non_duplicated = true;\r
+ std::size_t last_non_duplicate_index = sections.size();\r
+\r
+ Iterator it = begin;\r
+ robust_point_type previous_robust_point;\r
+ geometry::recalculate(previous_robust_point, *it, robust_policy);\r
+ \r
+ for(Iterator previous = it++;\r
+ it != end;\r
+ ++previous, ++it, index++)\r
+ {\r
+ robust_point_type current_robust_point;\r
+ geometry::recalculate(current_robust_point, *it, robust_policy);\r
+ model::referring_segment<robust_point_type> robust_segment(\r
+ previous_robust_point, current_robust_point);\r
+\r
+ int direction_classes[dimension_count] = {0};\r
+ get_direction_loop\r
+ <\r
+ DimensionVector, 0, dimension_count\r
+ >::apply(robust_segment, direction_classes);\r
+\r
+ // if "dir" == 0 for all point-dimensions, it is duplicate.\r
+ // Those sections might be omitted, if wished, lateron\r
+ bool duplicate = false;\r
+\r
+ if (direction_classes[0] == 0)\r
+ {\r
+ // Recheck because ALL dimensions should be checked,\r
+ // not only first one.\r
+ // (dimension_count might be < dimension<P>::value)\r
+ if (check_duplicate_loop\r
+ <\r
+ 0, geometry::dimension<Point>::type::value\r
+ >::apply(robust_segment)\r
+ )\r
+ {\r
+ duplicate = true;\r
+\r
+ // Change direction-info to force new section\r
+ // Note that wo consecutive duplicate segments will generate\r
+ // only one duplicate-section.\r
+ // Actual value is not important as long as it is not -1,0,1\r
+ assign_loop\r
+ <\r
+ int, 0, dimension_count\r
+ >::apply(direction_classes, -99);\r
+ }\r
+ }\r
+\r
+ if (section.count > 0\r
+ && (! compare_loop\r
+ <\r
+ int, 0, dimension_count\r
+ >::apply(direction_classes, section.directions)\r
+ || section.count > max_count)\r
+ )\r
+ {\r
+ if (! section.duplicate)\r
+ {\r
+ last_non_duplicate_index = sections.size();\r
+ }\r
+\r
+ sections.push_back(section);\r
+ section = section_type();\r
+ }\r
+\r
+ if (section.count == 0)\r
+ {\r
+ section.begin_index = index;\r
+ section.ring_id = ring_id;\r
+ section.duplicate = duplicate;\r
+ section.non_duplicate_index = ndi;\r
+ section.range_count = count;\r
+\r
+ if (mark_first_non_duplicated && ! duplicate)\r
+ {\r
+ section.is_non_duplicate_first = true;\r
+ mark_first_non_duplicated = false;\r
+ }\r
+\r
+ copy_loop\r
+ <\r
+ int, 0, dimension_count\r
+ >::apply(direction_classes, section.directions);\r
+\r
+ // In cartesian this is envelope of previous point expanded with current point\r
+ // in non-cartesian this is envelope of a segment\r
+ box_first_in_section<typename cs_tag<robust_point_type>::type>\r
+ ::apply(section.bounding_box, previous_robust_point, current_robust_point);\r
+ }\r
+ else\r
+ {\r
+ // In cartesian this is expand with current point\r
+ // in non-cartesian this is expand with a segment\r
+ box_next_in_section<typename cs_tag<robust_point_type>::type>\r
+ ::apply(section.bounding_box, previous_robust_point, current_robust_point);\r
+ }\r
+\r
+ section.end_index = index + 1;\r
+ section.count++;\r
+ if (! duplicate)\r
+ {\r
+ ndi++;\r
+ }\r
+ previous_robust_point = current_robust_point;\r
+ }\r
+\r
+ // Add last section if applicable\r
+ if (section.count > 0)\r
+ {\r
+ if (! section.duplicate)\r
+ {\r
+ last_non_duplicate_index = sections.size();\r
+ }\r
+\r
+ sections.push_back(section);\r
+ }\r
+\r
+ if (last_non_duplicate_index < sections.size()\r
+ && ! sections[last_non_duplicate_index].duplicate)\r
+ {\r
+ sections[last_non_duplicate_index].is_non_duplicate_last = true;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ closure_selector Closure,\r
+ bool Reverse,\r
+ typename Point,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize_range\r
+{\r
+ template\r
+ <\r
+ typename Range,\r
+ typename RobustPolicy,\r
+ typename Sections\r
+ >\r
+ static inline void apply(Range const& range,\r
+ RobustPolicy const& robust_policy,\r
+ Sections& sections,\r
+ ring_identifier ring_id,\r
+ std::size_t max_count)\r
+ {\r
+ typedef typename closeable_view<Range const, Closure>::type cview_type;\r
+ typedef typename reversible_view\r
+ <\r
+ cview_type const,\r
+ Reverse ? iterate_reverse : iterate_forward\r
+ >::type view_type;\r
+\r
+ cview_type cview(range);\r
+ view_type view(cview);\r
+\r
+ std::size_t const n = boost::size(view);\r
+ if (n == 0)\r
+ {\r
+ // Zero points, no section\r
+ return;\r
+ }\r
+\r
+ if (n == 1)\r
+ {\r
+ // Line with one point ==> no sections\r
+ return;\r
+ }\r
+\r
+ sectionalize_part<Point, DimensionVector>::apply(sections,\r
+ boost::begin(view), boost::end(view),\r
+ robust_policy, ring_id, max_count);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize_polygon\r
+{\r
+ template\r
+ <\r
+ typename Polygon,\r
+ typename RobustPolicy,\r
+ typename Sections\r
+ >\r
+ static inline void apply(Polygon const& poly,\r
+ RobustPolicy const& robust_policy,\r
+ Sections& sections,\r
+ ring_identifier ring_id, std::size_t max_count)\r
+ {\r
+ typedef typename point_type<Polygon>::type point_type;\r
+ typedef sectionalize_range\r
+ <\r
+ closure<Polygon>::value, Reverse,\r
+ point_type, DimensionVector\r
+ > per_range;\r
+\r
+ ring_id.ring_index = -1;\r
+ per_range::apply(exterior_ring(poly), robust_policy, sections, ring_id, max_count);\r
+\r
+ ring_id.ring_index++;\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(poly);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)\r
+ {\r
+ per_range::apply(*it, robust_policy, sections, ring_id, max_count);\r
+ }\r
+ }\r
+};\r
+\r
+template <typename DimensionVector>\r
+struct sectionalize_box\r
+{\r
+ template\r
+ <\r
+ typename Box,\r
+ typename RobustPolicy,\r
+ typename Sections\r
+ >\r
+ static inline void apply(Box const& box,\r
+ RobustPolicy const& robust_policy,\r
+ Sections& sections,\r
+ ring_identifier const& ring_id, std::size_t max_count)\r
+ {\r
+ typedef typename point_type<Box>::type point_type;\r
+\r
+ assert_dimension<Box, 2>();\r
+\r
+ // Add all four sides of the 2D-box as separate section.\r
+ // Easiest is to convert it to a polygon.\r
+ // However, we don't have the polygon type\r
+ // (or polygon would be a helper-type).\r
+ // Therefore we mimic a linestring/std::vector of 5 points\r
+\r
+ // TODO: might be replaced by assign_box_corners_oriented\r
+ // or just "convert"\r
+ point_type ll, lr, ul, ur;\r
+ geometry::detail::assign_box_corners(box, ll, lr, ul, ur);\r
+\r
+ std::vector<point_type> points;\r
+ points.push_back(ll);\r
+ points.push_back(ul);\r
+ points.push_back(ur);\r
+ points.push_back(lr);\r
+ points.push_back(ll);\r
+\r
+ sectionalize_range\r
+ <\r
+ closed, false,\r
+ point_type,\r
+ DimensionVector\r
+ >::apply(points, robust_policy, sections,\r
+ ring_id, max_count);\r
+ }\r
+};\r
+\r
+template <typename DimensionVector, typename Policy>\r
+struct sectionalize_multi\r
+{\r
+ template\r
+ <\r
+ typename MultiGeometry,\r
+ typename RobustPolicy,\r
+ typename Sections\r
+ >\r
+ static inline void apply(MultiGeometry const& multi,\r
+ RobustPolicy const& robust_policy,\r
+ Sections& sections, ring_identifier ring_id, std::size_t max_count)\r
+ {\r
+ ring_id.multi_index = 0;\r
+ for (typename boost::range_iterator<MultiGeometry const>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it, ++ring_id.multi_index)\r
+ {\r
+ Policy::apply(*it, robust_policy, sections, ring_id, max_count);\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Sections>\r
+inline void enlarge_sections(Sections& sections)\r
+{\r
+ // Robustness issue. Increase sections a tiny bit such that all points are really within (and not on border)\r
+ // Reason: turns might, rarely, be missed otherwise (case: "buffer_mp1")\r
+ // Drawback: not really, range is now completely inside the section. Section is a tiny bit too large,\r
+ // which might cause (a small number) of more comparisons\r
+ \r
+ // NOTE: above is old comment to the not used code expanding the Boxes by relaxed_epsilon(10)\r
+ \r
+ // Enlarge sections by scaled epsilon, this should be consistent with math::equals().\r
+ // Points and Segments are equal-compared WRT machine epsilon, but Boxes aren't\r
+ // Enlarging Boxes ensures that they correspond to the bound objects,\r
+ // Segments in this case, since Sections are collections of Segments.\r
+ for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);\r
+ it != boost::end(sections);\r
+ ++it)\r
+ {\r
+ detail::expand_by_epsilon(it->bounding_box);\r
+ }\r
+}\r
+\r
+\r
+}} // namespace detail::sectionalize\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Geometry,\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+template\r
+<\r
+ typename Box,\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize<box_tag, Box, Reverse, DimensionVector>\r
+ : detail::sectionalize::sectionalize_box<DimensionVector>\r
+{};\r
+\r
+template\r
+<\r
+ typename LineString,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize\r
+ <\r
+ linestring_tag,\r
+ LineString,\r
+ false,\r
+ DimensionVector\r
+ >\r
+ : detail::sectionalize::sectionalize_range\r
+ <\r
+ closed, false,\r
+ typename point_type<LineString>::type,\r
+ DimensionVector\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename Ring,\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize<ring_tag, Ring, Reverse, DimensionVector>\r
+ : detail::sectionalize::sectionalize_range\r
+ <\r
+ geometry::closure<Ring>::value, Reverse,\r
+ typename point_type<Ring>::type,\r
+ DimensionVector\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename Polygon,\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize<polygon_tag, Polygon, Reverse, DimensionVector>\r
+ : detail::sectionalize::sectionalize_polygon\r
+ <\r
+ Reverse, DimensionVector\r
+ >\r
+{};\r
+\r
+template\r
+<\r
+ typename MultiPolygon,\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize<multi_polygon_tag, MultiPolygon, Reverse, DimensionVector>\r
+ : detail::sectionalize::sectionalize_multi\r
+ <\r
+ DimensionVector,\r
+ detail::sectionalize::sectionalize_polygon\r
+ <\r
+ Reverse,\r
+ DimensionVector\r
+ >\r
+ >\r
+\r
+{};\r
+\r
+template\r
+<\r
+ typename MultiLinestring,\r
+ bool Reverse,\r
+ typename DimensionVector\r
+>\r
+struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVector>\r
+ : detail::sectionalize::sectionalize_multi\r
+ <\r
+ DimensionVector,\r
+ detail::sectionalize::sectionalize_range\r
+ <\r
+ closed, false,\r
+ typename point_type<MultiLinestring>::type,\r
+ DimensionVector\r
+ >\r
+ >\r
+\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+ \brief Split a geometry into monotonic sections\r
+ \ingroup sectionalize\r
+ \tparam Geometry type of geometry to check\r
+ \tparam Sections type of sections to create\r
+ \param geometry geometry to create sections from\r
+ \param robust_policy policy to handle robustness issues\r
+ \param sections structure with sections\r
+ \param source_index index to assign to the ring_identifiers\r
+ \param max_count maximal number of points per section\r
+ (defaults to 10, this seems to give the fastest results)\r
+\r
+ */\r
+template\r
+<\r
+ bool Reverse,\r
+ typename DimensionVector,\r
+ typename Geometry,\r
+ typename Sections,\r
+ typename RobustPolicy\r
+>\r
+inline void sectionalize(Geometry const& geometry,\r
+ RobustPolicy const& robust_policy,\r
+ Sections& sections,\r
+ int source_index = 0,\r
+ std::size_t max_count = 10)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ typedef typename boost::range_value<Sections>::type section_type;\r
+\r
+ // Compiletime check for point type of section boxes\r
+ // and point type related to robust policy\r
+ typedef typename geometry::coordinate_type\r
+ <\r
+ typename section_type::box_type\r
+ >::type ctype1;\r
+ typedef typename geometry::coordinate_type\r
+ <\r
+ typename geometry::robust_point_type\r
+ <\r
+ typename geometry::point_type<Geometry>::type,\r
+ RobustPolicy\r
+ >::type\r
+ >::type ctype2;\r
+\r
+ BOOST_MPL_ASSERT((boost::is_same<ctype1, ctype2>));\r
+\r
+\r
+ sections.clear();\r
+\r
+ ring_identifier ring_id;\r
+ ring_id.source_index = source_index;\r
+\r
+ dispatch::sectionalize\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ Reverse,\r
+ DimensionVector\r
+ >::apply(geometry, robust_policy, sections, ring_id, max_count);\r
+\r
+ detail::sectionalize::enlarge_sections(sections);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP\r
+\r
+\r
+#include <cstddef>\r
+#include <boost/type_traits/make_signed.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+typedef boost::make_signed<std::size_t>::type signed_size_type;\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SIGNED_SIZE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_base_of.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch {\r
+\r
+// Returns single geometry by Id\r
+// for single geometries returns the geometry itself\r
+template <typename Geometry,\r
+ bool IsMulti = boost::is_base_of\r
+ <\r
+ multi_tag,\r
+ typename geometry::tag<Geometry>::type\r
+ >::value\r
+>\r
+struct single_geometry\r
+{\r
+ typedef Geometry & return_type;\r
+\r
+ template <typename Id>\r
+ static inline return_type apply(Geometry & g, Id const& ) { return g; }\r
+};\r
+\r
+// for multi geometries returns one of the stored single geometries\r
+template <typename Geometry>\r
+struct single_geometry<Geometry, true>\r
+{\r
+ typedef typename boost::range_reference<Geometry>::type return_type;\r
+\r
+ template <typename Id>\r
+ static inline return_type apply(Geometry & g, Id const& id)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(id.multi_index >= 0);\r
+ typedef typename boost::range_size<Geometry>::type size_type;\r
+ return range::at(g, static_cast<size_type>(id.multi_index));\r
+ }\r
+};\r
+\r
+} // namespace detail_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail {\r
+\r
+template <typename Geometry>\r
+struct single_geometry_return_type\r
+{\r
+ typedef typename detail_dispatch::single_geometry<Geometry>::return_type type;\r
+};\r
+\r
+template <typename Geometry, typename Id>\r
+inline\r
+typename single_geometry_return_type<Geometry>::type\r
+single_geometry(Geometry & geometry, Id const& id)\r
+{\r
+ return detail_dispatch::single_geometry<Geometry>::apply(geometry, id);\r
+}\r
+\r
+template <typename Geometry, typename Id>\r
+inline\r
+typename single_geometry_return_type<Geometry const>::type\r
+single_geometry(Geometry const& geometry, Id const& id)\r
+{\r
+ return detail_dispatch::single_geometry<Geometry const>::apply(geometry, id);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SINGLE_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP\r
+\r
+#include <boost/mpl/if.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch {\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type,\r
+ bool IsMulti = boost::is_base_of<multi_tag, Tag>::value>\r
+struct sub_range : not_implemented<Tag>\r
+{};\r
+\r
+template <typename Geometry, typename Tag>\r
+struct sub_range<Geometry, Tag, false>\r
+{\r
+ typedef Geometry & return_type;\r
+\r
+ template <typename Id> static inline\r
+ return_type apply(Geometry & geometry, Id const&)\r
+ {\r
+ return geometry;\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct sub_range<Geometry, polygon_tag, false>\r
+{\r
+ typedef typename geometry::ring_return_type<Geometry>::type return_type;\r
+\r
+ template <typename Id> static inline\r
+ return_type apply(Geometry & geometry, Id const& id)\r
+ {\r
+ if ( id.ring_index < 0 )\r
+ {\r
+ return geometry::exterior_ring(geometry);\r
+ }\r
+ else\r
+ {\r
+ typedef typename boost::range_size\r
+ <\r
+ typename geometry::interior_type<Geometry>::type\r
+ >::type size_type;\r
+ size_type const ri = static_cast<size_type>(id.ring_index);\r
+ return range::at(geometry::interior_rings(geometry), ri);\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Geometry, typename Tag>\r
+struct sub_range<Geometry, Tag, true>\r
+{\r
+ typedef typename boost::range_value<Geometry>::type value_type;\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ boost::is_const<Geometry>::value,\r
+ typename boost::add_const<value_type>::type,\r
+ value_type\r
+ >::type sub_type;\r
+\r
+ typedef detail_dispatch::sub_range<sub_type> sub_sub_range;\r
+\r
+ // TODO: shouldn't it be return_type?\r
+ typedef typename sub_sub_range::return_type return_type;\r
+\r
+ template <typename Id> static inline\r
+ return_type apply(Geometry & geometry, Id const& id)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(0 <= id.multi_index);\r
+ typedef typename boost::range_size<Geometry>::type size_type;\r
+ size_type const mi = static_cast<size_type>(id.multi_index);\r
+ return sub_sub_range::apply(range::at(geometry, mi), id);\r
+ }\r
+};\r
+\r
+} // namespace detail_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+namespace detail {\r
+\r
+template <typename Geometry>\r
+struct sub_range_return_type\r
+{\r
+ typedef typename detail_dispatch::sub_range<Geometry>::return_type type;\r
+};\r
+\r
+// This function also works for geometry::segment_identifier\r
+\r
+template <typename Geometry, typename Id> inline\r
+typename sub_range_return_type<Geometry>::type\r
+sub_range(Geometry & geometry, Id const& id)\r
+{\r
+ return detail_dispatch::sub_range<Geometry>::apply(geometry, id);\r
+}\r
+\r
+template <typename Geometry, typename Id> inline\r
+typename sub_range_return_type<Geometry const>::type\r
+sub_range(Geometry const& geometry, Id const& id)\r
+{\r
+ return detail_dispatch::sub_range<Geometry const>::apply(geometry, id);\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace sweep\r
+{\r
+\r
+struct no_interrupt_policy\r
+{\r
+ static bool const enabled = false;\r
+\r
+ template <typename Event>\r
+ static inline bool apply(Event const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+}} // namespace detail::sweep\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+template\r
+<\r
+ typename Range,\r
+ typename PriorityQueue,\r
+ typename InitializationVisitor,\r
+ typename EventVisitor,\r
+ typename InterruptPolicy\r
+>\r
+inline void sweep(Range const& range, PriorityQueue& queue,\r
+ InitializationVisitor& initialization_visitor,\r
+ EventVisitor& event_visitor,\r
+ InterruptPolicy const& interrupt_policy)\r
+{\r
+ typedef typename PriorityQueue::value_type event_type;\r
+\r
+ initialization_visitor.apply(range, queue, event_visitor);\r
+ while (! queue.empty())\r
+ {\r
+ event_type event = queue.top();\r
+ queue.pop();\r
+ event_visitor.apply(event, queue);\r
+ if (interrupt_policy.enabled && interrupt_policy.apply(event))\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ boost::ignore_unused(interrupt_policy);\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Range,\r
+ typename PriorityQueue,\r
+ typename InitializationVisitor,\r
+ typename EventVisitor\r
+>\r
+inline void sweep(Range const& range, PriorityQueue& queue,\r
+ InitializationVisitor& initialization_visitor,\r
+ EventVisitor& event_visitor)\r
+{\r
+ sweep(range, queue, initialization_visitor, event_visitor,\r
+ detail::sweep::no_interrupt_policy());\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP\r
+\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/flattening.hpp>\r
+#include <boost/geometry/algorithms/detail/result_inverse.hpp>\r
+\r
+namespace boost { namespace geometry { namespace detail\r
+{\r
+\r
+/*!\r
+\brief The solution of the inverse problem of geodesics on latlong coordinates,\r
+ Forsyth-Andoyer-Lambert type approximation with second order terms.\r
+\author See\r
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965\r
+ http://www.dtic.mil/docs/citations/AD0627893\r
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970\r
+ http://www.dtic.mil/docs/citations/AD703541\r
+*/\r
+template <typename CT, bool EnableDistance, bool EnableAzimuth>\r
+struct thomas_inverse\r
+{\r
+ typedef result_inverse<CT> result_type;\r
+\r
+ template <typename T1, typename T2, typename Spheroid>\r
+ static inline result_type apply(T1 const& lon1,\r
+ T1 const& lat1,\r
+ T2 const& lon2,\r
+ T2 const& lat2,\r
+ Spheroid const& spheroid)\r
+ {\r
+ result_type result;\r
+\r
+ // coordinates in radians\r
+\r
+ if ( math::equals(lon1, lon2)\r
+ && math::equals(lat1, lat2) )\r
+ {\r
+ result.set(CT(0), CT(0));\r
+ return result;\r
+ }\r
+\r
+ CT const f = detail::flattening<CT>(spheroid);\r
+ CT const one_minus_f = CT(1) - f;\r
+\r
+// CT const tan_theta1 = one_minus_f * tan(lat1);\r
+// CT const tan_theta2 = one_minus_f * tan(lat2);\r
+// CT const theta1 = atan(tan_theta1);\r
+// CT const theta2 = atan(tan_theta2);\r
+\r
+ CT const pi_half = math::pi<CT>() / CT(2);\r
+ CT const theta1 = math::equals(lat1, pi_half) ? lat1 :\r
+ math::equals(lat1, -pi_half) ? lat1 :\r
+ atan(one_minus_f * tan(lat1));\r
+ CT const theta2 = math::equals(lat2, pi_half) ? lat2 :\r
+ math::equals(lat2, -pi_half) ? lat2 :\r
+ atan(one_minus_f * tan(lat2));\r
+\r
+ CT const theta_m = (theta1 + theta2) / CT(2);\r
+ CT const d_theta_m = (theta2 - theta1) / CT(2);\r
+ CT const d_lambda = lon2 - lon1;\r
+ CT const d_lambda_m = d_lambda / CT(2);\r
+\r
+ CT const sin_theta_m = sin(theta_m);\r
+ CT const cos_theta_m = cos(theta_m);\r
+ CT const sin_d_theta_m = sin(d_theta_m);\r
+ CT const cos_d_theta_m = cos(d_theta_m);\r
+ CT const sin2_theta_m = math::sqr(sin_theta_m);\r
+ CT const cos2_theta_m = math::sqr(cos_theta_m);\r
+ CT const sin2_d_theta_m = math::sqr(sin_d_theta_m);\r
+ CT const cos2_d_theta_m = math::sqr(cos_d_theta_m);\r
+ CT const sin_d_lambda_m = sin(d_lambda_m);\r
+ CT const sin2_d_lambda_m = math::sqr(sin_d_lambda_m);\r
+\r
+ CT const H = cos2_theta_m - sin2_d_theta_m;\r
+ CT const L = sin2_d_theta_m + H * sin2_d_lambda_m;\r
+ CT const cos_d = CT(1) - CT(2) * L;\r
+ CT const d = acos(cos_d);\r
+ CT const sin_d = sin(d);\r
+\r
+ CT const one_minus_L = CT(1) - L;\r
+\r
+ if ( math::equals(sin_d, CT(0))\r
+ || math::equals(L, CT(0))\r
+ || math::equals(one_minus_L, CT(0)) )\r
+ {\r
+ result.set(CT(0), CT(0));\r
+ return result;\r
+ }\r
+\r
+ CT const U = CT(2) * sin2_theta_m * cos2_d_theta_m / one_minus_L;\r
+ CT const V = CT(2) * sin2_d_theta_m * cos2_theta_m / L;\r
+ CT const X = U + V;\r
+ CT const Y = U - V;\r
+ CT const T = d / sin_d;\r
+ //CT const D = CT(4) * math::sqr(T);\r
+ //CT const E = CT(2) * cos_d;\r
+ //CT const A = D * E;\r
+ //CT const B = CT(2) * D;\r
+ //CT const C = T - (A - E) / CT(2);\r
+ \r
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )\r
+ {\r
+ //CT const n1 = X * (A + C*X);\r
+ //CT const n2 = Y * (B + E*Y);\r
+ //CT const n3 = D*X*Y;\r
+\r
+ //CT const f_sqr = math::sqr(f);\r
+ //CT const f_sqr_per_64 = f_sqr / CT(64);\r
+\r
+ CT const delta1d = f * (T*X-Y) / CT(4);\r
+ //CT const delta2d = f_sqr_per_64 * (n1 - n2 + n3);\r
+\r
+ CT const a = get_radius<0>(spheroid);\r
+\r
+ result.distance = a * sin_d * (T - delta1d);\r
+ //double S2 = a * sin_d * (T - delta1d + delta2d);\r
+ }\r
+ else\r
+ {\r
+ result.distance = CT(0);\r
+ }\r
+ \r
+ if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )\r
+ {\r
+ // NOTE: if both cos_latX == 0 then below we'd have 0 * INF\r
+ // it's a situation when the endpoints are on the poles +-90 deg\r
+ // in this case the azimuth could either be 0 or +-pi\r
+ // but above always 0 is returned\r
+\r
+ // may also be used to calculate distance21\r
+ //CT const D = CT(4) * math::sqr(T);\r
+ CT const E = CT(2) * cos_d;\r
+ //CT const A = D * E;\r
+ //CT const B = CT(2) * D;\r
+ // may also be used to calculate distance21\r
+ CT const f_sqr = math::sqr(f);\r
+ CT const f_sqr_per_64 = f_sqr / CT(64);\r
+\r
+ CT const F = CT(2)*Y-E*(CT(4)-X);\r
+ //CT const M = CT(32)*T-(CT(20)*T-A)*X-(B+CT(4))*Y;\r
+ CT const G = f*T/CT(2) + f_sqr_per_64;\r
+ CT const tan_d_lambda = tan(d_lambda);\r
+ CT const Q = -(F*G*tan_d_lambda) / CT(4);\r
+\r
+ CT const d_lambda_p = (d_lambda + Q) / CT(2);\r
+ CT const tan_d_lambda_p = tan(d_lambda_p);\r
+\r
+ CT const v = atan2(cos_d_theta_m, sin_theta_m * tan_d_lambda_p);\r
+ CT const u = atan2(-sin_d_theta_m, cos_theta_m * tan_d_lambda_p);\r
+\r
+ CT const pi = math::pi<CT>();\r
+ CT alpha1 = v + u;\r
+ if ( alpha1 > pi )\r
+ {\r
+ alpha1 -= CT(2) * pi;\r
+ }\r
+\r
+ result.azimuth = alpha1;\r
+ }\r
+ else\r
+ {\r
+ result.azimuth = CT(0);\r
+ }\r
+\r
+ return result;\r
+ }\r
+};\r
+\r
+}}} // namespace boost::geometry::detail\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THOMAS_INVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP\r
+\r
+#include <boost/geometry/core/exception.hpp>\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+\r
+// BSG 2012-02-06: we use this currently only for distance.\r
+// For other scalar results area,length,perimeter it is commented on purpose.\r
+// Reason is that for distance there is no other choice. distance of two\r
+// empty geometries (or one empty) should NOT return any value.\r
+// But for area it is no problem to be 0.\r
+// Suppose: area(intersection(a,b)). We (probably) don't want a throw there...\r
+\r
+// So decided that at least for Boost 1.49 this is commented for\r
+// scalar results, except distance.\r
+\r
+#if defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)\r
+#include <boost/core/ignore_unused.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Geometry>\r
+inline void throw_on_empty_input(Geometry const& geometry)\r
+{\r
+#if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)\r
+ if (geometry::is_empty(geometry))\r
+ {\r
+ throw empty_input_exception();\r
+ }\r
+#else\r
+ boost::ignore_unused(geometry);\r
+#endif\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_COMPARE_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_COMPARE_TURNS_HPP\r
+\r
+#include <cstddef>\r
+#include <functional>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace turns\r
+{\r
+\r
+// TURNS SORTING AND SEARCHING\r
+\r
+// sort turns by G1 - source_index == 0 by:\r
+// seg_id -> fraction -> other_id -> operation\r
+template\r
+<\r
+ typename IdLess = std::less<signed_size_type>,\r
+ int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0,\r
+ std::size_t OpId = 0\r
+>\r
+struct less_seg_fraction_other_op\r
+{\r
+ BOOST_STATIC_ASSERT(OpId < 2);\r
+ static const std::size_t other_op_id = (OpId + 1) % 2;\r
+\r
+ template <typename Op>\r
+ static inline int order_op(Op const& op)\r
+ {\r
+ switch (op.operation)\r
+ {\r
+ case detail::overlay::operation_none : return N;\r
+ case detail::overlay::operation_union : return U;\r
+ case detail::overlay::operation_intersection : return I;\r
+ case detail::overlay::operation_blocked : return B;\r
+ case detail::overlay::operation_continue : return C;\r
+ case detail::overlay::operation_opposite : return O;\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ template <typename Op>\r
+ static inline bool use_operation(Op const& left, Op const& right)\r
+ {\r
+ return order_op(left) < order_op(right);\r
+ }\r
+\r
+ template <typename Turn>\r
+ static inline bool use_other_id(Turn const& left, Turn const& right)\r
+ {\r
+ segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;\r
+ segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;\r
+\r
+ if ( left_other_seg_id.multi_index != right_other_seg_id.multi_index )\r
+ {\r
+ return left_other_seg_id.multi_index < right_other_seg_id.multi_index;\r
+ }\r
+ if ( left_other_seg_id.ring_index != right_other_seg_id.ring_index )\r
+ {\r
+ return left_other_seg_id.ring_index != right_other_seg_id.ring_index;\r
+ }\r
+ if ( left_other_seg_id.segment_index != right_other_seg_id.segment_index )\r
+ {\r
+ return IdLess()(left_other_seg_id.segment_index,\r
+ right_other_seg_id.segment_index);\r
+ }\r
+ return use_operation(left.operations[OpId], right.operations[OpId]);\r
+ }\r
+\r
+ template <typename Turn>\r
+ static inline bool use_fraction(Turn const& left, Turn const& right)\r
+ {\r
+ return\r
+ geometry::math::equals(left.operations[OpId].fraction,\r
+ right.operations[OpId].fraction)\r
+ ?\r
+ use_other_id(left, right)\r
+ :\r
+ (left.operations[OpId].fraction < right.operations[OpId].fraction)\r
+ ;\r
+ }\r
+\r
+ template <typename Turn>\r
+ inline bool operator()(Turn const& left, Turn const& right) const\r
+ {\r
+ segment_identifier const& sl = left.operations[OpId].seg_id;\r
+ segment_identifier const& sr = right.operations[OpId].seg_id;\r
+\r
+ return sl < sr || ( sl == sr && use_fraction(left, right) );\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+\r
+}} // namespace detail::turns\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_COMPARE_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_DEBUG_TURN_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_DEBUG_TURN_HPP\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_TURNS\r
+#include <iostream>\r
+#include <string>\r
+\r
+#include <boost/algorithm/string/predicate.hpp>\r
+\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+#endif // BOOST_GEOMETRY_DEBUG_TURNS\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace turns\r
+{\r
+\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_TURNS\r
+template <typename Turn, typename Operation>\r
+inline void debug_turn(Turn const& turn, Operation op,\r
+ std::string const& header)\r
+{\r
+ std::cout << header\r
+ << " at " << op.seg_id\r
+ << " meth: " << method_char(turn.method)\r
+ << " op: " << operation_char(op.operation)\r
+ << " of: " << operation_char(turn.operations[0].operation)\r
+ << operation_char(turn.operations[1].operation)\r
+ << " " << geometry::wkt(turn.point)\r
+ << std::endl;\r
+\r
+ if (boost::contains(header, "Finished"))\r
+ {\r
+ std::cout << std::endl;\r
+ }\r
+}\r
+#else\r
+template <typename Turn, typename Operation>\r
+inline void debug_turn(Turn const& , Operation, const char*)\r
+{\r
+}\r
+#endif // BOOST_GEOMETRY_DEBUG_TURNS\r
+\r
+\r
+}} // namespace detail::turns\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost:geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_DEBUG_TURN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_FILTER_CONTINUE_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_FILTER_CONTINUE_TURNS_HPP\r
+\r
+#include <algorithm>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace turns\r
+{\r
+\r
+\r
+template <typename Turns, bool Enable>\r
+struct filter_continue_turns\r
+{\r
+ static inline void apply(Turns&) {}\r
+};\r
+\r
+\r
+template <typename Turns>\r
+class filter_continue_turns<Turns, true>\r
+{\r
+private:\r
+ class IsContinueTurn\r
+ {\r
+ private:\r
+ template <typename Operation>\r
+ inline bool is_continue_or_opposite(Operation const& operation) const\r
+ {\r
+ return operation == detail::overlay::operation_continue\r
+ || operation == detail::overlay::operation_opposite;\r
+ }\r
+\r
+ public:\r
+ template <typename Turn>\r
+ bool operator()(Turn const& turn) const\r
+ {\r
+ if ( turn.method != detail::overlay::method_collinear\r
+ && turn.method != detail::overlay::method_equal )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return is_continue_or_opposite(turn.operations[0].operation)\r
+ && is_continue_or_opposite(turn.operations[1].operation);\r
+ }\r
+ };\r
+\r
+\r
+public:\r
+ static inline void apply(Turns& turns)\r
+ {\r
+ turns.erase( std::remove_if(turns.begin(), turns.end(),\r
+ IsContinueTurn()),\r
+ turns.end()\r
+ );\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::turns\r
+\r
+}} // namespect boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_FILTER_CONTINUE_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_PRINT_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_PRINT_TURNS_HPP\r
+\r
+#include <algorithm>\r
+#include <iostream>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace turns\r
+{\r
+\r
+struct turn_printer\r
+{\r
+ turn_printer(std::ostream & os)\r
+ : index(0)\r
+ , out(os)\r
+ {}\r
+\r
+ template <typename Turn>\r
+ void operator()(Turn const& turn)\r
+ {\r
+ out << index\r
+ << ": " << geometry::method_char(turn.method);\r
+\r
+ if ( turn.discarded )\r
+ out << " (discarded)\n";\r
+ else if ( turn.blocked() )\r
+ out << " (blocked)\n";\r
+ else\r
+ out << '\n';\r
+\r
+ double fraction[2];\r
+\r
+ fraction[0] = turn.operations[0].fraction.numerator()\r
+ / turn.operations[0].fraction.denominator();\r
+\r
+ out << geometry::operation_char(turn.operations[0].operation)\r
+ <<": seg: " << turn.operations[0].seg_id.source_index\r
+ << ", m: " << turn.operations[0].seg_id.multi_index\r
+ << ", r: " << turn.operations[0].seg_id.ring_index\r
+ << ", s: " << turn.operations[0].seg_id.segment_index;\r
+ out << ", fr: " << fraction[0];\r
+ out << ", col?: " << turn.operations[0].is_collinear;\r
+ out << ' ' << geometry::dsv(turn.point) << ' ';\r
+\r
+ out << '\n';\r
+\r
+ fraction[1] = turn.operations[1].fraction.numerator()\r
+ / turn.operations[1].fraction.denominator();\r
+\r
+ out << geometry::operation_char(turn.operations[1].operation)\r
+ << ": seg: " << turn.operations[1].seg_id.source_index\r
+ << ", m: " << turn.operations[1].seg_id.multi_index\r
+ << ", r: " << turn.operations[1].seg_id.ring_index\r
+ << ", s: " << turn.operations[1].seg_id.segment_index;\r
+ out << ", fr: " << fraction[1];\r
+ out << ", col?: " << turn.operations[1].is_collinear;\r
+ out << ' ' << geometry::dsv(turn.point) << ' ';\r
+\r
+ ++index;\r
+ out << std::endl;\r
+ }\r
+\r
+ int index;\r
+ std::ostream & out;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Turns>\r
+static inline void print_turns(Geometry1 const& g1,\r
+ Geometry2 const& g2,\r
+ Turns const& turns)\r
+{\r
+ std::cout << geometry::wkt(g1) << std::endl;\r
+ std::cout << geometry::wkt(g2) << std::endl;\r
+\r
+ std::for_each(boost::begin(turns), boost::end(turns), turn_printer(std::cout));\r
+}\r
+\r
+\r
+\r
+\r
+}} // namespace detail::turns\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_PRINT_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP\r
+\r
+#include <algorithm>\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace turns\r
+{\r
+\r
+template <typename Turns, bool Enable>\r
+struct remove_duplicate_turns\r
+{\r
+ static inline void apply(Turns&) {}\r
+};\r
+\r
+\r
+\r
+template <typename Turns>\r
+class remove_duplicate_turns<Turns, true>\r
+{\r
+private:\r
+ struct TurnEqualsTo\r
+ {\r
+ template <typename Turn>\r
+ bool operator()(Turn const& t1, Turn const& t2) const\r
+ {\r
+ return geometry::equals(t1.point, t2.point)\r
+ && t1.operations[0].seg_id == t2.operations[0].seg_id\r
+ && t1.operations[1].seg_id == t2.operations[1].seg_id;\r
+ }\r
+ };\r
+\r
+public:\r
+ static inline void apply(Turns& turns)\r
+ {\r
+ turns.erase( std::unique(turns.begin(), turns.end(),\r
+ TurnEqualsTo()),\r
+ turns.end()\r
+ );\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::turns\r
+\r
+}} // namespect boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP\r
+\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/flattening.hpp>\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS\r
+#define BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS 1000\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry { namespace detail\r
+{\r
+\r
+template <typename T>\r
+struct result_direct\r
+{\r
+ void set(T const& lo2, T const& la2)\r
+ {\r
+ lon2 = lo2;\r
+ lat2 = la2;\r
+ }\r
+ T lon2;\r
+ T lat2;\r
+};\r
+\r
+/*!\r
+\brief The solution of the direct problem of geodesics on latlong coordinates, after Vincenty, 1975\r
+\author See\r
+ - http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf\r
+ - http://www.icsm.gov.au/gda/gdav2.3.pdf\r
+\author Adapted from various implementations to get it close to the original document\r
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html\r
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html\r
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink\r
+\r
+*/\r
+template <typename CT>\r
+struct vincenty_direct\r
+{\r
+ typedef result_direct<CT> result_type;\r
+\r
+public:\r
+ template <typename T, typename Dist, typename Azi, typename Spheroid>\r
+ static inline result_type apply(T const& lo1,\r
+ T const& la1,\r
+ Dist const& distance,\r
+ Azi const& azimuth12,\r
+ Spheroid const& spheroid)\r
+ {\r
+ result_type result;\r
+\r
+ CT const lon1 = lo1;\r
+ CT const lat1 = la1;\r
+\r
+ if ( math::equals(distance, Dist(0)) || distance < Dist(0) )\r
+ {\r
+ result.set(lon1, lat1);\r
+ return result;\r
+ }\r
+\r
+ CT const radius_a = CT(get_radius<0>(spheroid));\r
+ CT const radius_b = CT(get_radius<2>(spheroid));\r
+ CT const flattening = geometry::detail::flattening<CT>(spheroid);\r
+\r
+ CT const sin_azimuth12 = sin(azimuth12);\r
+ CT const cos_azimuth12 = cos(azimuth12);\r
+\r
+ // U: reduced latitude, defined by tan U = (1-f) tan phi\r
+ CT const one_min_f = CT(1) - flattening;\r
+ CT const tan_U1 = one_min_f * tan(lat1);\r
+ CT const sigma1 = atan2(tan_U1, cos_azimuth12); // (1)\r
+\r
+ // may be calculated from tan using 1 sqrt()\r
+ CT const U1 = atan(tan_U1);\r
+ CT const sin_U1 = sin(U1);\r
+ CT const cos_U1 = cos(U1);\r
+\r
+ CT const sin_alpha = cos_U1 * sin_azimuth12; // (2)\r
+ CT const sin_alpha_sqr = math::sqr(sin_alpha);\r
+ CT const cos_alpha_sqr = CT(1) - sin_alpha_sqr;\r
+\r
+ CT const b_sqr = radius_b * radius_b;\r
+ CT const u_sqr = cos_alpha_sqr * (radius_a * radius_a - b_sqr) / b_sqr;\r
+ CT const A = CT(1) + (u_sqr/CT(16384)) * (CT(4096) + u_sqr*(CT(-768) + u_sqr*(CT(320) - u_sqr*CT(175)))); // (3)\r
+ CT const B = (u_sqr/CT(1024))*(CT(256) + u_sqr*(CT(-128) + u_sqr*(CT(74) - u_sqr*CT(47)))); // (4)\r
+\r
+ CT s_div_bA = distance / (radius_b * A);\r
+ CT sigma = s_div_bA; // (7)\r
+\r
+ CT previous_sigma;\r
+ CT sin_sigma;\r
+ CT cos_sigma;\r
+ CT cos_2sigma_m;\r
+ CT cos_2sigma_m_sqr;\r
+\r
+ int counter = 0; // robustness\r
+\r
+ do\r
+ {\r
+ previous_sigma = sigma;\r
+\r
+ CT const two_sigma_m = CT(2) * sigma1 + sigma; // (5)\r
+\r
+ sin_sigma = sin(sigma);\r
+ cos_sigma = cos(sigma);\r
+ CT const sin_sigma_sqr = math::sqr(sin_sigma);\r
+ cos_2sigma_m = cos(two_sigma_m);\r
+ cos_2sigma_m_sqr = math::sqr(cos_2sigma_m);\r
+\r
+ CT const delta_sigma = B * sin_sigma * (cos_2sigma_m\r
+ + (B/CT(4)) * ( cos_sigma * (CT(-1) + CT(2)*cos_2sigma_m_sqr)\r
+ - (B/CT(6) * cos_2sigma_m * (CT(-3)+CT(4)*sin_sigma_sqr) * (CT(-3)+CT(4)*cos_2sigma_m_sqr)) )); // (6)\r
+\r
+ sigma = s_div_bA + delta_sigma; // (7)\r
+\r
+ ++counter; // robustness\r
+\r
+ } while ( geometry::math::abs(previous_sigma - sigma) > CT(1e-12)\r
+ //&& geometry::math::abs(sigma) < pi\r
+ && counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness\r
+\r
+ {\r
+ result.lat2\r
+ = atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12,\r
+ one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8)\r
+ }\r
+\r
+ {\r
+ CT const lambda = atan2( sin_sigma * sin_azimuth12,\r
+ cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9)\r
+ CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10)\r
+ CT const L = lambda - (CT(1) - C) * flattening * sin_alpha\r
+ * ( sigma + C * sin_sigma * ( cos_2sigma_m + C * cos_sigma * ( CT(-1) + CT(2) * cos_2sigma_m_sqr ) ) ); // (11)\r
+\r
+ result.lon2 = lon1 + L;\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ /*\r
+ inline CT azimuth21() const\r
+ {\r
+ // NOTE: signs of X and Y are different than in the original paper\r
+ return is_distance_zero ?\r
+ CT(0) :\r
+ atan2(-sin_alpha, sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12); // (12)\r
+ }\r
+ */\r
+};\r
+\r
+}}} // namespace boost::geometry::detail\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_DIRECT_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP\r
+\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/flattening.hpp>\r
+#include <boost/geometry/algorithms/detail/result_inverse.hpp>\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS\r
+#define BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS 1000\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry { namespace detail\r
+{\r
+\r
+/*!\r
+\brief The solution of the inverse problem of geodesics on latlong coordinates, after Vincenty, 1975\r
+\author See\r
+ - http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf\r
+ - http://www.icsm.gov.au/gda/gdav2.3.pdf\r
+\author Adapted from various implementations to get it close to the original document\r
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html\r
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html\r
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink\r
+\r
+*/\r
+template <typename CT, bool EnableDistance, bool EnableAzimuth>\r
+struct vincenty_inverse\r
+{\r
+ typedef result_inverse<CT> result_type;\r
+\r
+public:\r
+ template <typename T1, typename T2, typename Spheroid>\r
+ static inline result_type apply(T1 const& lon1,\r
+ T1 const& lat1,\r
+ T2 const& lon2,\r
+ T2 const& lat2,\r
+ Spheroid const& spheroid)\r
+ {\r
+ result_type result;\r
+\r
+ if (math::equals(lat1, lat2) && math::equals(lon1, lon2))\r
+ {\r
+ result.set(CT(0), CT(0));\r
+ return result;\r
+ }\r
+\r
+ CT const c1 = 1;\r
+ CT const c2 = 2;\r
+ CT const c3 = 3;\r
+ CT const c4 = 4;\r
+ CT const c16 = 16;\r
+ CT const c_e_12 = CT(1e-12);\r
+\r
+ CT const pi = geometry::math::pi<CT>();\r
+ CT const two_pi = c2 * pi;\r
+\r
+ // lambda: difference in longitude on an auxiliary sphere\r
+ CT L = lon2 - lon1;\r
+ CT lambda = L;\r
+\r
+ if (L < -pi) L += two_pi;\r
+ if (L > pi) L -= two_pi;\r
+\r
+ CT const radius_a = CT(get_radius<0>(spheroid));\r
+ CT const radius_b = CT(get_radius<2>(spheroid));\r
+ CT const flattening = geometry::detail::flattening<CT>(spheroid);\r
+\r
+ // U: reduced latitude, defined by tan U = (1-f) tan phi\r
+ CT const one_min_f = c1 - flattening;\r
+ CT const tan_U1 = one_min_f * tan(lat1); // above (1)\r
+ CT const tan_U2 = one_min_f * tan(lat2); // above (1)\r
+\r
+ // calculate sin U and cos U using trigonometric identities\r
+ CT const temp_den_U1 = math::sqrt(c1 + math::sqr(tan_U1));\r
+ CT const temp_den_U2 = math::sqrt(c1 + math::sqr(tan_U2));\r
+ // cos = 1 / sqrt(1 + tan^2)\r
+ CT const cos_U1 = c1 / temp_den_U1;\r
+ CT const cos_U2 = c1 / temp_den_U2;\r
+ // sin = tan / sqrt(1 + tan^2)\r
+ CT const sin_U1 = tan_U1 / temp_den_U1;\r
+ CT const sin_U2 = tan_U2 / temp_den_U2;\r
+\r
+ // calculate sin U and cos U directly\r
+ //CT const U1 = atan(tan_U1);\r
+ //CT const U2 = atan(tan_U2);\r
+ //cos_U1 = cos(U1);\r
+ //cos_U2 = cos(U2);\r
+ //sin_U1 = tan_U1 * cos_U1; // sin(U1);\r
+ //sin_U2 = tan_U2 * cos_U2; // sin(U2);\r
+\r
+ CT previous_lambda;\r
+ CT sin_lambda;\r
+ CT cos_lambda;\r
+ CT sin_sigma;\r
+ CT sin_alpha;\r
+ CT cos2_alpha;\r
+ CT cos2_sigma_m;\r
+ CT sigma;\r
+\r
+ int counter = 0; // robustness\r
+\r
+ do\r
+ {\r
+ previous_lambda = lambda; // (13)\r
+ sin_lambda = sin(lambda);\r
+ cos_lambda = cos(lambda);\r
+ sin_sigma = math::sqrt(math::sqr(cos_U2 * sin_lambda) + math::sqr(cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda)); // (14)\r
+ CT cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)\r
+ sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)\r
+ cos2_alpha = c1 - math::sqr(sin_alpha);\r
+ cos2_sigma_m = math::equals(cos2_alpha, 0) ? 0 : cos_sigma - c2 * sin_U1 * sin_U2 / cos2_alpha; // (18)\r
+\r
+ CT C = flattening/c16 * cos2_alpha * (c4 + flattening * (c4 - c3 * cos2_alpha)); // (10)\r
+ sigma = atan2(sin_sigma, cos_sigma); // (16)\r
+ lambda = L + (c1 - C) * flattening * sin_alpha *\r
+ (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-c1 + c2 * math::sqr(cos2_sigma_m)))); // (11)\r
+\r
+ ++counter; // robustness\r
+\r
+ } while ( geometry::math::abs(previous_lambda - lambda) > c_e_12\r
+ && geometry::math::abs(lambda) < pi\r
+ && counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness\r
+ \r
+ if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )\r
+ {\r
+ // Oops getting hard here\r
+ // (again, problem is that ttmath cannot divide by doubles, which is OK)\r
+ CT const c1 = 1;\r
+ CT const c2 = 2;\r
+ CT const c3 = 3;\r
+ CT const c4 = 4;\r
+ CT const c6 = 6;\r
+ CT const c47 = 47;\r
+ CT const c74 = 74;\r
+ CT const c128 = 128;\r
+ CT const c256 = 256;\r
+ CT const c175 = 175;\r
+ CT const c320 = 320;\r
+ CT const c768 = 768;\r
+ CT const c1024 = 1024;\r
+ CT const c4096 = 4096;\r
+ CT const c16384 = 16384;\r
+\r
+ //CT sqr_u = cos2_alpha * (math::sqr(radius_a) - math::sqr(radius_b)) / math::sqr(radius_b); // above (1)\r
+ CT sqr_u = cos2_alpha * ( math::sqr(radius_a / radius_b) - c1 ); // above (1)\r
+\r
+ CT A = c1 + sqr_u/c16384 * (c4096 + sqr_u * (-c768 + sqr_u * (c320 - c175 * sqr_u))); // (3)\r
+ CT B = sqr_u/c1024 * (c256 + sqr_u * ( -c128 + sqr_u * (c74 - c47 * sqr_u))); // (4)\r
+ CT delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/c4) * (cos(sigma)* (-c1 + c2 * cos2_sigma_m)\r
+ - (B/c6) * cos2_sigma_m * (-c3 + c4 * math::sqr(sin_sigma)) * (-c3 + c4 * cos2_sigma_m))); // (6)\r
+\r
+ result.distance = radius_b * A * (sigma - delta_sigma); // (19)\r
+ }\r
+ else\r
+ {\r
+ result.distance = CT(0);\r
+ }\r
+ \r
+ if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) )\r
+ {\r
+ result.azimuth = atan2(cos_U2 * sin_lambda, cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda); // (20)\r
+ }\r
+ else\r
+ {\r
+ result.azimuth = CT(0);\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+// inline CT azimuth21() const\r
+// {\r
+// // NOTE: signs of X and Y are different than in the original paper\r
+// atan2(-cos_U1 * sin_lambda, sin_U1 * cos_U2 - cos_U1 * sin_U2 * cos_lambda); // (21)\r
+// }\r
+};\r
+\r
+}}} // namespace boost::geometry::detail\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_VINCENTY_INVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/strategies/concepts/within_concept.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+#include <boost/geometry/strategies/covered_by.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+#include <boost/geometry/views/detail/normalized_view.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace within {\r
+\r
+// TODO: is this needed?\r
+inline int check_result_type(int result)\r
+{\r
+ return result;\r
+}\r
+\r
+template <typename T>\r
+inline T check_result_type(T result)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(false);\r
+ return result;\r
+}\r
+\r
+template <typename Point, typename Range, typename Strategy> inline\r
+int point_in_range(Point const& point, Range const& range, Strategy const& strategy)\r
+{\r
+ boost::ignore_unused(strategy);\r
+\r
+ typedef typename boost::range_iterator<Range const>::type iterator_type;\r
+ typename Strategy::state_type state;\r
+ iterator_type it = boost::begin(range);\r
+ iterator_type end = boost::end(range);\r
+\r
+ for ( iterator_type previous = it++ ; it != end ; ++previous, ++it )\r
+ {\r
+ if ( ! strategy.apply(point, *previous, *it, state) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return check_result_type(strategy.result(state));\r
+}\r
+\r
+template <typename Geometry, typename Point, typename Range>\r
+inline int point_in_range(Point const& point, Range const& range)\r
+{\r
+ typedef typename point_type<Point>::type point_type1;\r
+ typedef typename point_type<Geometry>::type point_type2;\r
+\r
+ typedef typename strategy::within::services::default_strategy\r
+ <\r
+ typename tag<Point>::type,\r
+ typename tag<Geometry>::type,\r
+ typename tag<Point>::type,\r
+ typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type1>::type, spherical_tag\r
+ >::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type2>::type, spherical_tag\r
+ >::type,\r
+ Point,\r
+ Geometry\r
+ >::type strategy_type;\r
+\r
+ typedef typename strategy::covered_by::services::default_strategy\r
+ <\r
+ typename tag<Point>::type,\r
+ typename tag<Geometry>::type,\r
+ typename tag<Point>::type,\r
+ typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type1>::type, spherical_tag\r
+ >::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type2>::type, spherical_tag\r
+ >::type,\r
+ Point,\r
+ Geometry\r
+ >::type strategy_type2;\r
+\r
+ static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;\r
+ BOOST_MPL_ASSERT_MSG((same_strategies),\r
+ DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,\r
+ (strategy_type, strategy_type2));\r
+\r
+ return point_in_range(point, range, strategy_type());\r
+}\r
+\r
+}} // namespace detail::within\r
+\r
+namespace detail_dispatch { namespace within {\r
+\r
+// checks the relation between a point P and geometry G\r
+// returns 1 if P is in the interior of G\r
+// returns 0 if P is on the boundry of G\r
+// returns -1 if P is in the exterior of G\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type>\r
+struct point_in_geometry\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+template <typename Point2>\r
+struct point_in_geometry<Point2, point_tag>\r
+{\r
+ template <typename Point1, typename Strategy> static inline\r
+ int apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ return strategy.apply(point1, point2) ? 1 : -1;\r
+ }\r
+};\r
+\r
+template <typename Segment>\r
+struct point_in_geometry<Segment, segment_tag>\r
+{\r
+ template <typename Point, typename Strategy> static inline\r
+ int apply(Point const& point, Segment const& segment, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+\r
+ typedef typename geometry::point_type<Segment>::type point_type;\r
+ point_type p0, p1;\r
+// TODO: don't copy points\r
+ detail::assign_point_from_index<0>(segment, p0);\r
+ detail::assign_point_from_index<1>(segment, p1);\r
+\r
+ typename Strategy::state_type state;\r
+ strategy.apply(point, p0, p1, state);\r
+ int r = detail::within::check_result_type(strategy.result(state));\r
+\r
+ if ( r != 0 )\r
+ return -1; // exterior\r
+\r
+ // if the point is equal to the one of the terminal points\r
+ if ( detail::equals::equals_point_point(point, p0)\r
+ || detail::equals::equals_point_point(point, p1) )\r
+ return 0; // boundary\r
+ else\r
+ return 1; // interior\r
+ }\r
+};\r
+\r
+\r
+template <typename Linestring>\r
+struct point_in_geometry<Linestring, linestring_tag>\r
+{\r
+ template <typename Point, typename Strategy> static inline\r
+ int apply(Point const& point, Linestring const& linestring, Strategy const& strategy)\r
+ {\r
+ std::size_t count = boost::size(linestring);\r
+ if ( count > 1 )\r
+ {\r
+ if ( detail::within::point_in_range(point, linestring, strategy) != 0 )\r
+ return -1; // exterior\r
+\r
+ // if the linestring doesn't have a boundary\r
+ if (detail::equals::equals_point_point(range::front(linestring), range::back(linestring)))\r
+ return 1; // interior\r
+ // else if the point is equal to the one of the terminal points\r
+ else if (detail::equals::equals_point_point(point, range::front(linestring))\r
+ || detail::equals::equals_point_point(point, range::back(linestring)))\r
+ return 0; // boundary\r
+ else\r
+ return 1; // interior\r
+ }\r
+// TODO: for now degenerated linestrings are ignored\r
+// throw an exception here?\r
+ /*else if ( count == 1 )\r
+ {\r
+ if ( detail::equals::equals_point_point(point, range::front(linestring)) )\r
+ return 1;\r
+ }*/\r
+\r
+ return -1; // exterior\r
+ }\r
+};\r
+\r
+template <typename Ring>\r
+struct point_in_geometry<Ring, ring_tag>\r
+{\r
+ template <typename Point, typename Strategy> static inline\r
+ int apply(Point const& point, Ring const& ring, Strategy const& strategy)\r
+ {\r
+ if ( boost::size(ring) < core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Ring>::value\r
+ >::value )\r
+ {\r
+ return -1;\r
+ }\r
+\r
+ detail::normalized_view<Ring const> view(ring);\r
+ return detail::within::point_in_range(point, view, strategy);\r
+ }\r
+};\r
+\r
+// Polygon: in exterior ring, and if so, not within interior ring(s)\r
+template <typename Polygon>\r
+struct point_in_geometry<Polygon, polygon_tag>\r
+{\r
+ template <typename Point, typename Strategy>\r
+ static inline int apply(Point const& point, Polygon const& polygon,\r
+ Strategy const& strategy)\r
+ {\r
+ int const code = point_in_geometry\r
+ <\r
+ typename ring_type<Polygon>::type\r
+ >::apply(point, exterior_ring(polygon), strategy);\r
+\r
+ if (code == 1)\r
+ {\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ \r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings);\r
+ it != boost::end(rings);\r
+ ++it)\r
+ {\r
+ int const interior_code = point_in_geometry\r
+ <\r
+ typename ring_type<Polygon>::type\r
+ >::apply(point, *it, strategy);\r
+\r
+ if (interior_code != -1)\r
+ {\r
+ // If 0, return 0 (touch)\r
+ // If 1 (inside hole) return -1 (outside polygon)\r
+ // If -1 (outside hole) check other holes if any\r
+ return -interior_code;\r
+ }\r
+ }\r
+ }\r
+ return code;\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct point_in_geometry<Geometry, multi_point_tag>\r
+{\r
+ template <typename Point, typename Strategy> static inline\r
+ int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ typedef typename boost::range_value<Geometry>::type point_type;\r
+ typedef typename boost::range_const_iterator<Geometry>::type iterator;\r
+ for ( iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++it )\r
+ {\r
+ int pip = point_in_geometry<point_type>::apply(point, *it, strategy);\r
+\r
+ //BOOST_GEOMETRY_ASSERT(pip != 0);\r
+ if ( pip > 0 ) // inside\r
+ return 1;\r
+ }\r
+\r
+ return -1; // outside\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct point_in_geometry<Geometry, multi_linestring_tag>\r
+{\r
+ template <typename Point, typename Strategy> static inline\r
+ int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ int pip = -1; // outside\r
+\r
+ typedef typename boost::range_value<Geometry>::type linestring_type;\r
+ typedef typename boost::range_value<linestring_type>::type point_type;\r
+ typedef typename boost::range_iterator<Geometry const>::type iterator;\r
+ iterator it = boost::begin(geometry);\r
+ for ( ; it != boost::end(geometry) ; ++it )\r
+ {\r
+ pip = point_in_geometry<linestring_type>::apply(point, *it, strategy);\r
+\r
+ // inside or on the boundary\r
+ if ( pip >= 0 )\r
+ {\r
+ ++it;\r
+ break;\r
+ }\r
+ }\r
+\r
+ // outside\r
+ if ( pip < 0 )\r
+ return -1;\r
+\r
+ // TODO: the following isn't needed for covered_by()\r
+\r
+ unsigned boundaries = pip == 0 ? 1 : 0;\r
+\r
+ for ( ; it != boost::end(geometry) ; ++it )\r
+ {\r
+ if ( boost::size(*it) < 2 )\r
+ continue;\r
+\r
+ point_type const& front = range::front(*it);\r
+ point_type const& back = range::back(*it);\r
+\r
+ // is closed_ring - no boundary\r
+ if ( detail::equals::equals_point_point(front, back) )\r
+ continue;\r
+\r
+ // is point on boundary\r
+ if ( detail::equals::equals_point_point(point, front)\r
+ || detail::equals::equals_point_point(point, back) )\r
+ {\r
+ ++boundaries;\r
+ }\r
+ }\r
+\r
+ // if the number of boundaries is odd, the point is on the boundary\r
+ return boundaries % 2 ? 0 : 1;\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct point_in_geometry<Geometry, multi_polygon_tag>\r
+{\r
+ template <typename Point, typename Strategy> static inline\r
+ int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ // For invalid multipolygons\r
+ //int res = -1; // outside\r
+\r
+ typedef typename boost::range_value<Geometry>::type polygon_type;\r
+ typedef typename boost::range_const_iterator<Geometry>::type iterator;\r
+ for ( iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++it )\r
+ {\r
+ int pip = point_in_geometry<polygon_type>::apply(point, *it, strategy);\r
+\r
+ // inside or on the boundary\r
+ if ( pip >= 0 )\r
+ return pip;\r
+\r
+ // For invalid multi-polygons\r
+ //if ( 1 == pip ) // inside polygon\r
+ // return 1;\r
+ //else if ( res < pip ) // point must be inside at least one polygon\r
+ // res = pip;\r
+ }\r
+\r
+ return -1; // for valid multipolygons\r
+ //return res; // for invalid multipolygons\r
+ }\r
+};\r
+\r
+}} // namespace detail_dispatch::within\r
+\r
+namespace detail { namespace within {\r
+\r
+// 1 - in the interior\r
+// 0 - in the boundry\r
+// -1 - in the exterior\r
+template <typename Point, typename Geometry, typename Strategy>\r
+inline int point_in_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy)\r
+{\r
+ concepts::within::check\r
+ <\r
+ typename tag<Point>::type,\r
+ typename tag<Geometry>::type,\r
+ typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,\r
+ Strategy\r
+ >();\r
+\r
+ return detail_dispatch::within::point_in_geometry<Geometry>::apply(point, geometry, strategy);\r
+}\r
+\r
+template <typename Point, typename Geometry>\r
+inline int point_in_geometry(Point const& point, Geometry const& geometry)\r
+{\r
+ typedef typename point_type<Point>::type point_type1;\r
+ typedef typename point_type<Geometry>::type point_type2;\r
+\r
+ typedef typename strategy::within::services::default_strategy\r
+ <\r
+ typename tag<Point>::type,\r
+ typename tag<Geometry>::type,\r
+ typename tag<Point>::type,\r
+ typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type1>::type, spherical_tag\r
+ >::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type2>::type, spherical_tag\r
+ >::type,\r
+ Point,\r
+ Geometry\r
+ >::type strategy_type;\r
+\r
+ typedef typename strategy::covered_by::services::default_strategy\r
+ <\r
+ typename tag<Point>::type,\r
+ typename tag<Geometry>::type,\r
+ typename tag<Point>::type,\r
+ typename tag_cast<typename tag<Geometry>::type, areal_tag>::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type1>::type, spherical_tag\r
+ >::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type2>::type, spherical_tag\r
+ >::type,\r
+ Point,\r
+ Geometry\r
+ >::type strategy_type2;\r
+\r
+ static const bool same_strategies = boost::is_same<strategy_type, strategy_type2>::value;\r
+ BOOST_MPL_ASSERT_MSG((same_strategies),\r
+ DEFAULT_WITHIN_AND_COVERED_BY_STRATEGIES_NOT_COMPATIBLE,\r
+ (strategy_type, strategy_type2));\r
+\r
+ return point_in_geometry(point, geometry, strategy_type());\r
+}\r
+\r
+}} // namespace detail::within\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013.\r
+// Modifications copyright (c) 2013, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail_dispatch { namespace within {\r
+\r
+// returns true if G1 is within G2\r
+// this function should be called only if there are no intersection points\r
+// otherwise it may return invalid result\r
+// e.g. when non-first point of G1 is outside G2 or when some rings of G1 are the same as rings of G2\r
+\r
+template <typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename geometry::tag<Geometry1>::type,\r
+ typename Tag2 = typename geometry::tag<Geometry2>::type>\r
+struct within_no_turns\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ point1_type p;\r
+ if ( !geometry::point_on_border(p, geometry1) )\r
+ return false;\r
+\r
+ return detail::within::point_in_geometry(p, geometry2, strategy) >= 0;\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct within_no_turns<Geometry1, Geometry2, ring_tag, polygon_tag>\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+ point1_type p;\r
+ if ( !geometry::point_on_border(p, geometry1) )\r
+ return false;\r
+ // check if one of ring points is outside the polygon\r
+ if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )\r
+ return false;\r
+ // Now check if holes of G2 aren't inside G1\r
+ typedef typename boost::range_const_iterator\r
+ <\r
+ typename geometry::interior_type<Geometry2>::type\r
+ >::type iterator;\r
+ for ( iterator it = boost::begin(geometry::interior_rings(geometry2)) ;\r
+ it != boost::end(geometry::interior_rings(geometry2)) ;\r
+ ++it )\r
+ {\r
+ point2_type p;\r
+ if ( !geometry::point_on_border(p, *it) )\r
+ return false;\r
+ if ( detail::within::point_in_geometry(p, geometry1, strategy) > 0 )\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct within_no_turns<Geometry1, Geometry2, polygon_tag, polygon_tag>\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+ point1_type p;\r
+ if ( !geometry::point_on_border(p, geometry1) )\r
+ return false;\r
+ // check if one of ring points is outside the polygon\r
+ if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )\r
+ return false;\r
+ // Now check if holes of G2 aren't inside G1\r
+ typedef typename boost::range_const_iterator\r
+ <\r
+ typename geometry::interior_type<Geometry2>::type\r
+ >::type iterator2;\r
+ for ( iterator2 it = boost::begin(geometry::interior_rings(geometry2)) ;\r
+ it != boost::end(geometry::interior_rings(geometry2)) ;\r
+ ++it )\r
+ {\r
+ point2_type p2;\r
+ if ( !geometry::point_on_border(p2, *it) )\r
+ return false;\r
+ // if the hole of G2 is inside G1\r
+ if ( detail::within::point_in_geometry(p2, geometry1, strategy) > 0 )\r
+ {\r
+ // if it's also inside one of the G1 holes, it's ok\r
+ bool ok = false;\r
+ typedef typename boost::range_const_iterator\r
+ <\r
+ typename geometry::interior_type<Geometry1>::type\r
+ >::type iterator1;\r
+ for ( iterator1 it1 = boost::begin(geometry::interior_rings(geometry1)) ;\r
+ it1 != boost::end(geometry::interior_rings(geometry1)) ;\r
+ ++it1 )\r
+ {\r
+ if ( detail::within::point_in_geometry(p2, *it1, strategy) < 0 )\r
+ {\r
+ ok = true;\r
+ break;\r
+ }\r
+ }\r
+ if ( !ok )\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename geometry::tag<Geometry1>::type,\r
+ typename Tag2 = typename geometry::tag<Geometry2>::type,\r
+ bool IsMulti1 = boost::is_base_of<geometry::multi_tag, Tag1>::value,\r
+ bool IsMulti2 = boost::is_base_of<geometry::multi_tag, Tag2>::value>\r
+struct within_no_turns_multi\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ return within_no_turns<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>\r
+struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, false>\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ // All values of G1 must be inside G2\r
+ typedef typename boost::range_value<Geometry1>::type subgeometry1;\r
+ typedef typename boost::range_const_iterator<Geometry1>::type iterator;\r
+ for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )\r
+ {\r
+ if ( !within_no_turns<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>\r
+struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, false, true>\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ // G1 must be within at least one value of G2\r
+ typedef typename boost::range_value<Geometry2>::type subgeometry2;\r
+ typedef typename boost::range_const_iterator<Geometry2>::type iterator;\r
+ for ( iterator it = boost::begin(geometry2) ; it != boost::end(geometry2) ; ++it )\r
+ {\r
+ if ( within_no_turns<Geometry1, subgeometry2>::apply(geometry1, *it, strategy) )\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>\r
+struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, true>\r
+{\r
+ template <typename Strategy> static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ // each value of G1 must be inside at least one value of G2\r
+ typedef typename boost::range_value<Geometry1>::type subgeometry1;\r
+ typedef typename boost::range_const_iterator<Geometry1>::type iterator;\r
+ for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )\r
+ {\r
+ if ( !within_no_turns_multi<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+}} // namespace detail_dispatch::within\r
+\r
+namespace detail { namespace within {\r
+\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+inline bool within_no_turns(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+{\r
+ return detail_dispatch::within::within_no_turns_multi<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+}} // namespace detail::within\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace difference\r
+{\r
+\r
+/*!\r
+\brief_calc2{difference} \brief_strategy\r
+\ingroup difference\r
+\details \details_calc2{difference_insert, spatial set theoretic difference}\r
+ \brief_strategy. \details_inserter{difference}\r
+\tparam GeometryOut output geometry type, must be specified\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam OutputIterator output iterator\r
+\tparam Strategy \tparam_strategy_overlay\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{difference}\r
+\param strategy \param_strategy{difference}\r
+\return \return_out\r
+\r
+\qbk{distinguish,with strategy}\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+>\r
+inline OutputIterator difference_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ concepts::check<GeometryOut>();\r
+\r
+ return geometry::dispatch::intersection_insert\r
+ <\r
+ Geometry1, Geometry2,\r
+ GeometryOut,\r
+ overlay_difference,\r
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,\r
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value\r
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);\r
+}\r
+\r
+/*!\r
+\brief_calc2{difference}\r
+\ingroup difference\r
+\details \details_calc2{difference_insert, spatial set theoretic difference}.\r
+ \details_insert{difference}\r
+\tparam GeometryOut output geometry type, must be specified\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam OutputIterator output iterator\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{difference}\r
+\return \return_out\r
+\r
+\qbk{[include reference/algorithms/difference_insert.qbk]}\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator difference_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ concepts::check<GeometryOut>();\r
+\r
+ typedef intersection_strategies\r
+ <\r
+ typename cs_tag<GeometryOut>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ typename geometry::point_type<GeometryOut>::type,\r
+ RobustPolicy\r
+ > strategy;\r
+\r
+ return difference_insert<GeometryOut>(geometry1, geometry2,\r
+ robust_policy, out, strategy());\r
+}\r
+\r
+\r
+}} // namespace detail::difference\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+/*!\r
+\brief_calc2{difference}\r
+\ingroup difference\r
+\details \details_calc2{difference, spatial set theoretic difference}.\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Collection \tparam_output_collection\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param output_collection the output collection\r
+\r
+\qbk{[include reference/algorithms/difference.qbk]}\r
+*/\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Collection\r
+>\r
+inline void difference(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2, Collection& output_collection)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ typedef typename boost::range_value<Collection>::type geometry_out;\r
+ concepts::check<geometry_out>();\r
+\r
+ typedef typename geometry::rescale_overlay_policy_type\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::type rescale_policy_type;\r
+\r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);\r
+\r
+ detail::difference::difference_insert<geometry_out>(\r
+ geometry1, geometry2, robust_policy,\r
+ range::back_inserter(output_collection));\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_DISJOINT_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_DISJOINT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,\r
+ typename Tag1 = typename tag_cast\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ segment_tag, box_tag, linear_tag, areal_tag\r
+ >::type,\r
+ typename Tag2 = typename tag_cast\r
+ <\r
+ typename tag<Geometry2>::type,\r
+ segment_tag, box_tag, linear_tag, areal_tag\r
+ >::type,\r
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct disjoint\r
+ : not_implemented<Geometry1, Geometry2>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_DISJOINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_DISTANCE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_DISTANCE_HPP\r
+\r
+\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Strategy = typename detail::distance::default_strategy\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type,\r
+ typename Tag1 = typename tag_cast\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ segment_tag,\r
+ box_tag,\r
+ linear_tag,\r
+ areal_tag\r
+ >::type,\r
+ typename Tag2 = typename tag_cast\r
+ <\r
+ typename tag<Geometry2>::type,\r
+ segment_tag,\r
+ box_tag,\r
+ linear_tag,\r
+ areal_tag\r
+ >::type,\r
+ typename StrategyTag = typename strategy::distance::services::tag\r
+ <\r
+ Strategy\r
+ >::type,\r
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct distance: not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_DISTANCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type,\r
+ typename CS_Tag = typename cs_tag<Geometry>::type\r
+>\r
+struct envelope : not_implemented<Tag>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_ENVELOPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+\r
+#include <boost/geometry/strategies/compare.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename GeometryOut, typename Geometry,\r
+ typename StrategyLess = strategy::compare::default_strategy,\r
+ typename StrategyGreater = strategy::compare::default_strategy,\r
+ typename TagOut = typename tag<GeometryOut>::type,\r
+ typename Tag = typename tag<Geometry>::type,\r
+ typename CSTagOut = typename cs_tag<GeometryOut>::type,\r
+ typename CSTag = typename cs_tag<Geometry>::type\r
+>\r
+struct expand : not_implemented<TagOut, Tag>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_EXPAND_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_SIMPLE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_SIMPLE_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct is_simple\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_SIMPLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_VALID_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_VALID_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type,\r
+ // for multi-geometries: determines if empty multi-geometries are allowed\r
+ bool AllowEmptyMultiGeometries = true\r
+>\r
+struct is_valid\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_VALID_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/distance/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/envelope/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/envelope/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014, 2015, 2016.\r
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP\r
+\r
+\r
+#include <cstddef>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/geometry_id.hpp>\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/not.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+// For trivial checks\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/length.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>\r
+#include <boost/geometry/algorithms/relate.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>\r
+\r
+#include <boost/geometry/views/detail/indexed_point_view.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace equals\r
+{\r
+\r
+\r
+template\r
+<\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct box_box\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline bool apply(Box1 const& box1, Box2 const& box2)\r
+ {\r
+ if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))\r
+ || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))\r
+ {\r
+ return false;\r
+ }\r
+ return box_box<Dimension + 1, DimensionCount>::apply(box1, box2);\r
+ }\r
+};\r
+\r
+template <std::size_t DimensionCount>\r
+struct box_box<DimensionCount, DimensionCount>\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline bool apply(Box1 const& , Box2 const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+struct segment_segment\r
+{\r
+ template <typename Segment1, typename Segment2>\r
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)\r
+ {\r
+ return equals::equals_point_point(\r
+ indexed_point_view<Segment1 const, 0>(segment1),\r
+ indexed_point_view<Segment2 const, 0>(segment2) )\r
+ ? equals::equals_point_point(\r
+ indexed_point_view<Segment1 const, 1>(segment1),\r
+ indexed_point_view<Segment2 const, 1>(segment2) )\r
+ : ( equals::equals_point_point(\r
+ indexed_point_view<Segment1 const, 0>(segment1),\r
+ indexed_point_view<Segment2 const, 1>(segment2) )\r
+ && equals::equals_point_point(\r
+ indexed_point_view<Segment1 const, 1>(segment1),\r
+ indexed_point_view<Segment2 const, 0>(segment2) )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+struct area_check\r
+{\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ return geometry::math::equals(\r
+ geometry::area(geometry1),\r
+ geometry::area(geometry2));\r
+ }\r
+};\r
+\r
+\r
+struct length_check\r
+{\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ return geometry::math::equals(\r
+ geometry::length(geometry1),\r
+ geometry::length(geometry2));\r
+ }\r
+};\r
+\r
+\r
+template <typename TrivialCheck>\r
+struct equals_by_collection\r
+{\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ if (! TrivialCheck::apply(geometry1, geometry2))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ typename select_coordinate_type\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type,\r
+ double\r
+ >::type calculation_type;\r
+\r
+ typedef geometry::collected_vector\r
+ <\r
+ calculation_type,\r
+ Geometry1\r
+ > collected_vector;\r
+\r
+ std::vector<collected_vector> c1, c2;\r
+\r
+ geometry::collect_vectors(c1, geometry1);\r
+ geometry::collect_vectors(c2, geometry2);\r
+\r
+ if (boost::size(c1) != boost::size(c2))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ std::sort(c1.begin(), c1.end());\r
+ std::sort(c2.begin(), c2.end());\r
+\r
+ // Just check if these vectors are equal.\r
+ return std::equal(c1.begin(), c1.end(), c2.begin());\r
+ }\r
+};\r
+\r
+template<typename Geometry1, typename Geometry2>\r
+struct equals_by_relate\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_equals_type,\r
+ Geometry1,\r
+ Geometry2\r
+ >\r
+{};\r
+\r
+}} // namespace detail::equals\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag2 = typename tag<Geometry2>::type,\r
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,\r
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct equals: not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+\r
+// If reversal is needed, perform it\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1, typename Tag2,\r
+ std::size_t DimensionCount\r
+>\r
+struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>\r
+ : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ return equals\r
+ <\r
+ Geometry2, Geometry1,\r
+ Tag2, Tag1,\r
+ DimensionCount,\r
+ false\r
+ >::apply(g2, g1);\r
+ }\r
+};\r
+\r
+\r
+template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>\r
+struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>\r
+ : geometry::detail::not_\r
+ <\r
+ detail::disjoint::point_point<P1, P2, 0, DimensionCount>\r
+ >\r
+{};\r
+\r
+\r
+template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>\r
+struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>\r
+ : detail::equals::box_box<0, DimensionCount>\r
+{};\r
+\r
+\r
+template <typename Ring1, typename Ring2, bool Reverse>\r
+struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+\r
+template <typename Polygon1, typename Polygon2, bool Reverse>\r
+struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Ring, bool Reverse>\r
+struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+\r
+template <typename Ring, typename Box, bool Reverse>\r
+struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename Box, bool Reverse>\r
+struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>\r
+struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>\r
+ : detail::equals::segment_segment\r
+{};\r
+\r
+template <typename LineString1, typename LineString2, bool Reverse>\r
+struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>\r
+ //: detail::equals::equals_by_collection<detail::equals::length_check>\r
+ : detail::equals::equals_by_relate<LineString1, LineString2>\r
+{};\r
+\r
+template <typename LineString, typename MultiLineString, bool Reverse>\r
+struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>\r
+ : detail::equals::equals_by_relate<LineString, MultiLineString>\r
+{};\r
+\r
+template <typename MultiLineString1, typename MultiLineString2, bool Reverse>\r
+struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>\r
+ : detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>\r
+{};\r
+\r
+\r
+template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>\r
+struct equals\r
+ <\r
+ MultiPolygon1, MultiPolygon2,\r
+ multi_polygon_tag, multi_polygon_tag,\r
+ 2,\r
+ Reverse\r
+ >\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename MultiPolygon, bool Reverse>\r
+struct equals\r
+ <\r
+ Polygon, MultiPolygon,\r
+ polygon_tag, multi_polygon_tag,\r
+ 2,\r
+ Reverse\r
+ >\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+template <typename MultiPolygon, typename Ring, bool Reverse>\r
+struct equals\r
+ <\r
+ MultiPolygon, Ring,\r
+ multi_polygon_tag, ring_tag,\r
+ 2,\r
+ Reverse\r
+ >\r
+ : detail::equals::equals_by_collection<detail::equals::area_check>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct equals\r
+{\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ concepts::check_concepts_and_equal_dimensions\r
+ <\r
+ Geometry1 const,\r
+ Geometry2 const\r
+ >();\r
+\r
+ return dispatch::equals<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+\r
+ visitor(Geometry2 const& geometry2)\r
+ : m_geometry2(geometry2)\r
+ {}\r
+\r
+ template <typename Geometry1>\r
+ inline bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return equals<Geometry1, Geometry2>\r
+ ::apply(geometry1, m_geometry2);\r
+ }\r
+\r
+ };\r
+\r
+ static inline bool apply(\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2\r
+ )\r
+ {\r
+ return boost::apply_visitor(visitor(geometry2), geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+\r
+ visitor(Geometry1 const& geometry1)\r
+ : m_geometry1(geometry1)\r
+ {}\r
+\r
+ template <typename Geometry2>\r
+ inline bool operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return equals<Geometry1, Geometry2>\r
+ ::apply(m_geometry1, geometry2);\r
+ }\r
+\r
+ };\r
+\r
+ static inline bool apply(\r
+ Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2\r
+ )\r
+ {\r
+ return boost::apply_visitor(visitor(geometry1), geometry2);\r
+ }\r
+};\r
+\r
+template <\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct equals<\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+>\r
+{\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ template <typename Geometry1, typename Geometry2>\r
+ inline bool operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return equals<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2);\r
+ }\r
+\r
+ };\r
+\r
+ static inline bool apply(\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2\r
+ )\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_check{are spatially equal}\r
+\details \details_check12{equals, is spatially equal}. Spatially equal means\r
+ that the same point set is included. A box can therefore be spatially equal\r
+ to a ring or a polygon, or a linestring can be spatially equal to a\r
+ multi-linestring or a segment. This only works theoretically, not all\r
+ combinations are implemented yet.\r
+\ingroup equals\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_check2{are spatially equal}\r
+\r
+\qbk{[include reference/algorithms/equals.qbk]}\r
+\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::equals<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Distributed under the Boost Software License, Version 1.0.\r
+// (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/expand/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/expand/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP\r
+\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/util/add_const_if_c.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace for_each\r
+{\r
+\r
+\r
+struct fe_point_per_point\r
+{\r
+ template <typename Point, typename Functor>\r
+ static inline void apply(Point& point, Functor& f)\r
+ {\r
+ f(point);\r
+ }\r
+};\r
+\r
+\r
+struct fe_point_per_segment\r
+{\r
+ template <typename Point, typename Functor>\r
+ static inline void apply(Point& , Functor& /*f*/)\r
+ {\r
+ // TODO: if non-const, we should extract the points from the segment\r
+ // and call the functor on those two points\r
+ }\r
+};\r
+\r
+\r
+struct fe_range_per_point\r
+{\r
+ template <typename Range, typename Functor>\r
+ static inline void apply(Range& range, Functor& f)\r
+ {\r
+ // The previous implementation called the std library:\r
+ // return (std::for_each(boost::begin(range), boost::end(range), f));\r
+ // But that is not accepted for capturing lambda's.\r
+ // It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each).\r
+\r
+ // So we now loop manually.\r
+\r
+ for (typename boost::range_iterator<Range>::type\r
+ it = boost::begin(range); it != boost::end(range); ++it)\r
+ {\r
+ f(*it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <closure_selector Closure>\r
+struct fe_range_per_segment_with_closure\r
+{\r
+ template <typename Range, typename Functor>\r
+ static inline void apply(Range& range, Functor& f)\r
+ {\r
+ typedef typename add_const_if_c\r
+ <\r
+ is_const<Range>::value,\r
+ typename point_type<Range>::type\r
+ >::type point_type;\r
+\r
+ typedef typename boost::range_iterator<Range>::type iterator_type;\r
+\r
+ iterator_type it = boost::begin(range);\r
+ iterator_type previous = it++;\r
+ while(it != boost::end(range))\r
+ {\r
+ model::referring_segment<point_type> s(*previous, *it);\r
+ f(s);\r
+ previous = it++;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <>\r
+struct fe_range_per_segment_with_closure<open>\r
+{\r
+ template <typename Range, typename Functor>\r
+ static inline void apply(Range& range, Functor& f)\r
+ { \r
+ fe_range_per_segment_with_closure<closed>::apply(range, f);\r
+\r
+ model::referring_segment\r
+ <\r
+ typename add_const_if_c\r
+ <\r
+ is_const<Range>::value,\r
+ typename point_type<Range>::type\r
+ >::type\r
+ > s(range::back(range), range::front(range));\r
+\r
+ f(s);\r
+ }\r
+};\r
+\r
+\r
+struct fe_range_per_segment\r
+{\r
+ template <typename Range, typename Functor>\r
+ static inline void apply(Range& range, Functor& f)\r
+ {\r
+ fe_range_per_segment_with_closure\r
+ <\r
+ closure<Range>::value\r
+ >::apply(range, f);\r
+ }\r
+};\r
+\r
+\r
+struct fe_polygon_per_point\r
+{\r
+ template <typename Polygon, typename Functor>\r
+ static inline void apply(Polygon& poly, Functor& f)\r
+ {\r
+ fe_range_per_point::apply(exterior_ring(poly), f);\r
+\r
+ typename interior_return_type<Polygon>::type\r
+ rings = interior_rings(poly);\r
+\r
+ for (typename detail::interior_iterator<Polygon>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ fe_range_per_point::apply(*it, f);\r
+ }\r
+ }\r
+\r
+};\r
+\r
+struct fe_polygon_per_segment\r
+{\r
+ template <typename Polygon, typename Functor>\r
+ static inline void apply(Polygon& poly, Functor& f)\r
+ {\r
+ fe_range_per_segment::apply(exterior_ring(poly), f);\r
+\r
+ typename interior_return_type<Polygon>::type\r
+ rings = interior_rings(poly);\r
+\r
+ for (typename detail::interior_iterator<Polygon>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ fe_range_per_segment::apply(*it, f);\r
+ }\r
+ }\r
+\r
+};\r
+\r
+// Implementation of multi, for both point and segment,\r
+// just calling the single version.\r
+template <typename Policy>\r
+struct for_each_multi\r
+{\r
+ template <typename MultiGeometry, typename Functor>\r
+ static inline void apply(MultiGeometry& multi, Functor& f)\r
+ {\r
+ for (typename boost::range_iterator<MultiGeometry>::type\r
+ it = boost::begin(multi); it != boost::end(multi); ++it)\r
+ {\r
+ Policy::apply(*it, f);\r
+ }\r
+ }\r
+};\r
+\r
+}} // namespace detail::for_each\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type\r
+>\r
+struct for_each_point: not_implemented<Tag>\r
+{};\r
+\r
+\r
+template <typename Point>\r
+struct for_each_point<Point, point_tag>\r
+ : detail::for_each::fe_point_per_point\r
+{};\r
+\r
+\r
+template <typename Linestring>\r
+struct for_each_point<Linestring, linestring_tag>\r
+ : detail::for_each::fe_range_per_point\r
+{};\r
+\r
+\r
+template <typename Ring>\r
+struct for_each_point<Ring, ring_tag>\r
+ : detail::for_each::fe_range_per_point\r
+{};\r
+\r
+\r
+template <typename Polygon>\r
+struct for_each_point<Polygon, polygon_tag>\r
+ : detail::for_each::fe_polygon_per_point\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type\r
+>\r
+struct for_each_segment: not_implemented<Tag>\r
+{};\r
+\r
+template <typename Point>\r
+struct for_each_segment<Point, point_tag>\r
+ : detail::for_each::fe_point_per_segment\r
+{};\r
+\r
+\r
+template <typename Linestring>\r
+struct for_each_segment<Linestring, linestring_tag>\r
+ : detail::for_each::fe_range_per_segment\r
+{};\r
+\r
+\r
+template <typename Ring>\r
+struct for_each_segment<Ring, ring_tag>\r
+ : detail::for_each::fe_range_per_segment\r
+{};\r
+\r
+\r
+template <typename Polygon>\r
+struct for_each_segment<Polygon, polygon_tag>\r
+ : detail::for_each::fe_polygon_per_segment\r
+{};\r
+\r
+\r
+template <typename MultiGeometry>\r
+struct for_each_point<MultiGeometry, multi_tag>\r
+ : detail::for_each::for_each_multi\r
+ <\r
+ // Specify the dispatch of the single-version as policy\r
+ for_each_point\r
+ <\r
+ typename add_const_if_c\r
+ <\r
+ is_const<MultiGeometry>::value,\r
+ typename boost::range_value<MultiGeometry>::type\r
+ >::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+template <typename MultiGeometry>\r
+struct for_each_segment<MultiGeometry, multi_tag>\r
+ : detail::for_each::for_each_multi\r
+ <\r
+ // Specify the dispatch of the single-version as policy\r
+ for_each_segment\r
+ <\r
+ typename add_const_if_c\r
+ <\r
+ is_const<MultiGeometry>::value,\r
+ typename boost::range_value<MultiGeometry>::type\r
+ >::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief \brf_for_each{point}\r
+\details \det_for_each{point}\r
+\ingroup for_each\r
+\param geometry \param_geometry\r
+\param f \par_for_each_f{point}\r
+\tparam Geometry \tparam_geometry\r
+\tparam Functor \tparam_functor\r
+\r
+\qbk{[include reference/algorithms/for_each_point.qbk]}\r
+\qbk{[heading Example]}\r
+\qbk{[for_each_point] [for_each_point_output]}\r
+\qbk{[for_each_point_const] [for_each_point_const_output]}\r
+*/\r
+template<typename Geometry, typename Functor>\r
+inline Functor for_each_point(Geometry& geometry, Functor f)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::for_each_point<Geometry>::apply(geometry, f);\r
+ return f;\r
+}\r
+\r
+\r
+/*!\r
+\brief \brf_for_each{segment}\r
+\details \det_for_each{segment}\r
+\ingroup for_each\r
+\param geometry \param_geometry\r
+\param f \par_for_each_f{segment}\r
+\tparam Geometry \tparam_geometry\r
+\tparam Functor \tparam_functor\r
+\r
+\qbk{[include reference/algorithms/for_each_segment.qbk]}\r
+\qbk{[heading Example]}\r
+\qbk{[for_each_segment_const] [for_each_segment_const_output]}\r
+*/\r
+template<typename Geometry, typename Functor>\r
+inline Functor for_each_segment(Geometry& geometry, Functor f)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ dispatch::for_each_segment<Geometry>::apply(geometry, f);\r
+ return f;\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/intersection/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/intersection/implementation.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP\r
+\r
+\r
+#include <deque>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief \brief_check{has at least one intersection (crossing or self-tangency)}\r
+\note This function can be called for one geometry (self-intersection) and\r
+ also for two geometries (intersection)\r
+\ingroup intersects\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_check{is self-intersecting}\r
+\r
+\qbk{distinguish,one geometry}\r
+\qbk{[def __one_parameter__]}\r
+\qbk{[include reference/algorithms/intersects.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool intersects(Geometry const& geometry)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef detail::no_rescale_policy rescale_policy_type;\r
+\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type<point_type, rescale_policy_type>::type\r
+ > turn_info;\r
+\r
+ std::deque<turn_info> turns;\r
+\r
+ typedef detail::overlay::get_turn_info\r
+ <\r
+ detail::overlay::assign_null_policy\r
+ > turn_policy;\r
+\r
+ rescale_policy_type robust_policy;\r
+\r
+ detail::disjoint::disjoint_interrupt_policy policy;\r
+ detail::self_get_turn_points::get_turns\r
+ <\r
+ turn_policy\r
+ >::apply(geometry, robust_policy, turns, policy);\r
+ return policy.has_intersections;\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_check2{have at least one intersection}\r
+\ingroup intersects\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_check2{intersect each other}\r
+\r
+\qbk{distinguish,two geometries}\r
+\qbk{[include reference/algorithms/intersects.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return ! geometry::disjoint(geometry1, geometry2);\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>\r
+#include <boost/geometry/views/detail/normalized_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_convex\r
+{\r
+\r
+struct ring_is_convex\r
+{\r
+ template <typename Ring>\r
+ static inline bool apply(Ring const& ring)\r
+ {\r
+ typedef typename geometry::point_type<Ring>::type point_type;\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type\r
+ >::type side_strategy_type;\r
+\r
+ std::size_t n = boost::size(ring);\r
+ if (boost::size(ring) < core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Ring>::value\r
+ >::value)\r
+ {\r
+ // (Too) small rings are considered as non-concave, is convex\r
+ return true;\r
+ }\r
+\r
+ // Walk in clockwise direction, consider ring as closed\r
+ // (though closure is not important in this algorithm - any dupped\r
+ // point is skipped)\r
+ typedef detail::normalized_view<Ring const> view_type;\r
+ view_type view(ring);\r
+\r
+ typedef geometry::ever_circling_range_iterator<view_type const> it_type;\r
+ it_type previous(view);\r
+ it_type current(view);\r
+ current++;\r
+\r
+ std::size_t index = 1;\r
+ while (equals::equals_point_point(*current, *previous) && index < n)\r
+ {\r
+ current++;\r
+ index++;\r
+ }\r
+\r
+ if (index == n)\r
+ {\r
+ // All points are apparently equal\r
+ return true;\r
+ }\r
+\r
+ it_type next = current;\r
+ next++;\r
+ while (equals::equals_point_point(*current, *next))\r
+ {\r
+ next++;\r
+ }\r
+\r
+ // We have now three different points on the ring\r
+ // Walk through all points, use a counter because of the ever-circling\r
+ // iterator\r
+ for (std::size_t i = 0; i < n; i++)\r
+ {\r
+ int const side = side_strategy_type::apply(*previous, *current, *next);\r
+ if (side == 1)\r
+ {\r
+ // Next is on the left side of clockwise ring:\r
+ // the piece is not convex\r
+ return false;\r
+ }\r
+\r
+ previous = current;\r
+ current = next;\r
+\r
+ // Advance next to next different point\r
+ // (because there are non-equal points, this loop is not infinite)\r
+ next++;\r
+ while (equals::equals_point_point(*current, *next))\r
+ {\r
+ next++;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::is_convex\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct is_convex : not_implemented<Tag>\r
+{};\r
+\r
+template <typename Box>\r
+struct is_convex<Box, box_tag>\r
+{\r
+ static inline bool apply(Box const& )\r
+ {\r
+ // Any box is convex (TODO: consider spherical boxes)\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+// TODO: variants\r
+\r
+// TODO: documentation / qbk\r
+template<typename Geometry>\r
+inline bool is_convex(Geometry const& geometry)\r
+{\r
+ return dispatch::is_convex<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_EMPTY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_IS_EMPTY_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace is_empty\r
+{\r
+\r
+struct always_not_empty\r
+{\r
+ template <typename Geometry>\r
+ static inline bool apply(Geometry const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+struct range_is_empty\r
+{\r
+ template <typename Range>\r
+ static inline bool apply(Range const& range)\r
+ {\r
+ return boost::empty(range);\r
+ }\r
+};\r
+\r
+class polygon_is_empty\r
+{\r
+ template <typename InteriorRings>\r
+ static inline bool check_interior_rings(InteriorRings const& interior_rings)\r
+ {\r
+ return check_iterator_range\r
+ <\r
+ range_is_empty, true // allow empty range\r
+ >::apply(boost::begin(interior_rings), boost::end(interior_rings));\r
+ }\r
+\r
+public:\r
+ template <typename Polygon>\r
+ static inline bool apply(Polygon const& polygon)\r
+ {\r
+ return boost::empty(exterior_ring(polygon))\r
+ && check_interior_rings(interior_rings(polygon));\r
+ }\r
+};\r
+\r
+template <typename Policy = range_is_empty>\r
+struct multi_is_empty\r
+{\r
+ template <typename MultiGeometry>\r
+ static inline bool apply(MultiGeometry const& multigeometry)\r
+ {\r
+ return check_iterator_range\r
+ <\r
+ Policy, true // allow empty range\r
+ >::apply(boost::begin(multigeometry), boost::end(multigeometry));\r
+ }\r
+ \r
+};\r
+\r
+}} // namespace detail::is_empty\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct is_empty : not_implemented<Tag>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, point_tag>\r
+ : detail::is_empty::always_not_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, box_tag>\r
+ : detail::is_empty::always_not_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, segment_tag>\r
+ : detail::is_empty::always_not_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, linestring_tag>\r
+ : detail::is_empty::range_is_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, ring_tag>\r
+ : detail::is_empty::range_is_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, polygon_tag>\r
+ : detail::is_empty::polygon_is_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, multi_point_tag>\r
+ : detail::is_empty::range_is_empty\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, multi_linestring_tag>\r
+ : detail::is_empty::multi_is_empty<>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct is_empty<Geometry, multi_polygon_tag>\r
+ : detail::is_empty::multi_is_empty<detail::is_empty::polygon_is_empty>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct is_empty\r
+{\r
+ static inline bool apply(Geometry const& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::is_empty<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct is_empty<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor : boost::static_visitor<bool>\r
+ {\r
+ template <typename Geometry>\r
+ inline bool operator()(Geometry const& geometry) const\r
+ {\r
+ return is_empty<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_check{is the empty set}\r
+\ingroup is_empty\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_check{is the empty set}\r
+\r
+\qbk{[include reference/algorithms/is_empty.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool is_empty(Geometry const& geometry)\r
+{\r
+ return resolve_variant::is_empty<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_IS_EMPTY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_SIMPLE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_IS_SIMPLE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/is_simple/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/is_simple/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_IS_SIMPLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_VALID_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_IS_VALID_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/is_valid/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/is_valid/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_IS_VALID_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/mpl/fold.hpp>\r
+#include <boost/mpl/greater.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/insert.hpp>\r
+#include <boost/mpl/int.hpp>\r
+#include <boost/mpl/set.hpp>\r
+#include <boost/mpl/size.hpp>\r
+#include <boost/mpl/transform.hpp>\r
+#include <boost/range/begin.hpp>\r
+#include <boost/range/end.hpp>\r
+#include <boost/range/iterator.hpp>\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>\r
+#include <boost/geometry/algorithms/detail/multi_sum.hpp>\r
+// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/default_length_result.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace length\r
+{\r
+\r
+\r
+template<typename Segment>\r
+struct segment_length\r
+{\r
+ template <typename Strategy>\r
+ static inline typename default_length_result<Segment>::type apply(\r
+ Segment const& segment, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ typedef typename point_type<Segment>::type point_type;\r
+ point_type p1, p2;\r
+ geometry::detail::assign_point_from_index<0>(segment, p1);\r
+ geometry::detail::assign_point_from_index<1>(segment, p2);\r
+ return strategy.apply(p1, p2);\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Internal, calculates length of a linestring using iterator pairs and\r
+ specified strategy\r
+\note for_each could be used here, now that point_type is changed by boost\r
+ range iterator\r
+*/\r
+template<typename Range, closure_selector Closure>\r
+struct range_length\r
+{\r
+ typedef typename default_length_result<Range>::type return_type;\r
+\r
+ template <typename Strategy>\r
+ static inline return_type apply(\r
+ Range const& range, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+ typedef typename closeable_view<Range const, Closure>::type view_type;\r
+ typedef typename boost::range_iterator\r
+ <\r
+ view_type const\r
+ >::type iterator_type;\r
+\r
+ return_type sum = return_type();\r
+ view_type view(range);\r
+ iterator_type it = boost::begin(view), end = boost::end(view);\r
+ if(it != end)\r
+ {\r
+ for(iterator_type previous = it++;\r
+ it != end;\r
+ ++previous, ++it)\r
+ {\r
+ // Add point-point distance using the return type belonging\r
+ // to strategy\r
+ sum += strategy.apply(*previous, *it);\r
+ }\r
+ }\r
+\r
+ return sum;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::length\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct length : detail::calculate_null\r
+{\r
+ typedef typename default_length_result<Geometry>::type return_type;\r
+\r
+ template <typename Strategy>\r
+ static inline return_type apply(Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ return calculate_null::apply<return_type>(geometry, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct length<Geometry, linestring_tag>\r
+ : detail::length::range_length<Geometry, closed>\r
+{};\r
+\r
+\r
+// RING: length is currently 0; it might be argued that it is the "perimeter"\r
+\r
+\r
+template <typename Geometry>\r
+struct length<Geometry, segment_tag>\r
+ : detail::length::segment_length<Geometry>\r
+{};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct length<MultiLinestring, multi_linestring_tag> : detail::multi_sum\r
+{\r
+ template <typename Strategy>\r
+ static inline typename default_length_result<MultiLinestring>::type\r
+ apply(MultiLinestring const& multi, Strategy const& strategy)\r
+ {\r
+ return multi_sum::apply\r
+ <\r
+ typename default_length_result<MultiLinestring>::type,\r
+ detail::length::range_length\r
+ <\r
+ typename boost::range_value<MultiLinestring>::type,\r
+ closed // no need to close it explicitly\r
+ >\r
+ >(multi, strategy);\r
+\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct length\r
+{\r
+ template <typename Strategy>\r
+ static inline typename default_length_result<Geometry>::type\r
+ apply(Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ return dispatch::length<Geometry>::apply(geometry, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct length<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ typedef typename default_length_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>\r
+ >::type result_type;\r
+\r
+ template <typename Strategy>\r
+ struct visitor\r
+ : static_visitor<result_type>\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy)\r
+ : m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ inline typename default_length_result<Geometry>::type\r
+ operator()(Geometry const& geometry) const\r
+ {\r
+ return length<Geometry>::apply(geometry, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline result_type apply(\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ Strategy const& strategy\r
+ )\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{length}\r
+\ingroup length\r
+\details \details_calc{length, length (the sum of distances between consecutive points)}. \details_default_strategy\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{length}\r
+\r
+\qbk{[include reference/algorithms/length.qbk]}\r
+\qbk{[length] [length_output]}\r
+ */\r
+template<typename Geometry>\r
+inline typename default_length_result<Geometry>::type\r
+length(Geometry const& geometry)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ // detail::throw_on_empty_input(geometry);\r
+\r
+ // TODO put this into a resolve_strategy stage\r
+ typedef typename strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, point_tag, typename point_type<Geometry>::type\r
+ >::type strategy_type;\r
+\r
+ return resolve_variant::length<Geometry>::apply(geometry, strategy_type());\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc{length} \brief_strategy\r
+\ingroup length\r
+\details \details_calc{length, length (the sum of distances between consecutive points)} \brief_strategy. \details_strategy_reasons\r
+\tparam Geometry \tparam_geometry\r
+\tparam Strategy \tparam_strategy{distance}\r
+\param geometry \param_geometry\r
+\param strategy \param_strategy{distance}\r
+\return \return_calc{length}\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/length.qbk]}\r
+\qbk{[length_with_strategy] [length_with_strategy_output]}\r
+ */\r
+template<typename Geometry, typename Strategy>\r
+inline typename default_length_result<Geometry>::type\r
+length(Geometry const& geometry, Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ // detail::throw_on_empty_input(geometry);\r
+\r
+ return resolve_variant::length<Geometry>::apply(geometry, strategy);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace make\r
+{\r
+\r
+/*!\r
+\brief Construct a geometry\r
+\ingroup make\r
+\tparam Geometry \tparam_geometry\r
+\tparam Range \tparam_range_point\r
+\param range \param_range_point\r
+\return The constructed geometry, here: a linestring or a ring\r
+\r
+\qbk{distinguish, with a range}\r
+\qbk{\r
+[heading Example]\r
+[make_with_range] [make_with_range_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.assign.assign_points assign]\r
+}\r
+ */\r
+template <typename Geometry, typename Range>\r
+inline Geometry make_points(Range const& range)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ Geometry geometry;\r
+ geometry::append(geometry, range);\r
+ return geometry;\r
+}\r
+\r
+}} // namespace detail::make\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+/*!\r
+\brief Construct a geometry\r
+\ingroup make\r
+\details\r
+\note It does not work with array-point types, like int[2]\r
+\tparam Geometry \tparam_geometry\r
+\tparam Type \tparam_numeric to specify the coordinates\r
+\param c1 \param_x\r
+\param c2 \param_y\r
+\return The constructed geometry, here: a 2D point\r
+\r
+\qbk{distinguish, 2 coordinate values}\r
+\qbk{\r
+[heading Example]\r
+[make_2d_point] [make_2d_point_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.assign.assign_values_3_2_coordinate_values assign]\r
+}\r
+*/\r
+template <typename Geometry, typename Type>\r
+inline Geometry make(Type const& c1, Type const& c2)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ Geometry geometry;\r
+ dispatch::assign\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ geometry::dimension<Geometry>::type::value\r
+ >::apply(geometry, c1, c2);\r
+ return geometry;\r
+}\r
+\r
+/*!\r
+\brief Construct a geometry\r
+\ingroup make\r
+\tparam Geometry \tparam_geometry\r
+\tparam Type \tparam_numeric to specify the coordinates\r
+\param c1 \param_x\r
+\param c2 \param_y\r
+\param c3 \param_z\r
+\return The constructed geometry, here: a 3D point\r
+\r
+\qbk{distinguish, 3 coordinate values}\r
+\qbk{\r
+[heading Example]\r
+[make_3d_point] [make_3d_point_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.assign.assign_values_4_3_coordinate_values assign]\r
+}\r
+ */\r
+template <typename Geometry, typename Type>\r
+inline Geometry make(Type const& c1, Type const& c2, Type const& c3)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ Geometry geometry;\r
+ dispatch::assign\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ geometry::dimension<Geometry>::type::value\r
+ >::apply(geometry, c1, c2, c3);\r
+ return geometry;\r
+}\r
+\r
+template <typename Geometry, typename Type>\r
+inline Geometry make(Type const& c1, Type const& c2, Type const& c3, Type const& c4)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ Geometry geometry;\r
+ dispatch::assign\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry,\r
+ geometry::dimension<Geometry>::type::value\r
+ >::apply(geometry, c1, c2, c3, c4);\r
+ return geometry;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+/*!\r
+\brief Construct a box with inverse infinite coordinates\r
+\ingroup make\r
+\details The make_inverse function initializes a 2D or 3D box with large coordinates, the\r
+ min corner is very large, the max corner is very small. This is useful e.g. in combination\r
+ with the expand function, to determine the bounding box of a series of geometries.\r
+\tparam Geometry \tparam_geometry\r
+\return The constructed geometry, here: a box\r
+\r
+\qbk{\r
+[heading Example]\r
+[make_inverse] [make_inverse_output]\r
+\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.assign.assign_inverse assign_inverse]\r
+}\r
+ */\r
+template <typename Geometry>\r
+inline Geometry make_inverse()\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ Geometry geometry;\r
+ dispatch::assign_inverse\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::apply(geometry);\r
+ return geometry;\r
+}\r
+\r
+/*!\r
+\brief Construct a geometry with its coordinates initialized to zero\r
+\ingroup make\r
+\details The make_zero function initializes a 2D or 3D point or box with coordinates of zero\r
+\tparam Geometry \tparam_geometry\r
+\return The constructed and zero-initialized geometry\r
+ */\r
+template <typename Geometry>\r
+inline Geometry make_zero()\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ Geometry geometry;\r
+ dispatch::assign_zero\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::apply(geometry);\r
+ return geometry;\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/identity.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace info\r
+{\r
+ struct UNRECOGNIZED_GEOMETRY_TYPE {};\r
+ struct POINT {};\r
+ struct LINESTRING {};\r
+ struct POLYGON {};\r
+ struct RING {};\r
+ struct BOX {};\r
+ struct SEGMENT {};\r
+ struct MULTI_POINT {};\r
+ struct MULTI_LINESTRING {};\r
+ struct MULTI_POLYGON {};\r
+ struct GEOMETRY_COLLECTION {};\r
+ template <size_t D> struct DIMENSION {};\r
+}\r
+\r
+\r
+namespace nyi\r
+{\r
+\r
+\r
+struct not_implemented_tag {};\r
+\r
+template\r
+<\r
+ typename Term1,\r
+ typename Term2,\r
+ typename Term3\r
+>\r
+struct not_implemented_error\r
+{\r
+\r
+#ifndef BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD\r
+# define BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD false\r
+#endif\r
+\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD,\r
+ THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED,\r
+ (\r
+ types<Term1, Term2, Term3>\r
+ )\r
+ );\r
+};\r
+\r
+template <typename Tag>\r
+struct tag_to_term\r
+{\r
+ typedef Tag type;\r
+};\r
+\r
+template <> struct tag_to_term<geometry_not_recognized_tag> { typedef info::UNRECOGNIZED_GEOMETRY_TYPE type; };\r
+template <> struct tag_to_term<point_tag> { typedef info::POINT type; };\r
+template <> struct tag_to_term<linestring_tag> { typedef info::LINESTRING type; };\r
+template <> struct tag_to_term<polygon_tag> { typedef info::POLYGON type; };\r
+template <> struct tag_to_term<ring_tag> { typedef info::RING type; };\r
+template <> struct tag_to_term<box_tag> { typedef info::BOX type; };\r
+template <> struct tag_to_term<segment_tag> { typedef info::SEGMENT type; };\r
+template <> struct tag_to_term<multi_point_tag> { typedef info::MULTI_POINT type; };\r
+template <> struct tag_to_term<multi_linestring_tag> { typedef info::MULTI_LINESTRING type; };\r
+template <> struct tag_to_term<multi_polygon_tag> { typedef info::MULTI_POLYGON type; };\r
+template <> struct tag_to_term<geometry_collection_tag> { typedef info::GEOMETRY_COLLECTION type; };\r
+template <int D> struct tag_to_term<boost::mpl::int_<D> > { typedef info::DIMENSION<D> type; };\r
+\r
+\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Term1 = void,\r
+ typename Term2 = void,\r
+ typename Term3 = void\r
+>\r
+struct not_implemented\r
+ : nyi::not_implemented_tag,\r
+ nyi::not_implemented_error\r
+ <\r
+ typename boost::mpl::identity\r
+ <\r
+ typename nyi::tag_to_term<Term1>::type\r
+ >::type,\r
+ typename boost::mpl::identity\r
+ <\r
+ typename nyi::tag_to_term<Term2>::type\r
+ >::type,\r
+ typename boost::mpl::identity\r
+ <\r
+ typename nyi::tag_to_term<Term3>::type\r
+ >::type\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_GEOMETRIES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_GEOMETRIES_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/counting.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag_cast\r
+ <\r
+ typename tag<Geometry>::type,\r
+ single_tag,\r
+ multi_tag\r
+ >::type\r
+>\r
+struct num_geometries: not_implemented<Tag>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct num_geometries<Geometry, single_tag>\r
+ : detail::counting::other_count<1>\r
+{};\r
+\r
+\r
+template <typename MultiGeometry>\r
+struct num_geometries<MultiGeometry, multi_tag>\r
+{\r
+ static inline std::size_t apply(MultiGeometry const& multi_geometry)\r
+ {\r
+ return boost::size(multi_geometry);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct num_geometries\r
+{\r
+ static inline std::size_t apply(Geometry const& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::num_geometries<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct num_geometries<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<std::size_t>\r
+ {\r
+ template <typename Geometry>\r
+ inline std::size_t operator()(Geometry const& geometry) const\r
+ {\r
+ return num_geometries<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline std::size_t\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{number of geometries}\r
+\ingroup num_geometries\r
+\details \details_calc{num_geometries, number of geometries}.\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{number of geometries}\r
+\r
+\qbk{[include reference/algorithms/num_geometries.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline std::size_t num_geometries(Geometry const& geometry)\r
+{\r
+ return resolve_variant::num_geometries<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_GEOMETRIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_INTERIOR_RINGS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_INTERIOR_RINGS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/counting.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct num_interior_rings\r
+ : detail::counting::other_count<0>\r
+{};\r
+\r
+\r
+\r
+template <typename Polygon>\r
+struct num_interior_rings<Polygon, polygon_tag>\r
+{\r
+ static inline std::size_t apply(Polygon const& polygon)\r
+ {\r
+ return boost::size(geometry::interior_rings(polygon));\r
+ }\r
+\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct num_interior_rings<MultiPolygon, multi_polygon_tag>\r
+ : detail::counting::multi_count\r
+ <\r
+ num_interior_rings\r
+ <\r
+ typename boost::range_value<MultiPolygon const>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct num_interior_rings\r
+{\r
+ static inline std::size_t apply(Geometry const& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::num_interior_rings<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct num_interior_rings<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<std::size_t>\r
+ {\r
+ template <typename Geometry>\r
+ inline std::size_t operator()(Geometry const& geometry) const\r
+ {\r
+ return num_interior_rings<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline std::size_t\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{number of interior rings}\r
+\ingroup num_interior_rings\r
+\details \details_calc{num_interior_rings, number of interior rings}.\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{number of interior rings}\r
+\r
+\qbk{[include reference/algorithms/num_interior_rings.qbk]}\r
+\r
+\note Defined by OGC as "numInteriorRing". To be consistent with "numPoints"\r
+ letter "s" is appended\r
+*/\r
+template <typename Geometry>\r
+inline std::size_t num_interior_rings(Geometry const& geometry)\r
+{\r
+ return resolve_variant::num_interior_rings<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_INTERIOR_RINGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/size_t.hpp>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/counting.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace num_points\r
+{\r
+\r
+\r
+template <bool AddForOpen>\r
+struct range_count\r
+{\r
+ template <typename Range>\r
+ static inline std::size_t apply(Range const& range)\r
+ {\r
+ std::size_t n = boost::size(range);\r
+ if (AddForOpen\r
+ && n > 0\r
+ && geometry::closure<Range>::value == open\r
+ )\r
+ {\r
+ return n + 1;\r
+ }\r
+ return n;\r
+ }\r
+};\r
+\r
+}} // namespace detail::num_points\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ bool AddForOpen,\r
+ typename Tag = typename tag_cast\r
+ <\r
+ typename tag<Geometry>::type, multi_tag\r
+ >::type\r
+>\r
+struct num_points: not_implemented<Tag>\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, point_tag>\r
+ : detail::counting::other_count<1>\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, box_tag>\r
+ : detail::counting::other_count<(1 << geometry::dimension<Geometry>::value)>\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, segment_tag>\r
+ : detail::counting::other_count<2>\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, linestring_tag>\r
+ : detail::num_points::range_count<AddForOpen>\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, ring_tag>\r
+ : detail::num_points::range_count<AddForOpen>\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, polygon_tag>\r
+ : detail::counting::polygon_count\r
+ <\r
+ detail::num_points::range_count<AddForOpen>\r
+ >\r
+{};\r
+\r
+template <typename Geometry, bool AddForOpen>\r
+struct num_points<Geometry, AddForOpen, multi_tag>\r
+ : detail::counting::multi_count\r
+ <\r
+ num_points<typename boost::range_value<Geometry>::type, AddForOpen>\r
+ >\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct num_points\r
+{\r
+ static inline std::size_t apply(Geometry const& geometry,\r
+ bool add_for_open)\r
+ {\r
+ concepts::check<Geometry const>();\r
+\r
+ return add_for_open\r
+ ? dispatch::num_points<Geometry, true>::apply(geometry)\r
+ : dispatch::num_points<Geometry, false>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<std::size_t>\r
+ {\r
+ bool m_add_for_open;\r
+\r
+ visitor(bool add_for_open): m_add_for_open(add_for_open) {}\r
+\r
+ template <typename Geometry>\r
+ inline std::size_t operator()(Geometry const& geometry) const\r
+ {\r
+ return num_points<Geometry>::apply(geometry, m_add_for_open);\r
+ }\r
+ };\r
+\r
+ static inline std::size_t\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ bool add_for_open)\r
+ {\r
+ return boost::apply_visitor(visitor(add_for_open), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{number of points}\r
+\ingroup num_points\r
+\details \details_calc{num_points, number of points}.\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\param add_for_open add one for open geometries (i.e. polygon types which are not closed)\r
+\return \return_calc{number of points}\r
+\r
+\qbk{[include reference/algorithms/num_points.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline std::size_t num_points(Geometry const& geometry, bool add_for_open = false)\r
+{\r
+ return resolve_variant::num_points<Geometry>::apply(geometry, add_for_open);\r
+}\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_SEGMENTS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_SEGMENTS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/size_t.hpp>\r
+#include <boost/mpl/times.hpp>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/counting.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace num_segments\r
+{\r
+\r
+\r
+struct range_count\r
+{\r
+ template <typename Range>\r
+ static inline std::size_t apply(Range const& range)\r
+ {\r
+ std::size_t n = boost::size(range);\r
+ if ( n <= 1 )\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ return\r
+ geometry::closure<Range>::value == open\r
+ ?\r
+ n\r
+ :\r
+ static_cast<std::size_t>(n - 1);\r
+ }\r
+};\r
+\r
+}} // namespace detail::num_segments\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct num_segments\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, point_tag>\r
+ : detail::counting::other_count<0>\r
+{};\r
+\r
+// the number of segments (1-dimensional faces) of the hypercube is\r
+// given by the formula: d * 2^(d-1), where d is the dimension of the\r
+// hypercube; see also:\r
+// http://en.wikipedia.org/wiki/Hypercube\r
+template <typename Geometry>\r
+struct num_segments<Geometry, box_tag>\r
+ : detail::counting::other_count\r
+ <\r
+ geometry::dimension<Geometry>::value\r
+ * (1 << (geometry::dimension<Geometry>::value - 1))\r
+ >\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, segment_tag>\r
+ : detail::counting::other_count<1>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, linestring_tag>\r
+ : detail::num_segments::range_count\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, ring_tag>\r
+ : detail::num_segments::range_count\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, polygon_tag>\r
+ : detail::counting::polygon_count<detail::num_segments::range_count>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, multi_point_tag>\r
+ : detail::counting::other_count<0>\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, multi_linestring_tag>\r
+ : detail::counting::multi_count\r
+ <\r
+ num_segments< typename boost::range_value<Geometry>::type>\r
+ >\r
+{};\r
+\r
+template <typename Geometry>\r
+struct num_segments<Geometry, multi_polygon_tag>\r
+ : detail::counting::multi_count\r
+ <\r
+ num_segments< typename boost::range_value<Geometry>::type>\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+\r
+template <typename Geometry>\r
+struct num_segments\r
+{\r
+ static inline std::size_t apply(Geometry const& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+\r
+ return dispatch::num_segments<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct num_segments<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<std::size_t>\r
+ {\r
+ template <typename Geometry>\r
+ inline std::size_t operator()(Geometry const& geometry) const\r
+ {\r
+ return num_segments<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline std::size_t\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_calc{number of segments}\r
+\ingroup num_segments\r
+\details \details_calc{num_segments, number of segments}.\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{number of segments}\r
+\r
+\qbk{[include reference/algorithms/num_segments.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline std::size_t num_segments(Geometry const& geometry)\r
+{\r
+ return resolve_variant::num_segments<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_SEGMENTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/relate.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlaps\r
+{\r
+\r
+template\r
+<\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct box_box_loop\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline void apply(Box1 const& b1, Box2 const& b2,\r
+ bool& overlaps, bool& one_in_two, bool& two_in_one)\r
+ {\r
+ assert_dimension_equal<Box1, Box2>();\r
+\r
+ typedef typename coordinate_type<Box1>::type coordinate_type1;\r
+ typedef typename coordinate_type<Box2>::type coordinate_type2;\r
+\r
+ coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);\r
+ coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);\r
+ coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);\r
+ coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);\r
+\r
+ // We might use the (not yet accepted) Boost.Interval\r
+ // submission in the future\r
+\r
+ // If:\r
+ // B1: |-------|\r
+ // B2: |------|\r
+ // in any dimension -> no overlap\r
+ if (max1 <= min2 || min1 >= max2)\r
+ {\r
+ overlaps = false;\r
+ return;\r
+ }\r
+\r
+ // If:\r
+ // B1: |--------------------|\r
+ // B2: |-------------|\r
+ // in all dimensions -> within, then no overlap\r
+ // B1: |--------------------|\r
+ // B2: |-------------|\r
+ // this is "within-touch" -> then no overlap. So use < and >\r
+ if (min1 < min2 || max1 > max2)\r
+ {\r
+ one_in_two = false;\r
+ }\r
+\r
+ // Same other way round\r
+ if (min2 < min1 || max2 > max1)\r
+ {\r
+ two_in_one = false;\r
+ }\r
+\r
+ box_box_loop\r
+ <\r
+ Dimension + 1,\r
+ DimensionCount\r
+ >::apply(b1, b2, overlaps, one_in_two, two_in_one);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ std::size_t DimensionCount\r
+>\r
+struct box_box_loop<DimensionCount, DimensionCount>\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)\r
+ {\r
+ }\r
+};\r
+\r
+struct box_box\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline bool apply(Box1 const& b1, Box2 const& b2)\r
+ {\r
+ bool overlaps = true;\r
+ bool within1 = true;\r
+ bool within2 = true;\r
+ box_box_loop\r
+ <\r
+ 0,\r
+ dimension<Box1>::type::value\r
+ >::apply(b1, b2, overlaps, within1, within2);\r
+\r
+ /*\r
+ \see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps\r
+ where is stated that "inside" is not an "overlap",\r
+ this is true and is implemented as such.\r
+ */\r
+ return overlaps && ! within1 && ! within2;\r
+ }\r
+};\r
+\r
+}} // namespace detail::overlaps\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+//struct not_implemented_for_this_geometry_type : public boost::false_type {};\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag2 = typename tag<Geometry2>::type\r
+>\r
+struct overlaps\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_overlaps_type,\r
+ Geometry1,\r
+ Geometry2\r
+ >\r
+{};\r
+\r
+\r
+template <typename Box1, typename Box2>\r
+struct overlaps<Box1, Box2, box_tag, box_tag>\r
+ : detail::overlaps::box_box\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief \brief_check2{overlap}\r
+\ingroup overlaps\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_check2{overlap}\r
+\r
+\qbk{[include reference/algorithms/overlaps.qbk]}\r
+*/\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return dispatch::overlaps\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP\r
+\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/length.hpp>\r
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>\r
+#include <boost/geometry/algorithms/detail/calculate_sum.hpp>\r
+#include <boost/geometry/algorithms/detail/multi_sum.hpp>\r
+// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/strategies/default_length_result.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+// Default perimeter is 0.0, specializations implement calculated values\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct perimeter : detail::calculate_null\r
+{\r
+ typedef typename default_length_result<Geometry>::type return_type;\r
+\r
+ template <typename Strategy>\r
+ static inline return_type apply(Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ return calculate_null::apply<return_type>(geometry, strategy);\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct perimeter<Geometry, ring_tag>\r
+ : detail::length::range_length\r
+ <\r
+ Geometry,\r
+ closure<Geometry>::value\r
+ >\r
+{};\r
+\r
+template <typename Polygon>\r
+struct perimeter<Polygon, polygon_tag> : detail::calculate_polygon_sum\r
+{\r
+ typedef typename default_length_result<Polygon>::type return_type;\r
+ typedef detail::length::range_length\r
+ <\r
+ typename ring_type<Polygon>::type,\r
+ closure<Polygon>::value\r
+ > policy;\r
+\r
+ template <typename Strategy>\r
+ static inline return_type apply(Polygon const& polygon, Strategy const& strategy)\r
+ {\r
+ return calculate_polygon_sum::apply<return_type, policy>(polygon, strategy);\r
+ }\r
+};\r
+\r
+template <typename MultiPolygon>\r
+struct perimeter<MultiPolygon, multi_polygon_tag> : detail::multi_sum\r
+{\r
+ typedef typename default_length_result<MultiPolygon>::type return_type;\r
+\r
+ template <typename Strategy>\r
+ static inline return_type apply(MultiPolygon const& multi, Strategy const& strategy)\r
+ {\r
+ return multi_sum::apply\r
+ <\r
+ return_type,\r
+ perimeter<typename boost::range_value<MultiPolygon>::type>\r
+ >(multi, strategy);\r
+ }\r
+};\r
+\r
+\r
+// box,n-sphere: to be implemented\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy {\r
+\r
+struct perimeter\r
+{\r
+ template <typename Geometry, typename Strategy>\r
+ static inline typename default_length_result<Geometry>::type\r
+ apply(Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ return dispatch::perimeter<Geometry>::apply(geometry, strategy);\r
+ }\r
+\r
+ template <typename Geometry>\r
+ static inline typename default_length_result<Geometry>::type\r
+ apply(Geometry const& geometry, default_strategy)\r
+ {\r
+ typedef typename strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, point_tag, typename point_type<Geometry>::type\r
+ >::type strategy_type;\r
+\r
+ return dispatch::perimeter<Geometry>::apply(geometry, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct perimeter\r
+{\r
+ template <typename Strategy>\r
+ static inline typename default_length_result<Geometry>::type\r
+ apply(Geometry const& geometry, Strategy const& strategy)\r
+ {\r
+ concepts::check<Geometry const>();\r
+ return resolve_strategy::perimeter::apply(geometry, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct perimeter<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ typedef typename default_length_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>\r
+ >::type result_type;\r
+\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<result_type>\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy): m_strategy(strategy) {}\r
+\r
+ template <typename Geometry>\r
+ typename default_length_result<Geometry>::type\r
+ operator()(Geometry const& geometry) const\r
+ {\r
+ return perimeter<Geometry>::apply(geometry, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline result_type\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_calc{perimeter}\r
+\ingroup perimeter\r
+\details The function perimeter returns the perimeter of a geometry,\r
+ using the default distance-calculation-strategy\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_calc{perimeter}\r
+\r
+\qbk{[include reference/algorithms/perimeter.qbk]}\r
+ */\r
+template<typename Geometry>\r
+inline typename default_length_result<Geometry>::type perimeter(\r
+ Geometry const& geometry)\r
+{\r
+ // detail::throw_on_empty_input(geometry);\r
+ return resolve_variant::perimeter<Geometry>::apply(geometry, default_strategy());\r
+}\r
+\r
+/*!\r
+\brief \brief_calc{perimeter} \brief_strategy\r
+\ingroup perimeter\r
+\details The function perimeter returns the perimeter of a geometry,\r
+ using specified strategy\r
+\tparam Geometry \tparam_geometry\r
+\tparam Strategy \tparam_strategy{distance}\r
+\param geometry \param_geometry\r
+\param strategy strategy to be used for distance calculations.\r
+\return \return_calc{perimeter}\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/perimeter.qbk]}\r
+ */\r
+template<typename Geometry, typename Strategy>\r
+inline typename default_length_result<Geometry>::type perimeter(\r
+ Geometry const& geometry, Strategy const& strategy)\r
+{\r
+ // detail::throw_on_empty_input(geometry);\r
+ return resolve_variant::perimeter<Geometry>::apply(geometry, strategy);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_POINT_ON_SURFACE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_POINT_ON_SURFACE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <numeric>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/extreme_points.hpp>\r
+\r
+#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace point_on_surface\r
+{\r
+\r
+template <typename CoordinateType, int Dimension>\r
+struct specific_coordinate_first\r
+{\r
+ CoordinateType const m_value_to_be_first;\r
+\r
+ inline specific_coordinate_first(CoordinateType value_to_be_skipped)\r
+ : m_value_to_be_first(value_to_be_skipped)\r
+ {}\r
+\r
+ template <typename Point>\r
+ inline bool operator()(Point const& lhs, Point const& rhs)\r
+ {\r
+ CoordinateType const lh = geometry::get<Dimension>(lhs);\r
+ CoordinateType const rh = geometry::get<Dimension>(rhs);\r
+\r
+ // If both lhs and rhs equal m_value_to_be_first,\r
+ // we should handle conform if lh < rh = FALSE\r
+ // The first condition meets that, keep it first\r
+ if (geometry::math::equals(rh, m_value_to_be_first))\r
+ {\r
+ // Handle conform lh < -INF, which is always false\r
+ return false;\r
+ }\r
+\r
+ if (geometry::math::equals(lh, m_value_to_be_first))\r
+ {\r
+ // Handle conform -INF < rh, which is always true\r
+ return true;\r
+ }\r
+\r
+ return lh < rh;\r
+ }\r
+};\r
+\r
+template <int Dimension, typename Collection, typename Value, typename Predicate>\r
+inline bool max_value(Collection const& collection, Value& the_max, Predicate const& predicate)\r
+{\r
+ bool first = true;\r
+ for (typename Collection::const_iterator it = collection.begin(); it != collection.end(); ++it)\r
+ {\r
+ if (! it->empty())\r
+ {\r
+ Value the_value = geometry::get<Dimension>(*std::max_element(it->begin(), it->end(), predicate));\r
+ if (first || the_value > the_max)\r
+ {\r
+ the_max = the_value;\r
+ first = false;\r
+ }\r
+ }\r
+ }\r
+ return ! first;\r
+}\r
+\r
+\r
+template <int Dimension, typename Value>\r
+struct select_below\r
+{\r
+ Value m_value;\r
+ inline select_below(Value const& v)\r
+ : m_value(v)\r
+ {}\r
+\r
+ template <typename Intruder>\r
+ inline bool operator()(Intruder const& intruder) const\r
+ {\r
+ if (intruder.empty())\r
+ {\r
+ return true;\r
+ }\r
+ Value max = geometry::get<Dimension>(*std::max_element(intruder.begin(), intruder.end(), detail::extreme_points::compare<Dimension>()));\r
+ return geometry::math::equals(max, m_value) || max < m_value;\r
+ }\r
+};\r
+\r
+template <int Dimension, typename Value>\r
+struct adapt_base\r
+{\r
+ Value m_value;\r
+ inline adapt_base(Value const& v)\r
+ : m_value(v)\r
+ {}\r
+\r
+ template <typename Intruder>\r
+ inline void operator()(Intruder& intruder) const\r
+ {\r
+ if (intruder.size() >= 3)\r
+ {\r
+ detail::extreme_points::move_along_vector<Dimension>(intruder, m_value);\r
+ }\r
+ }\r
+};\r
+\r
+template <int Dimension, typename Value>\r
+struct min_of_intruder\r
+{\r
+ template <typename Intruder>\r
+ inline bool operator()(Intruder const& lhs, Intruder const& rhs) const\r
+ {\r
+ Value lhs_min = geometry::get<Dimension>(*std::min_element(lhs.begin(), lhs.end(), detail::extreme_points::compare<Dimension>()));\r
+ Value rhs_min = geometry::get<Dimension>(*std::min_element(rhs.begin(), rhs.end(), detail::extreme_points::compare<Dimension>()));\r
+ return lhs_min < rhs_min;\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, typename P>\r
+inline void calculate_average(Point& point, std::vector<P> const& points)\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+ typedef typename std::vector<P>::const_iterator iterator_type;\r
+ typedef typename std::vector<P>::size_type size_type;\r
+\r
+ coordinate_type x = 0;\r
+ coordinate_type y = 0;\r
+\r
+ iterator_type end = points.end();\r
+ for ( iterator_type it = points.begin() ; it != end ; ++it)\r
+ {\r
+ x += geometry::get<0>(*it);\r
+ y += geometry::get<1>(*it);\r
+ }\r
+\r
+ size_type const count = points.size();\r
+ geometry::set<0>(point, x / count);\r
+ geometry::set<1>(point, y / count);\r
+}\r
+\r
+\r
+template <int Dimension, typename Extremes, typename Intruders, typename CoordinateType>\r
+inline void replace_extremes_for_self_tangencies(Extremes& extremes, Intruders& intruders, CoordinateType const& max_intruder)\r
+{\r
+ // This function handles self-tangencies.\r
+ // Self-tangencies use, as usual, the major part of code...\r
+\r
+ // ___ e\r
+ // /|\ \ .\r
+ // / | \ \ .\r
+ // / | \ \ .\r
+ // / | \ \ .\r
+ // / /\ | \ \ .\r
+ // i2 i1\r
+\r
+ // The picture above shows the extreme (outside, "e") and two intruders ("i1","i2")\r
+ // Assume that "i1" is self-tangent with the extreme, in one point at the top\r
+ // Now the "penultimate" value is searched, this is is the top of i2\r
+ // Then everything including and below (this is "i2" here) is removed\r
+ // Then the base of "i1" and of "e" is adapted to this penultimate value\r
+ // It then looks like:\r
+\r
+ // b ___ e\r
+ // /|\ \ .\r
+ // / | \ \ .\r
+ // / | \ \ .\r
+ // / | \ \ .\r
+ // a c i1\r
+\r
+ // Then intruders (here "i1" but there may be more) are sorted from left to right\r
+ // Finally points "a","b" and "c" (in this order) are selected as a new triangle.\r
+ // This triangle will have a centroid which is inside (assumed that intruders left segment\r
+ // is not equal to extremes left segment, but that polygon would be invalid)\r
+\r
+ // Find highest non-self tangent intrusion, if any\r
+ CoordinateType penultimate_value;\r
+ specific_coordinate_first<CoordinateType, Dimension> pu_compare(max_intruder);\r
+ if (max_value<Dimension>(intruders, penultimate_value, pu_compare))\r
+ {\r
+ // Throw away all intrusions <= this value, and of the kept one set this as base.\r
+ select_below<Dimension, CoordinateType> predicate(penultimate_value);\r
+ intruders.erase\r
+ (\r
+ std::remove_if(boost::begin(intruders), boost::end(intruders), predicate),\r
+ boost::end(intruders)\r
+ );\r
+ adapt_base<Dimension, CoordinateType> fe_predicate(penultimate_value);\r
+ // Sort from left to right (or bottom to top if Dimension=0)\r
+ std::for_each(boost::begin(intruders), boost::end(intruders), fe_predicate);\r
+\r
+ // Also adapt base of extremes\r
+ detail::extreme_points::move_along_vector<Dimension>(extremes, penultimate_value);\r
+ }\r
+ // Then sort in 1-Dim. Take first to calc centroid.\r
+ std::sort(boost::begin(intruders), boost::end(intruders), min_of_intruder<1 - Dimension, CoordinateType>());\r
+\r
+ Extremes triangle;\r
+ triangle.reserve(3);\r
+\r
+ // Make a triangle of first two points of extremes (the ramp, from left to right), and last point of first intruder (which goes from right to left)\r
+ std::copy(extremes.begin(), extremes.begin() + 2, std::back_inserter(triangle));\r
+ triangle.push_back(intruders.front().back());\r
+\r
+ // (alternatively we could use the last two points of extremes, and first point of last intruder...):\r
+ //// ALTERNATIVE: std::copy(extremes.rbegin(), extremes.rbegin() + 2, std::back_inserter(triangle));\r
+ //// ALTERNATIVE: triangle.push_back(intruders.back().front());\r
+\r
+ // Now replace extremes with this smaller subset, a triangle, such that centroid calculation will result in a point inside\r
+ extremes = triangle;\r
+}\r
+\r
+template <int Dimension, typename Geometry, typename Point>\r
+inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;\r
+ std::vector<point_type> extremes;\r
+\r
+ typedef std::vector<std::vector<point_type> > intruders_type;\r
+ intruders_type intruders;\r
+ geometry::extreme_points<Dimension>(geometry, extremes, intruders);\r
+\r
+ if (extremes.size() < 3)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // If there are intruders, find the max.\r
+ if (! intruders.empty())\r
+ {\r
+ coordinate_type max_intruder;\r
+ detail::extreme_points::compare<Dimension> compare;\r
+ if (max_value<Dimension>(intruders, max_intruder, compare))\r
+ {\r
+ coordinate_type max_extreme = geometry::get<Dimension>(*std::max_element(extremes.begin(), extremes.end(), detail::extreme_points::compare<Dimension>()));\r
+ if (max_extreme > max_intruder)\r
+ {\r
+ detail::extreme_points::move_along_vector<Dimension>(extremes, max_intruder);\r
+ }\r
+ else\r
+ {\r
+ replace_extremes_for_self_tangencies<Dimension>(extremes, intruders, max_intruder);\r
+ }\r
+ }\r
+ }\r
+\r
+ // Now calculate the average/centroid of the (possibly adapted) extremes\r
+ calculate_average(point, extremes);\r
+\r
+ return true;\r
+}\r
+\r
+}} // namespace detail::point_on_surface\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Assigns a Point guaranteed to lie on the surface of the Geometry\r
+\tparam Geometry geometry type. This also defines the type of the output point\r
+\param geometry Geometry to take point from\r
+\param point Point to assign\r
+ */\r
+template <typename Geometry, typename Point>\r
+inline void point_on_surface(Geometry const& geometry, Point & point)\r
+{\r
+ concepts::check<Point>();\r
+ concepts::check<Geometry const>();\r
+\r
+ // First try in Y-direction (which should always succeed for valid polygons)\r
+ if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point))\r
+ {\r
+ // For invalid polygons, we might try X-direction\r
+ detail::point_on_surface::calculate_point_on_surface<0>(geometry, point);\r
+ }\r
+}\r
+\r
+/*!\r
+\brief Returns point guaranteed to lie on the surface of the Geometry\r
+\tparam Geometry geometry type. This also defines the type of the output point\r
+\param geometry Geometry to take point from\r
+\return The Point guaranteed to lie on the surface of the Geometry\r
+ */\r
+template<typename Geometry>\r
+inline typename geometry::point_type<Geometry>::type\r
+return_point_on_surface(Geometry const& geometry)\r
+{\r
+ typename geometry::point_type<Geometry>::type result;\r
+ geometry::point_on_surface(geometry, result);\r
+ return result;\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_POINT_ON_SURFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_RELATE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_RELATE_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_RELATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_RELATION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_RELATION_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/relation/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/relation/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_RELATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_REMOVE_SPIKES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_REMOVE_SPIKES_HPP\r
+\r
+#include <deque>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+\r
+/*\r
+Remove spikes from a ring/polygon.\r
+Ring (having 8 vertices, including closing vertex)\r
++------+\r
+| |\r
+| +--+\r
+| | ^this "spike" is removed, can be located outside/inside the ring\r
++------+\r
+(the actualy determination if it is removed is done by a strategy)\r
+\r
+*/\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace remove_spikes\r
+{\r
+\r
+\r
+template <typename Range>\r
+struct range_remove_spikes\r
+{\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Range>::type\r
+ >::type side_strategy;\r
+\r
+ typedef typename coordinate_type<Range>::type coordinate_type;\r
+ typedef typename point_type<Range>::type point_type;\r
+\r
+\r
+ static inline void apply(Range& range)\r
+ {\r
+ std::size_t n = boost::size(range);\r
+ std::size_t const min_num_points = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Range>::value\r
+ >::value - 1; // subtract one: a polygon with only one spike should result into one point\r
+ if (n < min_num_points)\r
+ {\r
+ return;\r
+ }\r
+\r
+ std::deque<point_type> cleaned;\r
+ for (typename boost::range_iterator<Range const>::type it = boost::begin(range);\r
+ it != boost::end(range); ++it)\r
+ {\r
+ // Add point\r
+ cleaned.push_back(*it);\r
+\r
+ while(cleaned.size() >= 3\r
+ && detail::point_is_spike_or_equal(cleaned.back(), *(cleaned.end() - 3), *(cleaned.end() - 2)))\r
+ {\r
+ // Remove pen-ultimate point causing the spike (or which was equal)\r
+ cleaned.erase(cleaned.end() - 2);\r
+ }\r
+ }\r
+\r
+ // For a closed-polygon, remove closing point, this makes checking first point(s) easier and consistent\r
+ if ( BOOST_GEOMETRY_CONDITION(geometry::closure<Range>::value == geometry::closed) )\r
+ {\r
+ cleaned.pop_back();\r
+ }\r
+\r
+ bool found = false;\r
+ do\r
+ {\r
+ found = false;\r
+ // Check for spike in first point\r
+ int const penultimate = 2;\r
+ while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(cleaned.front(), *(cleaned.end() - penultimate), cleaned.back()))\r
+ {\r
+ cleaned.pop_back();\r
+ found = true;\r
+ }\r
+ // Check for spike in second point\r
+ while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(*(cleaned.begin() + 1), cleaned.back(), cleaned.front()))\r
+ {\r
+ cleaned.pop_front();\r
+ found = true;\r
+ }\r
+ }\r
+ while (found);\r
+\r
+ if (cleaned.size() == 2)\r
+ {\r
+ // Ticket #9871: open polygon with only two points.\r
+ // the second point forms, by definition, a spike\r
+ cleaned.pop_back();\r
+ }\r
+\r
+ // Close if necessary\r
+ if ( BOOST_GEOMETRY_CONDITION(geometry::closure<Range>::value == geometry::closed) )\r
+ {\r
+ cleaned.push_back(cleaned.front());\r
+ }\r
+\r
+ // Copy output\r
+ geometry::clear(range);\r
+ std::copy(cleaned.begin(), cleaned.end(), range::back_inserter(range));\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct polygon_remove_spikes\r
+{\r
+ static inline void apply(Polygon& polygon)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+\r
+ typedef range_remove_spikes<ring_type> per_range;\r
+ per_range::apply(exterior_ring(polygon));\r
+\r
+ typename interior_return_type<Polygon>::type\r
+ rings = interior_rings(polygon);\r
+\r
+ for (typename detail::interior_iterator<Polygon>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ per_range::apply(*it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiGeometry, typename SingleVersion>\r
+struct multi_remove_spikes\r
+{\r
+ static inline void apply(MultiGeometry& multi)\r
+ {\r
+ for (typename boost::range_iterator<MultiGeometry>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ SingleVersion::apply(*it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::remove_spikes\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct remove_spikes\r
+{\r
+ static inline void apply(Geometry&)\r
+ {}\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct remove_spikes<Ring, ring_tag>\r
+ : detail::remove_spikes::range_remove_spikes<Ring>\r
+{};\r
+\r
+\r
+\r
+template <typename Polygon>\r
+struct remove_spikes<Polygon, polygon_tag>\r
+ : detail::remove_spikes::polygon_remove_spikes<Polygon>\r
+{};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct remove_spikes<MultiPolygon, multi_polygon_tag>\r
+ : detail::remove_spikes::multi_remove_spikes\r
+ <\r
+ MultiPolygon,\r
+ detail::remove_spikes::polygon_remove_spikes\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct remove_spikes\r
+{\r
+ static void apply(Geometry& geometry)\r
+ {\r
+ concepts::check<Geometry>();\r
+ dispatch::remove_spikes<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ template <typename Geometry>\r
+ void operator()(Geometry& geometry) const\r
+ {\r
+ remove_spikes<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)\r
+ {\r
+ boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+ \ingroup remove_spikes\r
+ \tparam Geometry geometry type\r
+ \param geometry the geometry to make remove_spikes\r
+*/\r
+template <typename Geometry>\r
+inline void remove_spikes(Geometry& geometry)\r
+{\r
+ resolve_variant::remove_spikes<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_REMOVE_SPIKES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/detail/multi_modify.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace reverse\r
+{\r
+\r
+\r
+struct range_reverse\r
+{\r
+ template <typename Range>\r
+ static inline void apply(Range& range)\r
+ {\r
+ std::reverse(boost::begin(range), boost::end(range));\r
+ }\r
+};\r
+\r
+\r
+struct polygon_reverse: private range_reverse\r
+{\r
+ template <typename Polygon>\r
+ static inline void apply(Polygon& polygon)\r
+ {\r
+ range_reverse::apply(exterior_ring(polygon));\r
+\r
+ typename interior_return_type<Polygon>::type\r
+ rings = interior_rings(polygon);\r
+\r
+ for (typename detail::interior_iterator<Polygon>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ range_reverse::apply(*it);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::reverse\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct reverse\r
+{\r
+ static inline void apply(Geometry&)\r
+ {}\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct reverse<Ring, ring_tag>\r
+ : detail::reverse::range_reverse\r
+{};\r
+\r
+\r
+template <typename LineString>\r
+struct reverse<LineString, linestring_tag>\r
+ : detail::reverse::range_reverse\r
+{};\r
+\r
+\r
+template <typename Polygon>\r
+struct reverse<Polygon, polygon_tag>\r
+ : detail::reverse::polygon_reverse\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct reverse<Geometry, multi_linestring_tag>\r
+ : detail::multi_modify\r
+ <\r
+ Geometry,\r
+ detail::reverse::range_reverse\r
+ >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct reverse<Geometry, multi_polygon_tag>\r
+ : detail::multi_modify\r
+ <\r
+ Geometry,\r
+ detail::reverse::polygon_reverse\r
+ >\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct reverse\r
+{\r
+ static void apply(Geometry& geometry)\r
+ {\r
+ concepts::check<Geometry>();\r
+ dispatch::reverse<Geometry>::apply(geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct reverse<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ template <typename Geometry>\r
+ void operator()(Geometry& geometry) const\r
+ {\r
+ reverse<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)\r
+ {\r
+ boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Reverses the points within a geometry\r
+\details Generic function to reverse a geometry. It resembles the std::reverse\r
+ functionality, but it takes the geometry type into account. Only for a ring\r
+ or for a linestring it is the same as the std::reverse.\r
+\ingroup reverse\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry which will be reversed\r
+\r
+\qbk{[include reference/algorithms/reverse.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline void reverse(Geometry& geometry)\r
+{\r
+ resolve_variant::reverse<Geometry>::apply(geometry);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>\r
+#include <boost/geometry/strategies/concepts/simplify_concept.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace simplify\r
+{\r
+\r
+struct simplify_range_insert\r
+{\r
+ template<typename Range, typename Strategy, typename OutputIterator, typename Distance>\r
+ static inline void apply(Range const& range, OutputIterator out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused(strategy);\r
+\r
+ if (boost::size(range) <= 2 || max_distance < 0)\r
+ {\r
+ std::copy(boost::begin(range), boost::end(range), out);\r
+ }\r
+ else\r
+ {\r
+ strategy.apply(range, out, max_distance);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+struct simplify_copy\r
+{\r
+ template <typename Range, typename Strategy, typename Distance>\r
+ static inline void apply(Range const& range, Range& out,\r
+ Distance const& , Strategy const& )\r
+ {\r
+ std::copy\r
+ (\r
+ boost::begin(range), boost::end(range), geometry::range::back_inserter(out)\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template<std::size_t Minimum>\r
+struct simplify_range\r
+{\r
+ template <typename Range, typename Strategy, typename Distance>\r
+ static inline void apply(Range const& range, Range& out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+ {\r
+ // Call do_container for a linestring / ring\r
+\r
+ /* For a RING:\r
+ The first/last point (the closing point of the ring) should maybe\r
+ be excluded because it lies on a line with second/one but last.\r
+ Here it is never excluded.\r
+\r
+ Note also that, especially if max_distance is too large,\r
+ the output ring might be self intersecting while the input ring is\r
+ not, although chances are low in normal polygons\r
+\r
+ Finally the inputring might have 3 (open) or 4 (closed) points (=correct),\r
+ the output < 3 or 4(=wrong)\r
+ */\r
+\r
+ if (boost::size(range) <= int(Minimum) || max_distance < 0.0)\r
+ {\r
+ simplify_copy::apply(range, out, max_distance, strategy);\r
+ }\r
+ else\r
+ {\r
+ simplify_range_insert::apply\r
+ (\r
+ range, geometry::range::back_inserter(out), max_distance, strategy\r
+ );\r
+ }\r
+ }\r
+};\r
+\r
+struct simplify_polygon\r
+{\r
+private:\r
+\r
+ template\r
+ <\r
+ std::size_t Minimum,\r
+ typename IteratorIn,\r
+ typename IteratorOut,\r
+ typename Distance,\r
+ typename Strategy\r
+ >\r
+ static inline void iterate(IteratorIn begin, IteratorIn end,\r
+ IteratorOut it_out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+ {\r
+ for (IteratorIn it_in = begin; it_in != end; ++it_in, ++it_out)\r
+ {\r
+ simplify_range<Minimum>::apply(*it_in, *it_out, max_distance, strategy);\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ std::size_t Minimum,\r
+ typename InteriorRingsIn,\r
+ typename InteriorRingsOut,\r
+ typename Distance,\r
+ typename Strategy\r
+ >\r
+ static inline void apply_interior_rings(\r
+ InteriorRingsIn const& interior_rings_in,\r
+ InteriorRingsOut& interior_rings_out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+ {\r
+ traits::resize<InteriorRingsOut>::apply(interior_rings_out,\r
+ boost::size(interior_rings_in));\r
+\r
+ iterate<Minimum>(\r
+ boost::begin(interior_rings_in), boost::end(interior_rings_in),\r
+ boost::begin(interior_rings_out),\r
+ max_distance, strategy);\r
+ }\r
+\r
+public:\r
+ template <typename Polygon, typename Strategy, typename Distance>\r
+ static inline void apply(Polygon const& poly_in, Polygon& poly_out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+ {\r
+ std::size_t const minimum = core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Polygon>::value\r
+ >::value;\r
+\r
+ // Note that if there are inner rings, and distance is too large,\r
+ // they might intersect with the outer ring in the output,\r
+ // while it didn't in the input.\r
+ simplify_range<minimum>::apply(exterior_ring(poly_in),\r
+ exterior_ring(poly_out),\r
+ max_distance, strategy);\r
+\r
+ apply_interior_rings<minimum>(interior_rings(poly_in),\r
+ interior_rings(poly_out),\r
+ max_distance, strategy);\r
+ }\r
+};\r
+\r
+\r
+template<typename Policy>\r
+struct simplify_multi\r
+{\r
+ template <typename MultiGeometry, typename Strategy, typename Distance>\r
+ static inline void apply(MultiGeometry const& multi, MultiGeometry& out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+ {\r
+ traits::resize<MultiGeometry>::apply(out, boost::size(multi));\r
+\r
+ typename boost::range_iterator<MultiGeometry>::type it_out\r
+ = boost::begin(out);\r
+ for (typename boost::range_iterator<MultiGeometry const>::type\r
+ it_in = boost::begin(multi);\r
+ it_in != boost::end(multi);\r
+ ++it_in, ++it_out)\r
+ {\r
+ Policy::apply(*it_in, *it_out, max_distance, strategy);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::simplify\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct simplify: not_implemented<Tag>\r
+{};\r
+\r
+template <typename Point>\r
+struct simplify<Point, point_tag>\r
+{\r
+ template <typename Distance, typename Strategy>\r
+ static inline void apply(Point const& point, Point& out,\r
+ Distance const& , Strategy const& )\r
+ {\r
+ geometry::convert(point, out);\r
+ }\r
+};\r
+\r
+\r
+template <typename Linestring>\r
+struct simplify<Linestring, linestring_tag>\r
+ : detail::simplify::simplify_range<2>\r
+{};\r
+\r
+template <typename Ring>\r
+struct simplify<Ring, ring_tag>\r
+ : detail::simplify::simplify_range\r
+ <\r
+ core_detail::closure::minimum_ring_size\r
+ <\r
+ geometry::closure<Ring>::value\r
+ >::value\r
+ >\r
+{};\r
+\r
+template <typename Polygon>\r
+struct simplify<Polygon, polygon_tag>\r
+ : detail::simplify::simplify_polygon\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct simplify_insert: not_implemented<Tag>\r
+{};\r
+\r
+\r
+template <typename Linestring>\r
+struct simplify_insert<Linestring, linestring_tag>\r
+ : detail::simplify::simplify_range_insert\r
+{};\r
+\r
+template <typename Ring>\r
+struct simplify_insert<Ring, ring_tag>\r
+ : detail::simplify::simplify_range_insert\r
+{};\r
+\r
+template <typename MultiPoint>\r
+struct simplify<MultiPoint, multi_point_tag>\r
+ : detail::simplify::simplify_copy\r
+{};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct simplify<MultiLinestring, multi_linestring_tag>\r
+ : detail::simplify::simplify_multi<detail::simplify::simplify_range<2> >\r
+{};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct simplify<MultiPolygon, multi_polygon_tag>\r
+ : detail::simplify::simplify_multi<detail::simplify::simplify_polygon>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+struct simplify\r
+{\r
+ template <typename Geometry, typename Distance, typename Strategy>\r
+ static inline void apply(Geometry const& geometry,\r
+ Geometry& out,\r
+ Distance const& max_distance,\r
+ Strategy const& strategy)\r
+ {\r
+ dispatch::simplify<Geometry>::apply(geometry, out, max_distance, strategy);\r
+ }\r
+\r
+ template <typename Geometry, typename Distance>\r
+ static inline void apply(Geometry const& geometry,\r
+ Geometry& out,\r
+ Distance const& max_distance,\r
+ default_strategy)\r
+ {\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ typedef typename strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, segment_tag, point_type\r
+ >::type ds_strategy_type;\r
+\r
+ typedef strategy::simplify::douglas_peucker\r
+ <\r
+ point_type, ds_strategy_type\r
+ > strategy_type;\r
+\r
+ BOOST_CONCEPT_ASSERT(\r
+ (concepts::SimplifyStrategy<strategy_type, point_type>)\r
+ );\r
+\r
+ apply(geometry, out, max_distance, strategy_type());\r
+ }\r
+};\r
+\r
+struct simplify_insert\r
+{\r
+ template\r
+ <\r
+ typename Geometry,\r
+ typename OutputIterator,\r
+ typename Distance,\r
+ typename Strategy\r
+ >\r
+ static inline void apply(Geometry const& geometry,\r
+ OutputIterator& out,\r
+ Distance const& max_distance,\r
+ Strategy const& strategy)\r
+ {\r
+ dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy);\r
+ }\r
+\r
+ template <typename Geometry, typename OutputIterator, typename Distance>\r
+ static inline void apply(Geometry const& geometry,\r
+ OutputIterator& out,\r
+ Distance const& max_distance,\r
+ default_strategy)\r
+ {\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ typedef typename strategy::distance::services::default_strategy\r
+ <\r
+ point_tag, segment_tag, point_type\r
+ >::type ds_strategy_type;\r
+\r
+ typedef strategy::simplify::douglas_peucker\r
+ <\r
+ point_type, ds_strategy_type\r
+ > strategy_type;\r
+\r
+ BOOST_CONCEPT_ASSERT(\r
+ (concepts::SimplifyStrategy<strategy_type, point_type>)\r
+ );\r
+\r
+ apply(geometry, out, max_distance, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry>\r
+struct simplify\r
+{\r
+ template <typename Distance, typename Strategy>\r
+ static inline void apply(Geometry const& geometry,\r
+ Geometry& out,\r
+ Distance const& max_distance,\r
+ Strategy const& strategy)\r
+ {\r
+ resolve_strategy::simplify::apply(geometry, out, max_distance, strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct simplify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Distance, typename Strategy>\r
+ struct visitor: boost::static_visitor<void>\r
+ {\r
+ Distance const& m_max_distance;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Distance const& max_distance, Strategy const& strategy)\r
+ : m_max_distance(max_distance)\r
+ , m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ void operator()(Geometry const& geometry, Geometry& out) const\r
+ {\r
+ simplify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Distance, typename Strategy>\r
+ static inline void\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,\r
+ Distance const& max_distance,\r
+ Strategy const& strategy)\r
+ {\r
+ boost::apply_visitor(\r
+ visitor<Distance, Strategy>(max_distance, strategy),\r
+ geometry,\r
+ out\r
+ );\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Simplify a geometry using a specified strategy\r
+\ingroup simplify\r
+\tparam Geometry \tparam_geometry\r
+\tparam Distance A numerical distance measure\r
+\tparam Strategy A type fulfilling a SimplifyStrategy concept\r
+\param strategy A strategy to calculate simplification\r
+\param geometry input geometry, to be simplified\r
+\param out output geometry, simplified version of the input geometry\r
+\param max_distance distance (in units of input coordinates) of a vertex\r
+ to other segments to be removed\r
+\param strategy simplify strategy to be used for simplification, might\r
+ include point-distance strategy\r
+\r
+\image html svg_simplify_country.png "The image below presents the simplified country"\r
+\qbk{distinguish,with strategy}\r
+*/\r
+template<typename Geometry, typename Distance, typename Strategy>\r
+inline void simplify(Geometry const& geometry, Geometry& out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ geometry::clear(out);\r
+\r
+ resolve_variant::simplify<Geometry>::apply(geometry, out, max_distance, strategy);\r
+}\r
+\r
+\r
+\r
+\r
+/*!\r
+\brief Simplify a geometry\r
+\ingroup simplify\r
+\tparam Geometry \tparam_geometry\r
+\tparam Distance \tparam_numeric\r
+\note This version of simplify simplifies a geometry using the default\r
+ strategy (Douglas Peucker),\r
+\param geometry input geometry, to be simplified\r
+\param out output geometry, simplified version of the input geometry\r
+\param max_distance distance (in units of input coordinates) of a vertex\r
+ to other segments to be removed\r
+\r
+\qbk{[include reference/algorithms/simplify.qbk]}\r
+ */\r
+template<typename Geometry, typename Distance>\r
+inline void simplify(Geometry const& geometry, Geometry& out,\r
+ Distance const& max_distance)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ geometry::simplify(geometry, out, max_distance, default_strategy());\r
+}\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace simplify\r
+{\r
+\r
+\r
+/*!\r
+\brief Simplify a geometry, using an output iterator\r
+ and a specified strategy\r
+\ingroup simplify\r
+\tparam Geometry \tparam_geometry\r
+\param geometry input geometry, to be simplified\r
+\param out output iterator, outputs all simplified points\r
+\param max_distance distance (in units of input coordinates) of a vertex\r
+ to other segments to be removed\r
+\param strategy simplify strategy to be used for simplification,\r
+ might include point-distance strategy\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/simplify.qbk]}\r
+*/\r
+template<typename Geometry, typename OutputIterator, typename Distance, typename Strategy>\r
+inline void simplify_insert(Geometry const& geometry, OutputIterator out,\r
+ Distance const& max_distance, Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ resolve_strategy::simplify_insert::apply(geometry, out, max_distance, strategy);\r
+}\r
+\r
+/*!\r
+\brief Simplify a geometry, using an output iterator\r
+\ingroup simplify\r
+\tparam Geometry \tparam_geometry\r
+\param geometry input geometry, to be simplified\r
+\param out output iterator, outputs all simplified points\r
+\param max_distance distance (in units of input coordinates) of a vertex\r
+ to other segments to be removed\r
+\r
+\qbk{[include reference/algorithms/simplify_insert.qbk]}\r
+ */\r
+template<typename Geometry, typename OutputIterator, typename Distance>\r
+inline void simplify_insert(Geometry const& geometry, OutputIterator out,\r
+ Distance const& max_distance)\r
+{\r
+ // Concept: output point type = point type of input geometry\r
+ concepts::check<Geometry const>();\r
+ concepts::check<typename point_type<Geometry>::type>();\r
+\r
+ simplify_insert(geometry, out, max_distance, default_strategy());\r
+}\r
+\r
+}} // namespace detail::simplify\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP\r
+\r
+#include <algorithm>\r
+#include <iterator>\r
+#include <vector>\r
+\r
+#include <boost/geometry/algorithms/intersection.hpp>\r
+#include <boost/geometry/algorithms/union.hpp>\r
+#include <boost/geometry/geometries/multi_polygon.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace sym_difference\r
+{\r
+\r
+\r
+template <typename GeometryOut>\r
+struct compute_difference\r
+{\r
+ template\r
+ <\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ return geometry::dispatch::intersection_insert\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ GeometryOut,\r
+ overlay_difference,\r
+ geometry::detail::overlay::do_reverse\r
+ <\r
+ geometry::point_order<Geometry1>::value\r
+ >::value,\r
+ geometry::detail::overlay::do_reverse\r
+ <\r
+ geometry::point_order<Geometry2>::value, true\r
+ >::value\r
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename GeometryOut, typename Geometry1, typename Geometry2>\r
+struct sym_difference_generic\r
+{\r
+ template\r
+ <\r
+ typename RobustPolicy,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ out = compute_difference\r
+ <\r
+ GeometryOut\r
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);\r
+\r
+ return compute_difference\r
+ <\r
+ GeometryOut\r
+ >::apply(geometry2, geometry1, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+template <typename GeometryOut, typename Areal1, typename Areal2>\r
+struct sym_difference_areal_areal\r
+{\r
+ template\r
+ <\r
+ typename RobustPolicy,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+ >\r
+ static inline OutputIterator apply(Areal1 const& areal1,\r
+ Areal2 const& areal2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef geometry::model::multi_polygon\r
+ <\r
+ GeometryOut\r
+ > helper_geometry_type;\r
+\r
+ helper_geometry_type diff12, diff21;\r
+\r
+ std::back_insert_iterator<helper_geometry_type> oit12(diff12);\r
+ std::back_insert_iterator<helper_geometry_type> oit21(diff21);\r
+\r
+ compute_difference\r
+ <\r
+ GeometryOut\r
+ >::apply(areal1, areal2, robust_policy, oit12, strategy);\r
+\r
+ compute_difference\r
+ <\r
+ GeometryOut\r
+ >::apply(areal2, areal1, robust_policy, oit21, strategy);\r
+\r
+ return geometry::dispatch::union_insert\r
+ <\r
+ helper_geometry_type,\r
+ helper_geometry_type,\r
+ GeometryOut\r
+ >::apply(diff12, diff21, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::sym_difference\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename GeometryOut,\r
+ typename TagIn1 = typename geometry::tag_cast\r
+ <\r
+ typename tag<Geometry1>::type, areal_tag\r
+ >::type,\r
+ typename TagIn2 = typename geometry::tag_cast\r
+ <\r
+ typename tag<Geometry2>::type, areal_tag\r
+ >::type,\r
+ typename TagOut = typename geometry::tag<GeometryOut>::type\r
+>\r
+struct sym_difference_insert\r
+ : detail::sym_difference::sym_difference_generic\r
+ <\r
+ GeometryOut, Geometry1, Geometry2\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Areal1,\r
+ typename Areal2,\r
+ typename GeometryOut,\r
+ typename TagOut\r
+>\r
+struct sym_difference_insert\r
+ <\r
+ Areal1, Areal2, GeometryOut,\r
+ areal_tag, areal_tag, TagOut\r
+ > : detail::sym_difference::sym_difference_areal_areal\r
+ <\r
+ GeometryOut, Areal1, Areal2\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace sym_difference\r
+{\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{symmetric difference} \brief_strategy\r
+\ingroup sym_difference\r
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}\r
+ \brief_strategy. \details_insert{sym_difference}\r
+\tparam GeometryOut output geometry type, must be specified\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Strategy \tparam_strategy_overlay\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{difference}\r
+\param strategy \param_strategy{difference}\r
+\return \return_out\r
+\r
+\qbk{distinguish,with strategy}\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator,\r
+ typename Strategy\r
+>\r
+inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ concepts::check<GeometryOut>();\r
+\r
+ return dispatch::sym_difference_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut\r
+ >::apply(geometry1, geometry2, robust_policy, out, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{symmetric difference}\r
+\ingroup sym_difference\r
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}\r
+ \details_insert{sym_difference}\r
+\tparam GeometryOut output geometry type, must be specified\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{difference}\r
+\return \return_out\r
+\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename RobustPolicy,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ RobustPolicy const& robust_policy, OutputIterator out)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ concepts::check<GeometryOut>();\r
+\r
+ typedef intersection_strategies\r
+ <\r
+ typename cs_tag<GeometryOut>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ typename geometry::point_type<GeometryOut>::type,\r
+ RobustPolicy\r
+ > strategy_type;\r
+\r
+ return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type());\r
+}\r
+\r
+}} // namespace detail::sym_difference\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief \brief_calc2{symmetric difference}\r
+\ingroup sym_difference\r
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Collection output collection, either a multi-geometry,\r
+ or a std::vector<Geometry> / std::deque<Geometry> etc\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param output_collection the output collection\r
+\r
+\qbk{[include reference/algorithms/sym_difference.qbk]}\r
+*/\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Collection\r
+>\r
+inline void sym_difference(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2, Collection& output_collection)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ typedef typename boost::range_value<Collection>::type geometry_out;\r
+ concepts::check<geometry_out>();\r
+\r
+ typedef typename geometry::rescale_overlay_policy_type\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::type rescale_policy_type;\r
+\r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);\r
+\r
+ detail::sym_difference::sym_difference_insert<geometry_out>(\r
+ geometry1, geometry2, robust_policy,\r
+ range::back_inserter(output_collection));\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015.\r
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP\r
+\r
+\r
+#include <deque>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/num_geometries.hpp>\r
+#include <boost/geometry/algorithms/detail/sub_range.hpp>\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+\r
+#include <boost/geometry/algorithms/relate.hpp>\r
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace touches\r
+{\r
+\r
+// Box/Box\r
+\r
+template\r
+<\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct box_box_loop\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline bool apply(Box1 const& b1, Box2 const& b2, bool & touch)\r
+ {\r
+ typedef typename coordinate_type<Box1>::type coordinate_type1;\r
+ typedef typename coordinate_type<Box2>::type coordinate_type2;\r
+\r
+ coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);\r
+ coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);\r
+ coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);\r
+ coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);\r
+\r
+ // TODO assert or exception?\r
+ //BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2);\r
+\r
+ if (max1 < min2 || max2 < min1)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if (max1 == min2 || max2 == min1)\r
+ {\r
+ touch = true;\r
+ }\r
+ \r
+ return box_box_loop\r
+ <\r
+ Dimension + 1,\r
+ DimensionCount\r
+ >::apply(b1, b2, touch);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ std::size_t DimensionCount\r
+>\r
+struct box_box_loop<DimensionCount, DimensionCount>\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline bool apply(Box1 const& , Box2 const&, bool &)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+struct box_box\r
+{\r
+ template <typename Box1, typename Box2>\r
+ static inline bool apply(Box1 const& b1, Box2 const& b2)\r
+ {\r
+ BOOST_STATIC_ASSERT((boost::is_same\r
+ <\r
+ typename geometry::coordinate_system<Box1>::type,\r
+ typename geometry::coordinate_system<Box2>::type\r
+ >::value\r
+ ));\r
+ assert_dimension_equal<Box1, Box2>();\r
+\r
+ bool touches = false;\r
+ bool ok = box_box_loop\r
+ <\r
+ 0,\r
+ dimension<Box1>::type::value\r
+ >::apply(b1, b2, touches);\r
+\r
+ return ok && touches;\r
+ }\r
+};\r
+\r
+// Areal/Areal\r
+\r
+struct areal_interrupt_policy\r
+{\r
+ static bool const enabled = true;\r
+ bool found_touch;\r
+ bool found_not_touch;\r
+\r
+ // dummy variable required by self_get_turn_points::get_turns\r
+ static bool const has_intersections = false;\r
+\r
+ inline bool result()\r
+ {\r
+ return found_touch && !found_not_touch;\r
+ }\r
+\r
+ inline areal_interrupt_policy()\r
+ : found_touch(false), found_not_touch(false)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& range)\r
+ {\r
+ // if already rejected (temp workaround?)\r
+ if ( found_not_touch )\r
+ return true;\r
+\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+ for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )\r
+ {\r
+ if ( it->has(overlay::operation_intersection) )\r
+ {\r
+ found_not_touch = true;\r
+ return true;\r
+ }\r
+\r
+ switch(it->method)\r
+ {\r
+ case overlay::method_crosses:\r
+ found_not_touch = true;\r
+ return true;\r
+ case overlay::method_equal:\r
+ // Segment spatially equal means: at the right side\r
+ // the polygon internally overlaps. So return false.\r
+ found_not_touch = true;\r
+ return true;\r
+ case overlay::method_touch:\r
+ case overlay::method_touch_interior:\r
+ case overlay::method_collinear:\r
+ if ( ok_for_touch(*it) )\r
+ {\r
+ found_touch = true;\r
+ }\r
+ else\r
+ {\r
+ found_not_touch = true;\r
+ return true;\r
+ }\r
+ break;\r
+ case overlay::method_none :\r
+ case overlay::method_disjoint :\r
+ case overlay::method_error :\r
+ break;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ template <typename Turn>\r
+ inline bool ok_for_touch(Turn const& turn)\r
+ {\r
+ return turn.both(overlay::operation_union)\r
+ || turn.both(overlay::operation_blocked)\r
+ || turn.combination(overlay::operation_union, overlay::operation_blocked)\r
+ ;\r
+ }\r
+};\r
+\r
+template<typename Geometry>\r
+struct check_each_ring_for_within\r
+{\r
+ bool has_within;\r
+ Geometry const& m_geometry;\r
+\r
+ inline check_each_ring_for_within(Geometry const& g)\r
+ : has_within(false)\r
+ , m_geometry(g)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline void apply(Range const& range)\r
+ {\r
+ typename geometry::point_type<Range>::type p;\r
+ geometry::point_on_border(p, range);\r
+ if ( !has_within && geometry::within(p, m_geometry) )\r
+ {\r
+ has_within = true;\r
+ }\r
+ }\r
+};\r
+\r
+template <typename FirstGeometry, typename SecondGeometry>\r
+inline bool rings_containing(FirstGeometry const& geometry1,\r
+ SecondGeometry const& geometry2)\r
+{\r
+ check_each_ring_for_within<FirstGeometry> checker(geometry1);\r
+ geometry::detail::for_each_range(geometry2, checker);\r
+ return checker.has_within;\r
+}\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct areal_areal\r
+{\r
+ static inline\r
+ bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ typedef detail::no_rescale_policy rescale_policy_type;\r
+ typedef typename geometry::point_type<Geometry1>::type point_type;\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type<point_type, rescale_policy_type>::type\r
+ > turn_info;\r
+\r
+ std::deque<turn_info> turns;\r
+ detail::touches::areal_interrupt_policy policy;\r
+ rescale_policy_type robust_policy;\r
+ boost::geometry::get_turns\r
+ <\r
+ detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,\r
+ detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,\r
+ detail::overlay::assign_null_policy\r
+ >(geometry1, geometry2, robust_policy, turns, policy);\r
+\r
+ return policy.result()\r
+ && ! geometry::detail::touches::rings_containing(geometry1, geometry2)\r
+ && ! geometry::detail::touches::rings_containing(geometry2, geometry1);\r
+ }\r
+};\r
+\r
+// P/*\r
+\r
+struct use_point_in_geometry\r
+{\r
+ template <typename Point, typename Geometry>\r
+ static inline bool apply(Point const& point, Geometry const& geometry)\r
+ {\r
+ return detail::within::point_in_geometry(point, geometry) == 0;\r
+ }\r
+};\r
+\r
+}}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch {\r
+\r
+// TODO: Since CastedTags are used is Reverse needed?\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag2 = typename tag<Geometry2>::type,\r
+ typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,\r
+ typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,\r
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct touches\r
+ : not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+// If reversal is needed, perform it\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1, typename Tag2,\r
+ typename CastedTag1, typename CastedTag2\r
+>\r
+struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>\r
+ : touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>\r
+{\r
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)\r
+ {\r
+ return touches<Geometry2, Geometry1>::apply(g2, g1);\r
+ }\r
+};\r
+\r
+// P/P\r
+\r
+template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2>\r
+struct touches<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, pointlike_tag, false>\r
+{\r
+ static inline bool apply(Geometry1 const& , Geometry2 const& )\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+// P/*\r
+\r
+template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>\r
+struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>\r
+ : detail::touches::use_point_in_geometry\r
+{};\r
+\r
+// TODO: support touches(MPt, Linear/Areal)\r
+\r
+// Box/Box\r
+\r
+template <typename Box1, typename Box2, typename CastedTag1, typename CastedTag2>\r
+struct touches<Box1, Box2, box_tag, box_tag, CastedTag1, CastedTag2, false>\r
+ : detail::touches::box_box\r
+{};\r
+\r
+template <typename Box1, typename Box2>\r
+struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>\r
+ : detail::touches::box_box\r
+{};\r
+\r
+// L/L\r
+\r
+template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>\r
+struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_touches_type,\r
+ Linear1,\r
+ Linear2\r
+ >\r
+{};\r
+\r
+// L/A\r
+\r
+template <typename Linear, typename Areal, typename Tag1, typename Tag2>\r
+struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_touches_type,\r
+ Linear,\r
+ Areal\r
+ >\r
+{};\r
+\r
+// A/L\r
+template <typename Linear, typename Areal, typename Tag1, typename Tag2>\r
+struct touches<Areal, Linear, Tag1, Tag2, areal_tag, linear_tag, false>\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_touches_type,\r
+ Areal,\r
+ Linear\r
+ >\r
+{};\r
+\r
+// A/A\r
+\r
+template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>\r
+struct touches<Areal1, Areal2, Tag1, Tag2, areal_tag, areal_tag, false>\r
+ : detail::relate::relate_impl\r
+ <\r
+ detail::de9im::static_mask_touches_type,\r
+ Areal1,\r
+ Areal2\r
+ >\r
+{};\r
+\r
+template <typename Areal1, typename Areal2>\r
+struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>\r
+ : detail::touches::areal_areal<Areal1, Areal2>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct touches\r
+{\r
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ return dispatch::touches<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+\r
+ visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {}\r
+\r
+ template <typename Geometry1>\r
+ bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry2), geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+\r
+ visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {}\r
+\r
+ template <typename Geometry2>\r
+ bool operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(geometry1), geometry2);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)>\r
+struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ template <typename Geometry1, typename Geometry2>\r
+ bool operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return touches<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry1, geometry2);\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct self_touches\r
+{\r
+ static bool apply(Geometry const& geometry)\r
+ {\r
+ concepts::check<Geometry const>();\r
+\r
+ typedef detail::no_rescale_policy rescale_policy_type;\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef detail::overlay::turn_info\r
+ <\r
+ point_type,\r
+ typename segment_ratio_type<point_type, rescale_policy_type>::type\r
+ > turn_info;\r
+\r
+ typedef detail::overlay::get_turn_info\r
+ <\r
+ detail::overlay::assign_null_policy\r
+ > policy_type;\r
+\r
+ std::deque<turn_info> turns;\r
+ detail::touches::areal_interrupt_policy policy;\r
+ rescale_policy_type robust_policy;\r
+ detail::self_get_turn_points::get_turns\r
+ <\r
+ policy_type\r
+ >::apply(geometry, robust_policy, turns, policy);\r
+\r
+ return policy.result();\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ template <typename Geometry>\r
+ bool operator()(Geometry const& geometry) const\r
+ {\r
+ return self_touches<Geometry>::apply(geometry);\r
+ }\r
+ };\r
+\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)\r
+ {\r
+ return boost::apply_visitor(visitor(), geometry);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief \brief_check{has at least one touching point (self-tangency)}\r
+\note This function can be called for one geometry (self-tangency) and\r
+ also for two geometries (touch)\r
+\ingroup touches\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\return \return_check{is self-touching}\r
+\r
+\qbk{distinguish,one geometry}\r
+\qbk{[def __one_parameter__]}\r
+\qbk{[include reference/algorithms/touches.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline bool touches(Geometry const& geometry)\r
+{\r
+ return resolve_variant::self_touches<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_check2{have at least one touching point (tangent - non overlapping)}\r
+\ingroup touches\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return \return_check2{touch each other}\r
+\r
+\qbk{distinguish,two geometries}\r
+\qbk{[include reference/algorithms/touches.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::touches<Geometry1, Geometry2>::apply(geometry1, geometry2);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP\r
+\r
+#include <cmath>\r
+#include <iterator>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/transform.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace transform\r
+{\r
+\r
+struct transform_point\r
+{\r
+ template <typename Point1, typename Point2, typename Strategy>\r
+ static inline bool apply(Point1 const& p1, Point2& p2,\r
+ Strategy const& strategy)\r
+ {\r
+ return strategy.apply(p1, p2);\r
+ }\r
+};\r
+\r
+\r
+struct transform_box\r
+{\r
+ template <typename Box1, typename Box2, typename Strategy>\r
+ static inline bool apply(Box1 const& b1, Box2& b2,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename point_type<Box1>::type point_type1;\r
+ typedef typename point_type<Box2>::type point_type2;\r
+\r
+ point_type1 lower_left, upper_right;\r
+ geometry::detail::assign::assign_box_2d_corner<min_corner, min_corner>(\r
+ b1, lower_left);\r
+ geometry::detail::assign::assign_box_2d_corner<max_corner, max_corner>(\r
+ b1, upper_right);\r
+\r
+ point_type2 p1, p2;\r
+ if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))\r
+ {\r
+ // Create a valid box and therefore swap if necessary\r
+ typedef typename coordinate_type<point_type2>::type coordinate_type;\r
+ coordinate_type x1 = geometry::get<0>(p1)\r
+ , y1 = geometry::get<1>(p1)\r
+ , x2 = geometry::get<0>(p2)\r
+ , y2 = geometry::get<1>(p2);\r
+\r
+ if (x1 > x2) { std::swap(x1, x2); }\r
+ if (y1 > y2) { std::swap(y1, y2); }\r
+\r
+ geometry::set<min_corner, 0>(b2, x1);\r
+ geometry::set<min_corner, 1>(b2, y1);\r
+ geometry::set<max_corner, 0>(b2, x2);\r
+ geometry::set<max_corner, 1>(b2, y2);\r
+\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+struct transform_box_or_segment\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& source, Geometry2& target,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename point_type<Geometry1>::type point_type1;\r
+ typedef typename point_type<Geometry2>::type point_type2;\r
+\r
+ point_type1 source_point[2];\r
+ geometry::detail::assign_point_from_index<0>(source, source_point[0]);\r
+ geometry::detail::assign_point_from_index<1>(source, source_point[1]);\r
+\r
+ point_type2 target_point[2];\r
+ if (strategy.apply(source_point[0], target_point[0])\r
+ && strategy.apply(source_point[1], target_point[1]))\r
+ {\r
+ geometry::detail::assign_point_to_index<0>(target_point[0], target);\r
+ geometry::detail::assign_point_to_index<1>(target_point[1], target);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename PointOut,\r
+ typename OutputIterator,\r
+ typename Range,\r
+ typename Strategy\r
+>\r
+inline bool transform_range_out(Range const& range,\r
+ OutputIterator out, Strategy const& strategy)\r
+{\r
+ PointOut point_out;\r
+ for(typename boost::range_iterator<Range const>::type\r
+ it = boost::begin(range);\r
+ it != boost::end(range);\r
+ ++it)\r
+ {\r
+ if (! transform_point::apply(*it, point_out, strategy))\r
+ {\r
+ return false;\r
+ }\r
+ *out++ = point_out;\r
+ }\r
+ return true;\r
+}\r
+\r
+\r
+struct transform_polygon\r
+{\r
+ template <typename Polygon1, typename Polygon2, typename Strategy>\r
+ static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,\r
+ Strategy const& strategy)\r
+ {\r
+ typedef typename point_type<Polygon2>::type point2_type;\r
+\r
+ geometry::clear(poly2);\r
+\r
+ if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),\r
+ range::back_inserter(geometry::exterior_ring(poly2)), strategy))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Note: here a resizeable container is assumed.\r
+ traits::resize\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename traits::interior_mutable_type<Polygon2>::type\r
+ >::type\r
+ >::apply(geometry::interior_rings(poly2),\r
+ geometry::num_interior_rings(poly1));\r
+\r
+ typename geometry::interior_return_type<Polygon1 const>::type\r
+ rings1 = geometry::interior_rings(poly1);\r
+ typename geometry::interior_return_type<Polygon2>::type\r
+ rings2 = geometry::interior_rings(poly2);\r
+\r
+ typename detail::interior_iterator<Polygon1 const>::type\r
+ it1 = boost::begin(rings1);\r
+ typename detail::interior_iterator<Polygon2>::type\r
+ it2 = boost::begin(rings2);\r
+ for ( ; it1 != boost::end(rings1); ++it1, ++it2)\r
+ {\r
+ if ( ! transform_range_out<point2_type>(*it1,\r
+ range::back_inserter(*it2),\r
+ strategy) )\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template <typename Point1, typename Point2>\r
+struct select_strategy\r
+{\r
+ typedef typename strategy::transform::services::default_strategy\r
+ <\r
+ typename cs_tag<Point1>::type,\r
+ typename cs_tag<Point2>::type,\r
+ typename coordinate_system<Point1>::type,\r
+ typename coordinate_system<Point2>::type,\r
+ dimension<Point1>::type::value,\r
+ dimension<Point2>::type::value,\r
+ typename point_type<Point1>::type,\r
+ typename point_type<Point2>::type\r
+ >::type type;\r
+};\r
+\r
+struct transform_range\r
+{\r
+ template <typename Range1, typename Range2, typename Strategy>\r
+ static inline bool apply(Range1 const& range1,\r
+ Range2& range2, Strategy const& strategy)\r
+ {\r
+ typedef typename point_type<Range2>::type point_type;\r
+\r
+ // Should NOT be done here!\r
+ // geometry::clear(range2);\r
+ return transform_range_out<point_type>(range1,\r
+ range::back_inserter(range2), strategy);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Is able to transform any multi-geometry, calling the single-version as policy\r
+*/\r
+template <typename Policy>\r
+struct transform_multi\r
+{\r
+ template <typename Multi1, typename Multi2, typename S>\r
+ static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)\r
+ {\r
+ traits::resize<Multi2>::apply(multi2, boost::size(multi1));\r
+\r
+ typename boost::range_iterator<Multi1 const>::type it1\r
+ = boost::begin(multi1);\r
+ typename boost::range_iterator<Multi2>::type it2\r
+ = boost::begin(multi2);\r
+\r
+ for (; it1 != boost::end(multi1); ++it1, ++it2)\r
+ {\r
+ if (! Policy::apply(*it1, *it2, strategy))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::transform\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2,\r
+ typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,\r
+ typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type\r
+>\r
+struct transform {};\r
+\r
+template <typename Point1, typename Point2>\r
+struct transform<Point1, Point2, point_tag, point_tag>\r
+ : detail::transform::transform_point\r
+{\r
+};\r
+\r
+\r
+template <typename Linestring1, typename Linestring2>\r
+struct transform\r
+ <\r
+ Linestring1, Linestring2,\r
+ linestring_tag, linestring_tag\r
+ >\r
+ : detail::transform::transform_range\r
+{\r
+};\r
+\r
+template <typename Range1, typename Range2>\r
+struct transform<Range1, Range2, ring_tag, ring_tag>\r
+ : detail::transform::transform_range\r
+{\r
+};\r
+\r
+template <typename Polygon1, typename Polygon2>\r
+struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>\r
+ : detail::transform::transform_polygon\r
+{\r
+};\r
+\r
+template <typename Box1, typename Box2>\r
+struct transform<Box1, Box2, box_tag, box_tag>\r
+ : detail::transform::transform_box\r
+{\r
+};\r
+\r
+template <typename Segment1, typename Segment2>\r
+struct transform<Segment1, Segment2, segment_tag, segment_tag>\r
+ : detail::transform::transform_box_or_segment\r
+{\r
+};\r
+\r
+template <typename Multi1, typename Multi2>\r
+struct transform\r
+ <\r
+ Multi1, Multi2,\r
+ multi_tag, multi_tag\r
+ >\r
+ : detail::transform::transform_multi\r
+ <\r
+ dispatch::transform\r
+ <\r
+ typename boost::range_value<Multi1>::type,\r
+ typename boost::range_value<Multi2>::type\r
+ >\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy {\r
+\r
+struct transform\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2>();\r
+\r
+ return dispatch::transform<Geometry1, Geometry2>::apply(\r
+ geometry1,\r
+ geometry2,\r
+ strategy\r
+ );\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2& geometry2,\r
+ default_strategy)\r
+ {\r
+ return apply(\r
+ geometry1,\r
+ geometry2,\r
+ typename detail::transform::select_strategy<Geometry1, Geometry2>::type()\r
+ );\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant {\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct transform\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return resolve_strategy::transform::apply(\r
+ geometry1,\r
+ geometry2,\r
+ strategy\r
+ );\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: static_visitor<bool>\r
+ {\r
+ Geometry2& m_geometry2;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry2& geometry2, Strategy const& strategy)\r
+ : m_geometry2(geometry2)\r
+ , m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry1>\r
+ inline bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return transform<Geometry1, Geometry2>::apply(\r
+ geometry1,\r
+ m_geometry2,\r
+ m_strategy\r
+ );\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool apply(\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2& geometry2,\r
+ Strategy const& strategy\r
+ )\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);\r
+ }\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Transforms from one geometry to another geometry \brief_strategy\r
+\ingroup transform\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Strategy strategy\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param strategy The strategy to be used for transformation\r
+\return True if the transformation could be done\r
+\r
+\qbk{distinguish,with strategy}\r
+\r
+\qbk{[include reference/algorithms/transform_with_strategy.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,\r
+ Strategy const& strategy)\r
+{\r
+ return resolve_variant::transform<Geometry1, Geometry2>\r
+ ::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief Transforms from one geometry to another geometry using a strategy\r
+\ingroup transform\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\return True if the transformation could be done\r
+\r
+\qbk{[include reference/algorithms/transform.qbk]}\r
+ */\r
+template <typename Geometry1, typename Geometry2>\r
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)\r
+{\r
+ return geometry::transform(geometry1, geometry2, default_strategy());\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_UNION_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP\r
+\r
+\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+#include <boost/geometry/core/is_areal.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/reverse_dispatch.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>\r
+#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename GeometryOut,\r
+ typename TagIn1 = typename tag<Geometry1>::type,\r
+ typename TagIn2 = typename tag<Geometry2>::type,\r
+ typename TagOut = typename tag<GeometryOut>::type,\r
+ bool Areal1 = geometry::is_areal<Geometry1>::value,\r
+ bool Areal2 = geometry::is_areal<Geometry2>::value,\r
+ bool ArealOut = geometry::is_areal<GeometryOut>::value,\r
+ bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,\r
+ bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,\r
+ bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,\r
+ bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value\r
+>\r
+struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>\r
+{};\r
+\r
+\r
+// If reversal is needed, perform it first\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename GeometryOut,\r
+ typename TagIn1, typename TagIn2, typename TagOut,\r
+ bool Areal1, bool Areal2, bool ArealOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct union_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut,\r
+ TagIn1, TagIn2, TagOut,\r
+ Areal1, Areal2, ArealOut,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ true\r
+ >: union_insert<Geometry2, Geometry1, GeometryOut>\r
+{\r
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>\r
+ static inline OutputIterator apply(Geometry1 const& g1,\r
+ Geometry2 const& g2,\r
+ RobustPolicy const& robust_policy,\r
+ OutputIterator out,\r
+ Strategy const& strategy)\r
+ {\r
+ return union_insert\r
+ <\r
+ Geometry2, Geometry1, GeometryOut\r
+ >::apply(g2, g1, robust_policy, out, strategy);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename GeometryOut,\r
+ typename TagIn1, typename TagIn2, typename TagOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct union_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut,\r
+ TagIn1, TagIn2, TagOut,\r
+ true, true, true,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ false\r
+ > : detail::overlay::overlay\r
+ <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, overlay_union>\r
+{};\r
+\r
+\r
+// dispatch for union of non-areal geometries\r
+template\r
+<\r
+ typename Geometry1, typename Geometry2, typename GeometryOut,\r
+ typename TagIn1, typename TagIn2, typename TagOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct union_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut,\r
+ TagIn1, TagIn2, TagOut,\r
+ false, false, false,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ false\r
+ > : union_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut,\r
+ typename tag_cast<TagIn1, pointlike_tag, linear_tag>::type,\r
+ typename tag_cast<TagIn2, pointlike_tag, linear_tag>::type,\r
+ TagOut,\r
+ false, false, false,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ false\r
+ >\r
+{};\r
+\r
+\r
+// dispatch for union of linear geometries\r
+template\r
+<\r
+ typename Linear1, typename Linear2, typename LineStringOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct union_insert\r
+ <\r
+ Linear1, Linear2, LineStringOut,\r
+ linear_tag, linear_tag, linestring_tag,\r
+ false, false, false,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ false\r
+ > : detail::overlay::linear_linear_linestring\r
+ <\r
+ Linear1, Linear2, LineStringOut, overlay_union\r
+ >\r
+{};\r
+\r
+\r
+// dispatch for point-like geometries\r
+template\r
+<\r
+ typename PointLike1, typename PointLike2, typename PointOut,\r
+ bool Reverse1, bool Reverse2, bool ReverseOut\r
+>\r
+struct union_insert\r
+ <\r
+ PointLike1, PointLike2, PointOut,\r
+ pointlike_tag, pointlike_tag, point_tag,\r
+ false, false, false,\r
+ Reverse1, Reverse2, ReverseOut,\r
+ false\r
+ > : detail::overlay::union_pointlike_pointlike_point\r
+ <\r
+ PointLike1, PointLike2, PointOut\r
+ >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace union_\r
+{\r
+\r
+/*!\r
+\brief_calc2{union}\r
+\ingroup union\r
+\details \details_calc2{union_insert, spatial set theoretic union}.\r
+ \details_insert{union}\r
+\tparam GeometryOut output geometry type, must be specified\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam OutputIterator output iterator\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param out \param_out{union}\r
+\return \return_out\r
+*/\r
+template\r
+<\r
+ typename GeometryOut,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename OutputIterator\r
+>\r
+inline OutputIterator union_insert(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ OutputIterator out)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ concepts::check<GeometryOut>();\r
+\r
+ typedef typename geometry::rescale_overlay_policy_type\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::type rescale_policy_type;\r
+\r
+ typedef intersection_strategies\r
+ <\r
+ typename cs_tag<GeometryOut>::type,\r
+ Geometry1,\r
+ Geometry2,\r
+ typename geometry::point_type<GeometryOut>::type,\r
+ rescale_policy_type\r
+ > strategy;\r
+\r
+ rescale_policy_type robust_policy\r
+ = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2);\r
+\r
+ return dispatch::union_insert\r
+ <\r
+ Geometry1, Geometry2, GeometryOut\r
+ >::apply(geometry1, geometry2, robust_policy, out, strategy());\r
+}\r
+\r
+\r
+}} // namespace detail::union_\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+\r
+/*!\r
+\brief Combines two geometries which each other\r
+\ingroup union\r
+\details \details_calc2{union, spatial set theoretic union}.\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\tparam Collection output collection, either a multi-geometry,\r
+ or a std::vector<Geometry> / std::deque<Geometry> etc\r
+\param geometry1 \param_geometry\r
+\param geometry2 \param_geometry\r
+\param output_collection the output collection\r
+\note Called union_ because union is a reserved word.\r
+\r
+\qbk{[include reference/algorithms/union.qbk]}\r
+*/\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Collection\r
+>\r
+inline void union_(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Collection& output_collection)\r
+{\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+\r
+ typedef typename boost::range_value<Collection>::type geometry_out;\r
+ concepts::check<geometry_out>();\r
+\r
+ detail::union_::union_insert<geometry_out>(geometry1, geometry2,\r
+ range::back_inserter(output_collection));\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_UNION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace unique\r
+{\r
+\r
+\r
+struct range_unique\r
+{\r
+ template <typename Range, typename ComparePolicy>\r
+ static inline void apply(Range& range, ComparePolicy const& policy)\r
+ {\r
+ typename boost::range_iterator<Range>::type it\r
+ = std::unique\r
+ (\r
+ boost::begin(range),\r
+ boost::end(range),\r
+ policy\r
+ );\r
+\r
+ traits::resize<Range>::apply(range, it - boost::begin(range));\r
+ }\r
+};\r
+\r
+\r
+struct polygon_unique\r
+{\r
+ template <typename Polygon, typename ComparePolicy>\r
+ static inline void apply(Polygon& polygon, ComparePolicy const& policy)\r
+ {\r
+ range_unique::apply(exterior_ring(polygon), policy);\r
+\r
+ typename interior_return_type<Polygon>::type\r
+ rings = interior_rings(polygon);\r
+\r
+ for (typename detail::interior_iterator<Polygon>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ range_unique::apply(*it, policy);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename Policy>\r
+struct multi_unique\r
+{\r
+ template <typename MultiGeometry, typename ComparePolicy>\r
+ static inline void apply(MultiGeometry& multi, ComparePolicy const& compare)\r
+ {\r
+ for (typename boost::range_iterator<MultiGeometry>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ Policy::apply(*it, compare);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::unique\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct unique\r
+{\r
+ template <typename ComparePolicy>\r
+ static inline void apply(Geometry&, ComparePolicy const& )\r
+ {}\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct unique<Ring, ring_tag>\r
+ : detail::unique::range_unique\r
+{};\r
+\r
+\r
+template <typename LineString>\r
+struct unique<LineString, linestring_tag>\r
+ : detail::unique::range_unique\r
+{};\r
+\r
+\r
+template <typename Polygon>\r
+struct unique<Polygon, polygon_tag>\r
+ : detail::unique::polygon_unique\r
+{};\r
+\r
+\r
+// For points, unique is not applicable and does nothing\r
+// (Note that it is not "spatially unique" but that it removes duplicate coordinates,\r
+// like std::unique does). Spatially unique is "dissolve" which can (or will be)\r
+// possible for multi-points as well, removing points at the same location.\r
+\r
+\r
+template <typename MultiLineString>\r
+struct unique<MultiLineString, multi_linestring_tag>\r
+ : detail::unique::multi_unique<detail::unique::range_unique>\r
+{};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct unique<MultiPolygon, multi_polygon_tag>\r
+ : detail::unique::multi_unique<detail::unique::polygon_unique>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+\brief \brief_calc{minimal set}\r
+\ingroup unique\r
+\details \details_calc{unique,minimal set (where duplicate consecutive points are removed)}.\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry which will be made unique\r
+\r
+\qbk{[include reference/algorithms/unique.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline void unique(Geometry& geometry)\r
+{\r
+ concepts::check<Geometry>();\r
+\r
+ // Default strategy is the default point-comparison policy\r
+ typedef geometry::equal_to\r
+ <\r
+ typename geometry::point_type<Geometry>::type\r
+ > policy;\r
+\r
+\r
+ dispatch::unique<Geometry>::apply(geometry, policy());\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_VALIDITY_FAILURE_TYPE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_VALIDITY_FAILURE_TYPE_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+\brief Enumerates the possible validity failure types for a geometry\r
+\ingroup enum\r
+\details The enumeration validity_failure_type enumerates the possible\r
+ reasons for which a geometry may be found as invalid by the\r
+ is_valid algorithm.\r
+ Besides the values that indicate invalidity, there is an\r
+ additional value (no_failure) that indicates validity.\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.is_valid The is_valid\r
+algorithm taking a reference to validity_failure_type as second argument]\r
+}\r
+*/\r
+enum validity_failure_type\r
+{\r
+ /// The geometry is valid\r
+ ///\r
+ no_failure = 0,\r
+ /// The geometry has a very small number of points, e.g., less\r
+ /// than 2 for linestrings, less than 3 for open rings, a closed\r
+ /// multi-polygon that contains a polygon with less than 4 points, etc.\r
+ /// (applies to linestrings, rings, polygons, multi-linestrings\r
+ /// and multi-polygons)\r
+ failure_few_points = 10,\r
+ /// The topological dimension of the geometry is smaller than its\r
+ /// dimension, e.g., a linestring with 3 identical points, an open\r
+ /// polygon with an interior ring consisting of 3 collinear points, etc.\r
+ /// (applies to linear and areal geometries, including segments\r
+ /// and boxes)\r
+ failure_wrong_topological_dimension = 11,\r
+ /// The geometry contains spikes\r
+ /// (applies to linear and areal geometries)\r
+ failure_spikes = 12,\r
+ /// The geometry has (consecutive) duplicate points\r
+ /// (applies to areal geometries only)\r
+ failure_duplicate_points = 13,\r
+ /// The geometry is defined as closed, the starting/ending points\r
+ /// are not equal\r
+ /// (applies to areal geometries only)\r
+ failure_not_closed = 20, // for areal geometries\r
+ /// The geometry has invalid self-intersections.\r
+ /// (applies to areal geometries only)\r
+ failure_self_intersections = 21, // for areal geometries\r
+ /// The actual orientation of the geometry is different from the one defined\r
+ /// (applies to areal geometries only)\r
+ failure_wrong_orientation = 22, // for areal geometries\r
+ /// The geometry contains interior rings that lie outside the exterior ring\r
+ /// (applies to polygons and multi-polygons only)\r
+ failure_interior_rings_outside = 30, // for (multi-)polygons\r
+ /// The geometry has nested interior rings\r
+ /// (applies to polygons and multi-polygons only)\r
+ failure_nested_interior_rings = 31, // for (multi-)polygons\r
+ /// The interior of the geometry is disconnected\r
+ /// (applies to polygons and multi-polygons only)\r
+ failure_disconnected_interior = 32, // for (multi-)polygons\r
+ /// The multi-polygon contains polygons whose interiors are not disjoint\r
+ /// (applies to multi-polygons only)\r
+ failure_intersecting_interiors = 40, // for multi-polygons\r
+ /// The top-right corner of the box is lexicographically smaller\r
+ /// than its bottom-left corner\r
+ /// (applies to boxes only)\r
+ failure_wrong_corner_order = 50, // for boxes\r
+ /// The geometry has at least one point with an invalid coordinate\r
+ /// (for example, the coordinate is a NaN)\r
+ failure_invalid_coordinate = 60\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_VALIDITY_FAILURE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/make.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/strategies/concepts/within_concept.hpp>\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/order_as_direction.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>\r
+#include <deque>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace within {\r
+\r
+struct use_point_in_geometry\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)\r
+ {\r
+ return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;\r
+ }\r
+};\r
+\r
+struct use_relate\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)\r
+ {\r
+ return Strategy::apply(geometry1, geometry2);\r
+ }\r
+};\r
+\r
+}} // namespace detail::within\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename tag<Geometry1>::type,\r
+ typename Tag2 = typename tag<Geometry2>::type\r
+>\r
+struct within\r
+ : not_implemented<Tag1, Tag2>\r
+{};\r
+\r
+\r
+template <typename Point, typename Box>\r
+struct within<Point, Box, point_tag, box_tag>\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)\r
+ {\r
+ boost::ignore_unused_variable_warning(strategy);\r
+ return strategy.apply(point, box);\r
+ }\r
+};\r
+\r
+template <typename Box1, typename Box2>\r
+struct within<Box1, Box2, box_tag, box_tag>\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)\r
+ {\r
+ assert_dimension_equal<Box1, Box2>();\r
+ boost::ignore_unused_variable_warning(strategy);\r
+ return strategy.apply(box1, box2);\r
+ }\r
+};\r
+\r
+// P/P\r
+\r
+template <typename Point1, typename Point2>\r
+struct within<Point1, Point2, point_tag, point_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct within<Point, MultiPoint, point_tag, multi_point_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+// P/L\r
+\r
+template <typename Point, typename Segment>\r
+struct within<Point, Segment, point_tag, segment_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename Linestring>\r
+struct within<Point, Linestring, point_tag, linestring_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename MultiLinestring>\r
+struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+// P/A\r
+\r
+template <typename Point, typename Ring>\r
+struct within<Point, Ring, point_tag, ring_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename Polygon>\r
+struct within<Point, Polygon, point_tag, polygon_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+template <typename Point, typename MultiPolygon>\r
+struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>\r
+ : public detail::within::use_point_in_geometry\r
+{};\r
+\r
+// L/L\r
+\r
+template <typename Linestring1, typename Linestring2>\r
+struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Linestring, typename MultiLinestring>\r
+struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename Linestring>\r
+struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring1, typename MultiLinestring2>\r
+struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+// L/A\r
+\r
+template <typename Linestring, typename Ring>\r
+struct within<Linestring, Ring, linestring_tag, ring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename Ring>\r
+struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Linestring, typename Polygon>\r
+struct within<Linestring, Polygon, linestring_tag, polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename Polygon>\r
+struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Linestring, typename MultiPolygon>\r
+struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiLinestring, typename MultiPolygon>\r
+struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+// A/A\r
+\r
+template <typename Ring1, typename Ring2>\r
+struct within<Ring1, Ring2, ring_tag, ring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Ring, typename Polygon>\r
+struct within<Ring, Polygon, ring_tag, polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Polygon, typename Ring>\r
+struct within<Polygon, Ring, polygon_tag, ring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Polygon1, typename Polygon2>\r
+struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Ring, typename MultiPolygon>\r
+struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiPolygon, typename Ring>\r
+struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename Polygon, typename MultiPolygon>\r
+struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiPolygon, typename Polygon>\r
+struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+template <typename MultiPolygon1, typename MultiPolygon2>\r
+struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>\r
+ : public detail::within::use_relate\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+struct within\r
+{\r
+ template <typename Geometry1, typename Geometry2, typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ concepts::within::check\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,\r
+ Strategy\r
+ >();\r
+\r
+ return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ default_strategy)\r
+ {\r
+ typedef typename point_type<Geometry1>::type point_type1;\r
+ typedef typename point_type<Geometry2>::type point_type2;\r
+\r
+ typedef typename strategy::within::services::default_strategy\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ typename tag<Geometry2>::type,\r
+ typename tag<Geometry1>::type,\r
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type1>::type, spherical_tag\r
+ >::type,\r
+ typename tag_cast\r
+ <\r
+ typename cs_tag<point_type2>::type, spherical_tag\r
+ >::type,\r
+ Geometry1,\r
+ Geometry2\r
+ >::type strategy_type;\r
+\r
+ return apply(geometry1, geometry2, strategy_type());\r
+ }\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct within\r
+{\r
+ template <typename Strategy>\r
+ static inline bool apply(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ concepts::check<Geometry1 const>();\r
+ concepts::check<Geometry2 const>();\r
+ assert_dimension_equal<Geometry1, Geometry2>();\r
+\r
+ return resolve_strategy::within::apply(geometry1,\r
+ geometry2,\r
+ strategy);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>\r
+struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry2 const& m_geometry2;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry2 const& geometry2, Strategy const& strategy)\r
+ : m_geometry2(geometry2)\r
+ , m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry1>\r
+ bool operator()(Geometry1 const& geometry1) const\r
+ {\r
+ return within<Geometry1, Geometry2>::apply(geometry1,\r
+ m_geometry2,\r
+ m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),\r
+ geometry1);\r
+ }\r
+};\r
+\r
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Geometry1 const& m_geometry1;\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Geometry1 const& geometry1, Strategy const& strategy)\r
+ : m_geometry1(geometry1)\r
+ , m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry2>\r
+ bool operator()(Geometry2 const& geometry2) const\r
+ {\r
+ return within<Geometry1, Geometry2>::apply(m_geometry1,\r
+ geometry2,\r
+ m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool\r
+ apply(Geometry1 const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),\r
+ geometry2\r
+ );\r
+ }\r
+};\r
+\r
+template <\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)\r
+>\r
+struct within<\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>\r
+>\r
+{\r
+ template <typename Strategy>\r
+ struct visitor: boost::static_visitor<bool>\r
+ {\r
+ Strategy const& m_strategy;\r
+\r
+ visitor(Strategy const& strategy): m_strategy(strategy) {}\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ bool operator()(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2) const\r
+ {\r
+ return within<Geometry1, Geometry2>::apply(geometry1,\r
+ geometry2,\r
+ m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename Strategy>\r
+ static inline bool\r
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,\r
+ Strategy const& strategy)\r
+ {\r
+ return boost::apply_visitor(visitor<Strategy>(strategy),\r
+ geometry1,\r
+ geometry2);\r
+ }\r
+};\r
+\r
+}\r
+\r
+\r
+/*!\r
+\brief \brief_check12{is completely inside}\r
+\ingroup within\r
+\details \details_check12{within, is completely inside}.\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry which might be within the second geometry\r
+\param geometry2 \param_geometry which might contain the first geometry\r
+\return true if geometry1 is completely contained within geometry2,\r
+ else false\r
+\note The default strategy is used for within detection\r
+\r
+\r
+\qbk{[include reference/algorithms/within.qbk]}\r
+\r
+\qbk{\r
+[heading Example]\r
+[within]\r
+[within_output]\r
+}\r
+ */\r
+template<typename Geometry1, typename Geometry2>\r
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ return resolve_variant::within\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, default_strategy());\r
+}\r
+\r
+/*!\r
+\brief \brief_check12{is completely inside} \brief_strategy\r
+\ingroup within\r
+\details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons\r
+\tparam Geometry1 \tparam_geometry\r
+\tparam Geometry2 \tparam_geometry\r
+\param geometry1 \param_geometry which might be within the second geometry\r
+\param geometry2 \param_geometry which might contain the first geometry\r
+\param strategy strategy to be used\r
+\return true if geometry1 is completely contained within geometry2,\r
+ else false\r
+\r
+\qbk{distinguish,with strategy}\r
+\qbk{[include reference/algorithms/within.qbk]}\r
+\qbk{\r
+[heading Available Strategies]\r
+\* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]\r
+\* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]\r
+\* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]\r
+\r
+[heading Example]\r
+[within_strategy]\r
+[within_strategy_output]\r
+\r
+}\r
+*/\r
+template<typename Geometry1, typename Geometry2, typename Strategy>\r
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,\r
+ Strategy const& strategy)\r
+{\r
+ return resolve_variant::within\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::apply(geometry1, geometry2, strategy);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP\r
+#define BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP\r
+\r
+#include <functional>\r
+\r
+#include <boost/call_traits.hpp>\r
+#include <boost/concept/requires.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/util/for_each_coordinate.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename Point>\r
+struct param\r
+{\r
+ typedef typename boost::call_traits\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >::param_type type;\r
+};\r
+\r
+\r
+template <typename Value, template <typename> class Function>\r
+struct value_operation\r
+{\r
+ Value m_value;\r
+\r
+ inline value_operation(Value const &value)\r
+ : m_value(value)\r
+ {}\r
+\r
+ template <typename PointDst, std::size_t Index>\r
+ inline void apply(PointDst& point_dst) const\r
+ {\r
+ set<Index>(point_dst,\r
+ Function\r
+ <\r
+ typename geometry::select_most_precise\r
+ <\r
+ Value,\r
+ typename geometry::coordinate_type<PointDst>::type\r
+ >::type\r
+ >()(get<Index>(point_dst), m_value));\r
+ }\r
+};\r
+\r
+template <typename PointSrc, template <typename> class Function>\r
+struct point_operation\r
+{\r
+ PointSrc const& m_point_src;\r
+\r
+ inline point_operation(PointSrc const& point)\r
+ : m_point_src(point)\r
+ {}\r
+\r
+ template <typename PointDst, std::size_t Index>\r
+ inline void apply(PointDst& point_dst) const\r
+ {\r
+ set<Index>(point_dst,\r
+ Function\r
+ <\r
+ typename geometry::select_most_precise\r
+ <\r
+ typename geometry::coordinate_type<PointSrc>::type,\r
+ typename geometry::coordinate_type<PointDst>::type\r
+ >::type\r
+ >()(get<Index>(point_dst), get<Index>(m_point_src)));\r
+ }\r
+};\r
+\r
+\r
+template <typename Value>\r
+struct value_assignment\r
+{\r
+ Value m_value;\r
+\r
+ inline value_assignment(Value const &value)\r
+ : m_value(value)\r
+ {}\r
+\r
+ template <typename PointDst, std::size_t Index>\r
+ inline void apply(PointDst& point_dst) const\r
+ {\r
+ set<Index>(point_dst, m_value);\r
+ }\r
+};\r
+\r
+template <typename PointSrc>\r
+struct point_assignment\r
+{\r
+ PointSrc const& m_point_src;\r
+\r
+ inline point_assignment(PointSrc const& point)\r
+ : m_point_src(point)\r
+ {}\r
+\r
+ template <typename PointDst, std::size_t Index>\r
+ inline void apply(PointDst& point_dst) const\r
+ {\r
+ set<Index>(point_dst, get<Index>(m_point_src));\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+/*!\r
+ \brief Adds the same value to each coordinate of a point\r
+ \ingroup arithmetic\r
+ \details\r
+ \tparam Point \tparam_point\r
+ \param p point\r
+ \param value value to add\r
+ */\r
+template <typename Point>\r
+inline void add_value(Point& p, typename detail::param<Point>::type value)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ for_each_coordinate(p,\r
+ detail::value_operation\r
+ <\r
+ typename coordinate_type<Point>::type,\r
+ std::plus\r
+ >(value));\r
+}\r
+\r
+/*!\r
+ \brief Adds a point to another\r
+ \ingroup arithmetic\r
+ \details The coordinates of the second point will be added to those of the first point.\r
+ The second point is not modified.\r
+ \tparam Point1 \tparam_point\r
+ \tparam Point2 \tparam_point\r
+ \param p1 first point\r
+ \param p2 second point\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline void add_point(Point1& p1, Point2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2));\r
+}\r
+\r
+/*!\r
+ \brief Subtracts the same value to each coordinate of a point\r
+ \ingroup arithmetic\r
+ \details\r
+ \tparam Point \tparam_point\r
+ \param p point\r
+ \param value value to subtract\r
+ */\r
+template <typename Point>\r
+inline void subtract_value(Point& p, typename detail::param<Point>::type value)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ for_each_coordinate(p,\r
+ detail::value_operation\r
+ <\r
+ typename coordinate_type<Point>::type,\r
+ std::minus\r
+ >(value));\r
+}\r
+\r
+/*!\r
+ \brief Subtracts a point to another\r
+ \ingroup arithmetic\r
+ \details The coordinates of the second point will be subtracted to those of the first point.\r
+ The second point is not modified.\r
+ \tparam Point1 \tparam_point\r
+ \tparam Point2 \tparam_point\r
+ \param p1 first point\r
+ \param p2 second point\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline void subtract_point(Point1& p1, Point2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2));\r
+}\r
+\r
+/*!\r
+ \brief Multiplies each coordinate of a point by the same value\r
+ \ingroup arithmetic\r
+ \details\r
+ \tparam Point \tparam_point\r
+ \param p point\r
+ \param value value to multiply by\r
+ */\r
+template <typename Point>\r
+inline void multiply_value(Point& p, typename detail::param<Point>::type value)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ for_each_coordinate(p,\r
+ detail::value_operation\r
+ <\r
+ typename coordinate_type<Point>::type,\r
+ std::multiplies\r
+ >(value));\r
+}\r
+\r
+/*!\r
+ \brief Multiplies a point by another\r
+ \ingroup arithmetic\r
+ \details The coordinates of the first point will be multiplied by those of the second point.\r
+ The second point is not modified.\r
+ \tparam Point1 \tparam_point\r
+ \tparam Point2 \tparam_point\r
+ \param p1 first point\r
+ \param p2 second point\r
+ \note This is *not* a dot, cross or wedge product. It is a mere field-by-field multiplication.\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline void multiply_point(Point1& p1, Point2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2));\r
+}\r
+\r
+/*!\r
+ \brief Divides each coordinate of the same point by a value\r
+ \ingroup arithmetic\r
+ \details\r
+ \tparam Point \tparam_point\r
+ \param p point\r
+ \param value value to divide by\r
+ */\r
+template <typename Point>\r
+inline void divide_value(Point& p, typename detail::param<Point>::type value)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ for_each_coordinate(p,\r
+ detail::value_operation\r
+ <\r
+ typename coordinate_type<Point>::type,\r
+ std::divides\r
+ >(value));\r
+}\r
+\r
+/*!\r
+ \brief Divides a point by another\r
+ \ingroup arithmetic\r
+ \details The coordinates of the first point will be divided by those of the second point.\r
+ The second point is not modified.\r
+ \tparam Point1 \tparam_point\r
+ \tparam Point2 \tparam_point\r
+ \param p1 first point\r
+ \param p2 second point\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline void divide_point(Point1& p1, Point2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2));\r
+}\r
+\r
+/*!\r
+ \brief Assign each coordinate of a point the same value\r
+ \ingroup arithmetic\r
+ \details\r
+ \tparam Point \tparam_point\r
+ \param p point\r
+ \param value value to assign\r
+ */\r
+template <typename Point>\r
+inline void assign_value(Point& p, typename detail::param<Point>::type value)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ for_each_coordinate(p,\r
+ detail::value_assignment\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >(value));\r
+}\r
+\r
+/*!\r
+ \brief Assign a point with another\r
+ \ingroup arithmetic\r
+ \details The coordinates of the first point will be assigned those of the second point.\r
+ The second point is not modified.\r
+ \tparam Point1 \tparam_point\r
+ \tparam Point2 \tparam_point\r
+ \param p1 first point\r
+ \param p2 second point\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline void assign_point(Point1& p1, Point2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ for_each_coordinate(p1, detail::point_assignment<Point2>(p2));\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP\r
+#define BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/size_t.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <std::size_t Dimension>\r
+struct cross_product\r
+{\r
+ // We define cross product only for 2d (see Wolfram) and 3d.\r
+ // In Math, it is also well-defined for 7-dimension.\r
+ // Generalisation of cross product to n-dimension is defined as\r
+ // wedge product but it is not direct analogue to binary cross product.\r
+ BOOST_MPL_ASSERT_MSG((false),\r
+ NOT_IMPLEMENTED_FOR_THIS_DIMENSION,\r
+ (mpl::size_t<Dimension>));\r
+};\r
+\r
+template <>\r
+struct cross_product<2>\r
+{\r
+ template <typename P1, typename P2, typename ResultP>\r
+ static inline void apply(P1 const& p1, P2 const& p2, ResultP& result)\r
+ {\r
+ assert_dimension<P1, 2>();\r
+ assert_dimension<P2, 2>();\r
+ assert_dimension<ResultP, 2>();\r
+\r
+ // For 2-dimensions, analog of the cross product U(x,y) and V(x,y) is\r
+ // Ux * Vy - Uy * Vx\r
+ // which is returned as 0-component (or X) of 2d vector, 1-component is undefined.\r
+ set<0>(result, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2));\r
+ }\r
+};\r
+\r
+template <>\r
+struct cross_product<3>\r
+{\r
+ template <typename P1, typename P2, typename ResultP>\r
+ static inline void apply(P1 const& p1, P2 const& p2, ResultP& result)\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ assert_dimension<P2, 3>();\r
+ assert_dimension<ResultP, 3>();\r
+\r
+ set<0>(result, get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2));\r
+ set<1>(result, get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2));\r
+ set<2>(result, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2));\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Computes the cross product of two vectors.\r
+\details All vectors should have the same dimension, 3 or 2.\r
+\ingroup arithmetic\r
+\param p1 first vector\r
+\param p2 second vector\r
+\return the cross product vector\r
+ */\r
+template <typename ResultP, typename P1, typename P2>\r
+inline ResultP cross_product(P1 const& p1, P2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<ResultP>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<P1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<P2>) );\r
+\r
+ ResultP result;\r
+ detail::cross_product<dimension<ResultP>::value>::apply(p1, p2, result);\r
+ return result;\r
+}\r
+\r
+/*!\r
+\brief Computes the cross product of two vectors.\r
+\details All vectors should have the same dimension, 3 or 2.\r
+\ingroup arithmetic\r
+\param p1 first vector\r
+\param p2 second vector\r
+\return the cross product vector\r
+*/\r
+template <typename P>\r
+inline P cross_product(P const& p1, P const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT((concepts::Point<P>));\r
+ BOOST_CONCEPT_ASSERT((concepts::ConstPoint<P>));\r
+\r
+ P result;\r
+ detail::cross_product<dimension<P>::value>::apply(p1, p2, result);\r
+ return result;\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP\r
+#define BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename ReturnType, typename U, typename V>\r
+class calculate_determinant\r
+{\r
+ template <typename T>\r
+ static inline ReturnType rt(T const& v)\r
+ {\r
+ return boost::numeric_cast<ReturnType>(v);\r
+ }\r
+\r
+public :\r
+\r
+ static inline ReturnType apply(U const& ux, U const& uy\r
+ , V const& vx, V const& vy)\r
+ {\r
+ return rt(ux) * rt(vy) - rt(uy) * rt(vx);\r
+ }\r
+};\r
+\r
+template <typename ReturnType, typename U, typename V>\r
+inline ReturnType determinant(U const& ux, U const& uy\r
+ , V const& vx, V const& vy)\r
+{\r
+ return calculate_determinant\r
+ <\r
+ ReturnType, U, V\r
+ >::apply(ux, uy, vx, vy);\r
+}\r
+\r
+\r
+template <typename ReturnType, typename U, typename V>\r
+inline ReturnType determinant(U const& u, V const& v)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<U>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<V>) );\r
+\r
+ return calculate_determinant\r
+ <\r
+ ReturnType,\r
+ typename geometry::coordinate_type<U>::type,\r
+ typename geometry::coordinate_type<V>::type\r
+ >::apply(get<0>(u), get<1>(u), get<0>(v), get<1>(v));\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP\r
+#define BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/requires.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename P1, typename P2, std::size_t Dimension, std::size_t DimensionCount>\r
+struct dot_product_maker\r
+{\r
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;\r
+\r
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)\r
+ {\r
+ return get<Dimension>(p1) * get<Dimension>(p2)\r
+ + dot_product_maker<P1, P2, Dimension+1, DimensionCount>::apply(p1, p2);\r
+ }\r
+};\r
+\r
+template <typename P1, typename P2, std::size_t DimensionCount>\r
+struct dot_product_maker<P1, P2, DimensionCount, DimensionCount>\r
+{\r
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;\r
+\r
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)\r
+ {\r
+ return get<DimensionCount>(p1) * get<DimensionCount>(p2);\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+ \brief Computes the dot product (or scalar product) of 2 vectors (points).\r
+ \ingroup arithmetic\r
+ \tparam Point1 \tparam_point\r
+ \tparam Point2 \tparam_point\r
+ \param p1 first point\r
+ \param p2 second point\r
+ \return the dot product\r
+ */\r
+template <typename Point1, typename Point2>\r
+inline typename select_coordinate_type<Point1, Point2>::type dot_product(\r
+ Point1 const& p1, Point2 const& p2)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ return detail::dot_product_maker\r
+ <\r
+ Point1, Point2,\r
+ 0, dimension<Point1>::type::value - 1\r
+ >::apply(p1, p2);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_ACCESS_HPP\r
+#define BOOST_GEOMETRY_CORE_ACCESS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_pointer.hpp>\r
+#include <boost/type_traits/remove_pointer.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/// Index of minimum corner of the box.\r
+int const min_corner = 0;\r
+\r
+/// Index of maximum corner of the box.\r
+int const max_corner = 1;\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class which gives access (get,set) to points.\r
+\ingroup traits\r
+\par Geometries:\r
+/// @li point\r
+\par Specializations should provide, per Dimension\r
+/// @li static inline T get(G const&)\r
+/// @li static inline void set(G&, T const&)\r
+\tparam Geometry geometry-type\r
+\tparam Dimension dimension to access\r
+*/\r
+template <typename Geometry, std::size_t Dimension, typename Enable = void>\r
+struct access\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+/*!\r
+\brief Traits class defining "get" and "set" to get\r
+ and set point coordinate values\r
+\tparam Geometry geometry (box, segment)\r
+\tparam Index index (min_corner/max_corner for box, 0/1 for segment)\r
+\tparam Dimension dimension\r
+\par Geometries:\r
+ - box\r
+ - segment\r
+\par Specializations should provide:\r
+ - static inline T get(G const&)\r
+ - static inline void set(G&, T const&)\r
+\ingroup traits\r
+*/\r
+template <typename Geometry, std::size_t Index, std::size_t Dimension>\r
+struct indexed_access {};\r
+\r
+\r
+} // namespace traits\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension\r
+>\r
+struct indexed_access_non_pointer\r
+{\r
+ static inline CoordinateType get(Geometry const& geometry)\r
+ {\r
+ return traits::indexed_access<Geometry, Index, Dimension>::get(geometry);\r
+ }\r
+ static inline void set(Geometry& b, CoordinateType const& value)\r
+ {\r
+ traits::indexed_access<Geometry, Index, Dimension>::set(b, value);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension\r
+>\r
+struct indexed_access_pointer\r
+{\r
+ static inline CoordinateType get(Geometry const* geometry)\r
+ {\r
+ return traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::get(*geometry);\r
+ }\r
+ static inline void set(Geometry* geometry, CoordinateType const& value)\r
+ {\r
+ traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::set(*geometry, value);\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Geometry,\r
+ typename\r
+ CoordinateType,\r
+ std::size_t Dimension,\r
+ typename IsPointer\r
+>\r
+struct access\r
+{\r
+ //static inline T get(G const&) {}\r
+ //static inline void set(G& g, T const& value) {}\r
+};\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Geometry,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension,\r
+ typename IsPointer\r
+>\r
+struct indexed_access\r
+{\r
+ //static inline T get(G const&) {}\r
+ //static inline void set(G& g, T const& value) {}\r
+};\r
+\r
+template <typename Point, typename CoordinateType, std::size_t Dimension>\r
+struct access<point_tag, Point, CoordinateType, Dimension, boost::false_type>\r
+{\r
+ static inline CoordinateType get(Point const& point)\r
+ {\r
+ return traits::access<Point, Dimension>::get(point);\r
+ }\r
+ static inline void set(Point& p, CoordinateType const& value)\r
+ {\r
+ traits::access<Point, Dimension>::set(p, value);\r
+ }\r
+};\r
+\r
+template <typename Point, typename CoordinateType, std::size_t Dimension>\r
+struct access<point_tag, Point, CoordinateType, Dimension, boost::true_type>\r
+{\r
+ static inline CoordinateType get(Point const* point)\r
+ {\r
+ return traits::access<typename boost::remove_pointer<Point>::type, Dimension>::get(*point);\r
+ }\r
+ static inline void set(Point* p, CoordinateType const& value)\r
+ {\r
+ traits::access<typename boost::remove_pointer<Point>::type, Dimension>::set(*p, value);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Box,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension\r
+>\r
+struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::false_type>\r
+ : detail::indexed_access_non_pointer<Box, CoordinateType, Index, Dimension>\r
+{};\r
+\r
+template\r
+<\r
+ typename Box,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension\r
+>\r
+struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::true_type>\r
+ : detail::indexed_access_pointer<Box, CoordinateType, Index, Dimension>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension\r
+>\r
+struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::false_type>\r
+ : detail::indexed_access_non_pointer<Segment, CoordinateType, Index, Dimension>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Segment,\r
+ typename CoordinateType,\r
+ std::size_t Index,\r
+ std::size_t Dimension\r
+>\r
+struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::true_type>\r
+ : detail::indexed_access_pointer<Segment, CoordinateType, Index, Dimension>\r
+{};\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+// Two dummy tags to distinguish get/set variants below.\r
+// They don't have to be specified by the user. The functions are distinguished\r
+// by template signature also, but for e.g. GCC this is not enough. So give them\r
+// a different signature.\r
+struct signature_getset_dimension {};\r
+struct signature_getset_index_dimension {};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Get coordinate value of a geometry (usually a point)\r
+\details \details_get_set\r
+\ingroup get\r
+\tparam Dimension \tparam_dimension_required\r
+\tparam Geometry \tparam_geometry (usually a Point Concept)\r
+\param geometry \param_geometry (usually a point)\r
+\return The coordinate value of specified dimension of specified geometry\r
+\r
+\qbk{[include reference/core/get_point.qbk]}\r
+*/\r
+template <std::size_t Dimension, typename Geometry>\r
+inline typename coordinate_type<Geometry>::type get(Geometry const& geometry\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ , detail::signature_getset_dimension* dummy = 0\r
+#endif\r
+ )\r
+{\r
+ boost::ignore_unused(dummy);\r
+\r
+ typedef core_dispatch::access\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type,\r
+ typename coordinate_type<Geometry>::type,\r
+ Dimension,\r
+ typename boost::is_pointer<Geometry>::type\r
+ > coord_access_type;\r
+\r
+ return coord_access_type::get(geometry);\r
+}\r
+\r
+\r
+/*!\r
+\brief Set coordinate value of a geometry (usually a point)\r
+\details \details_get_set\r
+\tparam Dimension \tparam_dimension_required\r
+\tparam Geometry \tparam_geometry (usually a Point Concept)\r
+\param geometry geometry to assign coordinate to\r
+\param geometry \param_geometry (usually a point)\r
+\param value The coordinate value to set\r
+\ingroup set\r
+\r
+\qbk{[include reference/core/set_point.qbk]}\r
+*/\r
+template <std::size_t Dimension, typename Geometry>\r
+inline void set(Geometry& geometry\r
+ , typename coordinate_type<Geometry>::type const& value\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ , detail::signature_getset_dimension* dummy = 0\r
+#endif\r
+ )\r
+{\r
+ boost::ignore_unused(dummy);\r
+\r
+ typedef core_dispatch::access\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type,\r
+ typename coordinate_type<Geometry>::type,\r
+ Dimension,\r
+ typename boost::is_pointer<Geometry>::type\r
+ > coord_access_type;\r
+\r
+ coord_access_type::set(geometry, value);\r
+}\r
+\r
+\r
+/*!\r
+\brief get coordinate value of a Box or Segment\r
+\details \details_get_set\r
+\tparam Index \tparam_index_required\r
+\tparam Dimension \tparam_dimension_required\r
+\tparam Geometry \tparam_box_or_segment\r
+\param geometry \param_geometry\r
+\return coordinate value\r
+\ingroup get\r
+\r
+\qbk{distinguish,with index}\r
+\qbk{[include reference/core/get_box.qbk]}\r
+*/\r
+template <std::size_t Index, std::size_t Dimension, typename Geometry>\r
+inline typename coordinate_type<Geometry>::type get(Geometry const& geometry\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ , detail::signature_getset_index_dimension* dummy = 0\r
+#endif\r
+ )\r
+{\r
+ boost::ignore_unused(dummy);\r
+\r
+ typedef core_dispatch::indexed_access\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type,\r
+ typename coordinate_type<Geometry>::type,\r
+ Index,\r
+ Dimension,\r
+ typename boost::is_pointer<Geometry>::type\r
+ > coord_access_type;\r
+\r
+ return coord_access_type::get(geometry);\r
+}\r
+\r
+/*!\r
+\brief set coordinate value of a Box / Segment\r
+\details \details_get_set\r
+\tparam Index \tparam_index_required\r
+\tparam Dimension \tparam_dimension_required\r
+\tparam Geometry \tparam_box_or_segment\r
+\param geometry geometry to assign coordinate to\r
+\param geometry \param_geometry\r
+\param value The coordinate value to set\r
+\ingroup set\r
+\r
+\qbk{distinguish,with index}\r
+\qbk{[include reference/core/set_box.qbk]}\r
+*/\r
+template <std::size_t Index, std::size_t Dimension, typename Geometry>\r
+inline void set(Geometry& geometry\r
+ , typename coordinate_type<Geometry>::type const& value\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ , detail::signature_getset_index_dimension* dummy = 0\r
+#endif\r
+ )\r
+{\r
+ boost::ignore_unused(dummy);\r
+\r
+ typedef core_dispatch::indexed_access\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type,\r
+ typename coordinate_type<Geometry>::type,\r
+ Index,\r
+ Dimension,\r
+ typename boost::is_pointer<Geometry>::type\r
+ > coord_access_type;\r
+\r
+ coord_access_type::set(geometry, value);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_ACCESS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.\r
+// Copyright (c) 2007, 2014 Peter Dimov\r
+// Copyright (c) Beman Dawes 2011\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_ASSERT_HPP\r
+#define BOOST_GEOMETRY_CORE_ASSERT_HPP\r
+\r
+#include <boost/assert.hpp>\r
+\r
+#undef BOOST_GEOMETRY_ASSERT\r
+#undef BOOST_GEOMETRY_ASSERT_MSG\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_GEOMETRY_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )\r
+\r
+#include <boost/config.hpp> // for BOOST_LIKELY\r
+#include <boost/current_function.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined\r
+ void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line); // user defined\r
+}} // namespace boost::geometry\r
+\r
+#define BOOST_GEOMETRY_ASSERT(expr) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::geometry::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))\r
+#define BOOST_GEOMETRY_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::geometry::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))\r
+\r
+#else\r
+\r
+#define BOOST_GEOMETRY_ASSERT(expr) BOOST_ASSERT(expr)\r
+#define BOOST_GEOMETRY_ASSERT_MSG(expr, msg) BOOST_ASSERT_MSG(expr, msg)\r
+\r
+#endif\r
+\r
+#endif // BOOST_GEOMETRY_CORE_EXCEPTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_CLOSURE_HPP\r
+#define BOOST_GEOMETRY_CORE_CLOSURE_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/size_t.hpp>\r
+#include <boost/range/value_type.hpp>\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+\brief Enumerates options for defining if polygons are open or closed\r
+\ingroup enum\r
+\details The enumeration closure_selector describes options for if a polygon is\r
+ open or closed. In a closed polygon the very first point (per ring) should\r
+ be equal to the very last point.\r
+ The specific closing property of a polygon type is defined by the closure\r
+ metafunction. The closure metafunction defines a value, which is one of the\r
+ values enumerated in the closure_selector\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.core.closure The closure metafunction]\r
+}\r
+*/\r
+enum closure_selector\r
+{\r
+ /// Rings are open: first point and last point are different, algorithms\r
+ /// close them explicitly on the fly\r
+ open = 0,\r
+ /// Rings are closed: first point and last point must be the same\r
+ closed = 1,\r
+ /// (Not yet implemented): algorithms first figure out if ring must be\r
+ /// closed on the fly\r
+ closure_undertermined = -1\r
+};\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+ \brief Traits class indicating if points within a\r
+ ring or (multi)polygon are closed (last point == first point),\r
+ open or not known.\r
+ \ingroup traits\r
+ \par Geometries:\r
+ - ring\r
+ \tparam G geometry\r
+*/\r
+template <typename G>\r
+struct closure\r
+{\r
+ static const closure_selector value = closed;\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace core_detail { namespace closure\r
+{\r
+\r
+struct closed\r
+{\r
+ static const closure_selector value = geometry::closed;\r
+};\r
+\r
+\r
+/// Metafunction to define the minimum size of a ring:\r
+/// 3 for open rings, 4 for closed rings\r
+template <closure_selector Closure>\r
+struct minimum_ring_size {};\r
+\r
+template <>\r
+struct minimum_ring_size<geometry::closed> : boost::mpl::size_t<4> {};\r
+\r
+template <>\r
+struct minimum_ring_size<geometry::open> : boost::mpl::size_t<3> {};\r
+\r
+\r
+}} // namespace detail::point_order\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry>\r
+struct closure\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+template <typename Box>\r
+struct closure<point_tag, Box> : public core_detail::closure::closed {};\r
+\r
+template <typename Box>\r
+struct closure<box_tag, Box> : public core_detail::closure::closed {};\r
+\r
+template <typename Box>\r
+struct closure<segment_tag, Box> : public core_detail::closure::closed {};\r
+\r
+template <typename LineString>\r
+struct closure<linestring_tag, LineString>\r
+ : public core_detail::closure::closed {};\r
+\r
+\r
+template <typename Ring>\r
+struct closure<ring_tag, Ring>\r
+{\r
+ static const closure_selector value\r
+ = geometry::traits::closure<Ring>::value;\r
+};\r
+\r
+// Specialization for Polygon: the closure is the closure of its rings\r
+template <typename Polygon>\r
+struct closure<polygon_tag, Polygon>\r
+{\r
+ static const closure_selector value = core_dispatch::closure\r
+ <\r
+ ring_tag,\r
+ typename ring_type<polygon_tag, Polygon>::type\r
+ >::value ;\r
+};\r
+\r
+template <typename MultiPoint>\r
+struct closure<multi_point_tag, MultiPoint>\r
+ : public core_detail::closure::closed {};\r
+\r
+template <typename MultiLinestring>\r
+struct closure<multi_linestring_tag, MultiLinestring>\r
+ : public core_detail::closure::closed {};\r
+\r
+// Specialization for MultiPolygon: the closure is the closure of Polygon's rings\r
+template <typename MultiPolygon>\r
+struct closure<multi_polygon_tag, MultiPolygon>\r
+{\r
+ static const closure_selector value = core_dispatch::closure\r
+ <\r
+ polygon_tag,\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >::value ;\r
+};\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief \brief_meta{value, closure (clockwise\, counterclockwise),\r
+ \meta_geometry_type}\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/closure.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct closure\r
+{\r
+ static const closure_selector value = core_dispatch::closure\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename util::bare_type<Geometry>::type\r
+ >::value;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_CLOSURE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP\r
+#define BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/static_assert.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class indicating the number of dimensions of a point\r
+\par Geometries:\r
+ - point\r
+\par Specializations should provide:\r
+ - value (should be derived from boost::mpl::int_<D>\r
+\ingroup traits\r
+*/\r
+template <typename Point, typename Enable = void>\r
+struct dimension\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)\r
+ );\r
+};\r
+\r
+} // namespace traits\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+// Base class derive from its own specialization of point-tag\r
+template <typename T, typename G>\r
+struct dimension : dimension<point_tag, typename point_type<T, G>::type> {};\r
+\r
+template <typename P>\r
+struct dimension<point_tag, P>\r
+ : traits::dimension<typename geometry::util::bare_type<P>::type>\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (traits::dimension<typename geometry::util::bare_type<P>::type>::value > 0),\r
+ INVALID_DIMENSION_VALUE,\r
+ (traits::dimension<typename geometry::util::bare_type<P>::type>)\r
+ );\r
+};\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+/*!\r
+\brief \brief_meta{value, number of coordinates (the number of axes of any geometry), \meta_point_type}\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/coordinate_dimension.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct dimension\r
+ : core_dispatch::dimension\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type\r
+ >\r
+{};\r
+\r
+/*!\r
+\brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected\r
+\ingroup utility\r
+*/\r
+template <typename Geometry, int Dimensions>\r
+inline void assert_dimension()\r
+{\r
+ BOOST_STATIC_ASSERT(( static_cast<int>(dimension<Geometry>::value) == Dimensions ));\r
+}\r
+\r
+/*!\r
+\brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected\r
+\ingroup utility\r
+*/\r
+template <typename Geometry, int Dimensions>\r
+inline void assert_dimension_less_equal()\r
+{\r
+ BOOST_STATIC_ASSERT(( static_cast<int>(dimension<Geometry>::type::value) <= Dimensions ));\r
+}\r
+\r
+template <typename Geometry, int Dimensions>\r
+inline void assert_dimension_greater_equal()\r
+{\r
+ BOOST_STATIC_ASSERT(( static_cast<int>(dimension<Geometry>::type::value) >= Dimensions ));\r
+}\r
+\r
+/*!\r
+\brief assert_dimension_equal, enables compile-time checking if coordinate dimensions of two geometries are equal\r
+\ingroup utility\r
+*/\r
+template <typename G1, typename G2>\r
+inline void assert_dimension_equal()\r
+{\r
+ BOOST_STATIC_ASSERT(( static_cast<size_t>(dimension<G1>::type::value) == static_cast<size_t>(dimension<G2>::type::value) ));\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP\r
+#define BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class defining the coordinate system of a point, important for strategy selection\r
+\ingroup traits\r
+\par Geometries:\r
+ - point\r
+\par Specializations should provide:\r
+ - typedef CS type; (cs::cartesian, cs::spherical, etc)\r
+*/\r
+template <typename Point, typename Enable = void>\r
+struct coordinate_system\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)\r
+ );\r
+};\r
+\r
+} // namespace traits\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+ template <typename GeometryTag, typename G>\r
+ struct coordinate_system\r
+ {\r
+ typedef typename point_type<GeometryTag, G>::type P;\r
+\r
+ // Call its own specialization on point-tag\r
+ typedef typename coordinate_system<point_tag, P>::type type;\r
+ };\r
+\r
+\r
+ template <typename Point>\r
+ struct coordinate_system<point_tag, Point>\r
+ {\r
+ typedef typename traits::coordinate_system\r
+ <\r
+ typename geometry::util::bare_type<Point>::type\r
+ >::type type;\r
+ };\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+\brief \brief_meta{type, coordinate system (cartesian\, spherical\, etc), \meta_point_type}\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/coordinate_system.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct coordinate_system\r
+{\r
+ typedef typename core_dispatch::coordinate_system\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP\r
+#define BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class which indicate the coordinate type (double,float,...) of a point\r
+\ingroup traits\r
+\par Geometries:\r
+ - point\r
+\par Specializations should provide:\r
+ - typedef T type; (double,float,int,etc)\r
+*/\r
+template <typename Point, typename Enable = void>\r
+struct coordinate_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)\r
+ );\r
+};\r
+\r
+} // namespace traits\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct coordinate_type\r
+{\r
+ typedef typename point_type<GeometryTag, Geometry>::type point_type;\r
+\r
+ // Call its own specialization on point-tag\r
+ typedef typename coordinate_type<point_tag, point_type>::type type;\r
+};\r
+\r
+template <typename Point>\r
+struct coordinate_type<point_tag, Point>\r
+{\r
+ typedef typename traits::coordinate_type\r
+ <\r
+ typename geometry::util::bare_type<Point>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief \brief_meta{type, coordinate type (int\, float\, double\, etc), \meta_point_type}\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/coordinate_type.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct coordinate_type\r
+{\r
+ typedef typename core_dispatch::coordinate_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename geometry::util::bare_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+template <typename Geometry>\r
+struct fp_coordinate_type\r
+{\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename coordinate_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_CS_HPP\r
+#define BOOST_GEOMETRY_CORE_CS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/integral_constant.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Unit of plane angle: Degrees\r
+\details Tag defining the unit of plane angle for spherical coordinate systems.\r
+ This tag specifies that coordinates are defined in degrees (-180 .. 180).\r
+ It has to be specified for some coordinate systems.\r
+\qbk{[include reference/core/degree_radian.qbk]}\r
+*/\r
+struct degree {};\r
+\r
+\r
+/*!\r
+\brief Unit of plane angle: Radians\r
+\details Tag defining the unit of plane angle for spherical coordinate systems.\r
+ This tag specifies that coordinates are defined in radians (-PI .. PI).\r
+ It has to be specified for some coordinate systems.\r
+\qbk{[include reference/core/degree_radian.qbk]}\r
+*/\r
+struct radian {};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace core_detail\r
+{\r
+\r
+template <typename DegreeOrRadian>\r
+struct coordinate_system_units\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ ((false),\r
+ COORDINATE_SYSTEM_UNITS_MUST_BE_DEGREES_OR_RADIANS,\r
+ (types<DegreeOrRadian>));\r
+};\r
+\r
+template <>\r
+struct coordinate_system_units<geometry::degree>\r
+{\r
+ typedef geometry::degree units;\r
+};\r
+\r
+template <>\r
+struct coordinate_system_units<geometry::radian>\r
+{\r
+ typedef geometry::radian units;\r
+};\r
+\r
+} // namespace core_detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+namespace cs\r
+{\r
+\r
+/*!\r
+\brief Cartesian coordinate system\r
+\details Defines the Cartesian or rectangular coordinate system\r
+ where points are defined in 2 or 3 (or more)\r
+dimensions and usually (but not always) known as x,y,z\r
+\see http://en.wikipedia.org/wiki/Cartesian_coordinate_system\r
+\ingroup cs\r
+*/\r
+struct cartesian {};\r
+\r
+\r
+\r
+\r
+/*!\r
+\brief Geographic coordinate system, in degree or in radian\r
+\details Defines the geographic coordinate system where points\r
+ are defined in two angles and usually\r
+known as lat,long or lo,la or phi,lambda\r
+\see http://en.wikipedia.org/wiki/Geographic_coordinate_system\r
+\ingroup cs\r
+\note might be moved to extensions/gis/geographic\r
+*/\r
+template<typename DegreeOrRadian>\r
+struct geographic\r
+{\r
+ typedef typename core_detail::coordinate_system_units\r
+ <\r
+ DegreeOrRadian\r
+ >::units units;\r
+};\r
+\r
+\r
+\r
+/*!\r
+\brief Spherical (polar) coordinate system, in degree or in radian\r
+\details Defines the spherical coordinate system where points are\r
+ defined in two angles\r
+ and an optional radius usually known as r, theta, phi\r
+\par Coordinates:\r
+- coordinate 0:\r
+ 0 <= phi < 2pi is the angle between the positive x-axis and the\r
+ line from the origin to the P projected onto the xy-plane.\r
+- coordinate 1:\r
+ 0 <= theta <= pi is the angle between the positive z-axis and the\r
+ line formed between the origin and P.\r
+- coordinate 2 (if specified):\r
+ r >= 0 is the distance from the origin to a given point P.\r
+\r
+\see http://en.wikipedia.org/wiki/Spherical_coordinates\r
+\ingroup cs\r
+*/\r
+template<typename DegreeOrRadian>\r
+struct spherical\r
+{\r
+ typedef typename core_detail::coordinate_system_units\r
+ <\r
+ DegreeOrRadian\r
+ >::units units;\r
+};\r
+\r
+\r
+/*!\r
+\brief Spherical equatorial coordinate system, in degree or in radian\r
+\details This one resembles the geographic coordinate system, and has latitude\r
+ up from zero at the equator, to 90 at the pole\r
+ (opposite to the spherical(polar) coordinate system).\r
+ Used in astronomy and in GIS (but there is also the geographic)\r
+\r
+\see http://en.wikipedia.org/wiki/Spherical_coordinates\r
+\ingroup cs\r
+*/\r
+template<typename DegreeOrRadian>\r
+struct spherical_equatorial\r
+{\r
+ typedef typename core_detail::coordinate_system_units\r
+ <\r
+ DegreeOrRadian\r
+ >::units units;\r
+};\r
+\r
+\r
+\r
+/*!\r
+\brief Polar coordinate system\r
+\details Defines the polar coordinate system "in which each point\r
+ on a plane is determined by an angle and a distance"\r
+\see http://en.wikipedia.org/wiki/Polar_coordinates\r
+\ingroup cs\r
+*/\r
+template<typename DegreeOrRadian>\r
+struct polar\r
+{\r
+ typedef typename core_detail::coordinate_system_units\r
+ <\r
+ DegreeOrRadian\r
+ >::units units;\r
+};\r
+\r
+\r
+} // namespace cs\r
+\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class defining coordinate system tag, bound to coordinate system\r
+\ingroup traits\r
+\tparam CoordinateSystem coordinate system\r
+*/\r
+template <typename CoordinateSystem>\r
+struct cs_tag\r
+{\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+template<typename DegreeOrRadian>\r
+struct cs_tag<cs::geographic<DegreeOrRadian> >\r
+{\r
+ typedef geographic_tag type;\r
+};\r
+\r
+template<typename DegreeOrRadian>\r
+struct cs_tag<cs::spherical<DegreeOrRadian> >\r
+{\r
+ typedef spherical_polar_tag type;\r
+};\r
+\r
+template<typename DegreeOrRadian>\r
+struct cs_tag<cs::spherical_equatorial<DegreeOrRadian> >\r
+{\r
+ typedef spherical_equatorial_tag type;\r
+};\r
+\r
+\r
+template<>\r
+struct cs_tag<cs::cartesian>\r
+{\r
+ typedef cartesian_tag type;\r
+};\r
+\r
+\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+} // namespace traits\r
+\r
+/*!\r
+\brief Meta-function returning coordinate system tag (cs family) of any geometry\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+*/\r
+template <typename Geometry>\r
+struct cs_tag\r
+{\r
+ typedef typename traits::cs_tag\r
+ <\r
+ typename geometry::coordinate_system<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+/*!\r
+\brief Meta-function to verify if a coordinate system is radian\r
+\tparam CoordinateSystem Any coordinate system.\r
+\ingroup core\r
+*/\r
+template <typename CoordinateSystem>\r
+struct is_radian : boost::true_type {};\r
+\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+// Specialization for any degree coordinate systems\r
+template <template<typename> class CoordinateSystem>\r
+struct is_radian< CoordinateSystem<degree> > : boost::false_type\r
+{\r
+};\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_CS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_EXCEPTION_HPP\r
+#define BOOST_GEOMETRY_CORE_EXCEPTION_HPP\r
+\r
+#include <exception>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Base exception class for Boost.Geometry algorithms\r
+\ingroup core\r
+\details This class is never thrown. All exceptions thrown in Boost.Geometry\r
+ are derived from exception, so it might be convenient to catch it.\r
+*/\r
+class exception : public std::exception\r
+{\r
+public:\r
+ virtual char const* what() const throw()\r
+ {\r
+ return "Boost.Geometry exception";\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Invalid Input Exception\r
+\ingroup core\r
+\details The invalid_input_exception is thrown if an invalid attribute\r
+ is passed into a function, e.g. a DE-9IM mask string code containing\r
+ invalid characters passed into a de9im::mask constructor.\r
+ */\r
+class invalid_input_exception : public geometry::exception\r
+{\r
+public:\r
+\r
+ inline invalid_input_exception() {}\r
+\r
+ virtual char const* what() const throw()\r
+ {\r
+ return "Boost.Geometry Invalid-Input exception";\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Empty Input Exception\r
+\ingroup core\r
+\details The empty_input_exception is thrown if free functions, e.g. distance,\r
+ are called with empty geometries, e.g. a linestring\r
+ without points, a polygon without points, an empty multi-geometry.\r
+\qbk{\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.area the area function]\r
+\* [link geometry.reference.algorithms.distance the distance function]\r
+\* [link geometry.reference.algorithms.length the length function]\r
+}\r
+ */\r
+class empty_input_exception : public geometry::invalid_input_exception\r
+{\r
+public:\r
+\r
+ inline empty_input_exception() {}\r
+\r
+ virtual char const* what() const throw()\r
+ {\r
+ return "Boost.Geometry Empty-Input exception";\r
+ }\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_EXCEPTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP\r
+#define BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/util/add_const_if_c.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+\r
+/*!\r
+ \brief Traits class defining access to exterior_ring of a polygon\r
+ \details Should define const and non const access\r
+ \ingroup traits\r
+ \tparam Polygon the polygon type\r
+ \par Geometries:\r
+ - polygon\r
+ \par Specializations should provide:\r
+ - static inline RING& get(POLY& )\r
+ - static inline RING const& get(POLY const& )\r
+*/\r
+template <typename Polygon>\r
+struct exterior_ring\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POLYGON_TYPE\r
+ , (types<Polygon>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+\r
+template <typename Tag, typename Geometry>\r
+struct exterior_ring\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct exterior_ring<polygon_tag, Polygon>\r
+{\r
+ static\r
+ typename geometry::ring_return_type<Polygon>::type\r
+ apply(typename add_const_if_c\r
+ <\r
+ boost::is_const<Polygon>::type::value,\r
+ Polygon\r
+ >::type& polygon)\r
+ {\r
+ return traits::exterior_ring\r
+ <\r
+ typename boost::remove_const<Polygon>::type\r
+ >::get(polygon);\r
+ }\r
+};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+ \brief Function to get the exterior_ring ring of a polygon\r
+ \ingroup exterior_ring\r
+ \note OGC compliance: instead of ExteriorRing\r
+ \tparam Polygon polygon type\r
+ \param polygon the polygon to get the exterior ring from\r
+ \return a reference to the exterior ring\r
+*/\r
+template <typename Polygon>\r
+inline typename ring_return_type<Polygon>::type exterior_ring(Polygon& polygon)\r
+{\r
+ return core_dispatch::exterior_ring\r
+ <\r
+ typename tag<Polygon>::type,\r
+ Polygon\r
+ >::apply(polygon);\r
+}\r
+\r
+\r
+/*!\r
+\brief Function to get the exterior ring of a polygon (const version)\r
+\ingroup exterior_ring\r
+\note OGC compliance: instead of ExteriorRing\r
+\tparam Polygon polygon type\r
+\param polygon the polygon to get the exterior ring from\r
+\return a const reference to the exterior ring\r
+\r
+\qbk{distinguish,const version}\r
+*/\r
+template <typename Polygon>\r
+inline typename ring_return_type<Polygon const>::type exterior_ring(\r
+ Polygon const& polygon)\r
+{\r
+ return core_dispatch::exterior_ring\r
+ <\r
+ typename tag<Polygon>::type,\r
+ Polygon const\r
+ >::apply(polygon);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP\r
+#define BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/int.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename GeometryTag>\r
+struct geometry_id\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<GeometryTag>)\r
+ );\r
+};\r
+\r
+\r
+template <>\r
+struct geometry_id<point_tag> : boost::mpl::int_<1> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<linestring_tag> : boost::mpl::int_<2> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<polygon_tag> : boost::mpl::int_<3> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<multi_point_tag> : boost::mpl::int_<4> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<multi_linestring_tag> : boost::mpl::int_<5> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<multi_polygon_tag> : boost::mpl::int_<6> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<segment_tag> : boost::mpl::int_<92> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<ring_tag> : boost::mpl::int_<93> {};\r
+\r
+\r
+template <>\r
+struct geometry_id<box_tag> : boost::mpl::int_<94> {};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+\r
+/*!\r
+\brief Meta-function returning the id of a geometry type\r
+\details The meta-function geometry_id defines a numerical ID (based on\r
+ boost::mpl::int_<...> ) for each geometry concept. A numerical ID is\r
+ sometimes useful, and within Boost.Geometry it is used for the\r
+ reverse_dispatch metafuntion.\r
+\note Used for e.g. reverse meta-function\r
+\ingroup core\r
+*/\r
+template <typename Geometry>\r
+struct geometry_id : core_dispatch::geometry_id<typename tag<Geometry>::type>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP\r
+#define BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/interior_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+\r
+/*!\r
+ \brief Traits class defining access to interior_rings of a polygon\r
+ \details defines access (const and non const) to interior ring\r
+ \ingroup traits\r
+ \par Geometries:\r
+ - polygon\r
+ \par Specializations should provide:\r
+ - static inline INTERIOR& get(POLY&)\r
+ - static inline const INTERIOR& get(POLY const&)\r
+ \tparam Geometry geometry\r
+*/\r
+template <typename Geometry>\r
+struct interior_rings\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename GeometryTag,\r
+ typename Geometry\r
+>\r
+struct interior_rings {};\r
+\r
+\r
+template <typename Polygon>\r
+struct interior_rings<polygon_tag, Polygon>\r
+{\r
+ static inline\r
+ typename geometry::interior_return_type<Polygon>::type\r
+ apply(Polygon& polygon)\r
+ {\r
+ return traits::interior_rings\r
+ <\r
+ typename boost::remove_const<Polygon>::type\r
+ >::get(polygon);\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct interior_type<multi_polygon_tag, MultiPolygon>\r
+{\r
+ typedef typename core_dispatch::interior_type\r
+ <\r
+ polygon_tag,\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+\r
+/*!\r
+\brief Function to get the interior rings of a polygon (non const version)\r
+\ingroup interior_rings\r
+\note OGC compliance: instead of InteriorRingN\r
+\tparam Polygon polygon type\r
+\param polygon the polygon to get the interior rings from\r
+\return the interior rings (possibly a reference)\r
+*/\r
+\r
+template <typename Polygon>\r
+inline typename interior_return_type<Polygon>::type interior_rings(Polygon& polygon)\r
+{\r
+ return core_dispatch::interior_rings\r
+ <\r
+ typename tag<Polygon>::type,\r
+ Polygon\r
+ >::apply(polygon);\r
+}\r
+\r
+\r
+/*!\r
+\brief Function to get the interior rings of a polygon (const version)\r
+\ingroup interior_rings\r
+\note OGC compliance: instead of InteriorRingN\r
+\tparam Polygon polygon type\r
+\param polygon the polygon to get the interior rings from\r
+\return the interior rings (possibly a const reference)\r
+\r
+\qbk{distinguish,const version}\r
+*/\r
+template <typename Polygon>\r
+inline typename interior_return_type<Polygon const>::type interior_rings(\r
+ Polygon const& polygon)\r
+{\r
+ return core_dispatch::interior_rings\r
+ <\r
+ typename tag<Polygon>::type,\r
+ Polygon const\r
+ >::apply(polygon);\r
+}\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_INTERIOR_TYPE_HPP\r
+#define BOOST_GEOMETRY_CORE_INTERIOR_TYPE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class indicating interior container type of a polygon\r
+\details defines inner container type, so the container containing\r
+ the interior rings\r
+\ingroup traits\r
+\par Geometries:\r
+ - polygon\r
+\par Specializations should provide:\r
+ - typedef X type ( e.g. std::vector<myring<P>> )\r
+\tparam Geometry geometry\r
+*/\r
+template <typename Geometry>\r
+struct interior_const_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+template <typename Geometry>\r
+struct interior_mutable_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct interior_return_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct interior_return_type<polygon_tag, Polygon>\r
+{\r
+ typedef typename boost::remove_const<Polygon>::type nc_polygon_type;\r
+\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_const<Polygon>,\r
+ typename traits::interior_const_type<nc_polygon_type>::type,\r
+ typename traits::interior_mutable_type<nc_polygon_type>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct interior_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct interior_type<polygon_tag, Polygon>\r
+{\r
+ typedef typename boost::remove_reference\r
+ <\r
+ typename interior_return_type<polygon_tag, Polygon>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+\brief \brief_meta{type, interior_type (container type\r
+ of inner rings), \meta_geometry_type}\r
+\details Interior rings should be organized as a container\r
+ (std::vector, std::deque, boost::array) with\r
+ Boost.Range support. This metafunction defines the type\r
+ of the container.\r
+\tparam Geometry A type fullfilling the Polygon or MultiPolygon concept.\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/interior_type.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct interior_type\r
+{\r
+ typedef typename core_dispatch::interior_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::type type;\r
+};\r
+\r
+template <typename Geometry>\r
+struct interior_return_type\r
+{\r
+ typedef typename core_dispatch::interior_return_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_INTERIOR_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_IS_AREAL_HPP\r
+#define BOOST_GEOMETRY_CORE_IS_AREAL_HPP\r
+\r
+\r
+#include <boost/type_traits/integral_constant.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename GeometryTag> struct is_areal : boost::false_type {};\r
+\r
+template <> struct is_areal<ring_tag> : boost::true_type {};\r
+template <> struct is_areal<box_tag> : boost::true_type {};\r
+template <> struct is_areal<polygon_tag> : boost::true_type {};\r
+template <> struct is_areal<multi_polygon_tag> : boost::true_type {};\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+\r
+/*!\r
+ \brief Meta-function defining "true" for areal types (box, (multi)polygon, ring),\r
+ \note Used for tag dispatching and meta-function finetuning\r
+ \note Also a "ring" has areal properties within Boost.Geometry\r
+ \ingroup core\r
+*/\r
+template <typename Geometry>\r
+struct is_areal : core_dispatch::is_areal<typename tag<Geometry>::type>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_IS_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP\r
+#define BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Metafunction to define the argument passed to the three\r
+ traits classes clear, push_back and resize\r
+\ingroup mutable_range\r
+ */\r
+template <typename Range>\r
+struct rvalue_type\r
+{\r
+ typedef typename boost::remove_reference<Range>::type& type;\r
+};\r
+\r
+\r
+/*!\r
+\brief Traits class to clear a geometry\r
+\ingroup mutable_range\r
+ */\r
+template <typename Range>\r
+struct clear\r
+{\r
+ static inline void apply(typename rvalue_type<Range>::type range)\r
+ {\r
+ range.clear();\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Traits class to append a point to a range (ring, linestring, multi*)\r
+\ingroup mutable_range\r
+ */\r
+template <typename Range>\r
+struct push_back\r
+{\r
+ typedef typename boost::range_value\r
+ <\r
+ typename boost::remove_reference<Range>::type\r
+ >::type item_type;\r
+\r
+ static inline void apply(typename rvalue_type<Range>::type range,\r
+ item_type const& item)\r
+ {\r
+ range.push_back(item);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Traits class to append a point to a range (ring, linestring, multi*)\r
+\ingroup mutable_range\r
+ */\r
+template <typename Range>\r
+struct resize\r
+{\r
+ static inline void apply(typename rvalue_type<Range>::type range,\r
+ std::size_t new_size)\r
+ {\r
+ range.resize(new_size);\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_POINT_ORDER_HPP\r
+#define BOOST_GEOMETRY_CORE_POINT_ORDER_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range/value_type.hpp>\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Enumerates options for the order of points within polygons\r
+\ingroup enum\r
+\details The enumeration order_selector describes options for the order of\r
+ points within a polygon. Polygons can be ordered either clockwise or\r
+ counterclockwise. The specific order of a polygon type is defined by the\r
+ point_order metafunction. The point_order metafunction defines a value,\r
+ which is one of the values enumerated in the order_selector\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.core.point_order The point_order metafunction]\r
+}\r
+*/\r
+enum order_selector\r
+{\r
+ /// Points are ordered clockwise\r
+ clockwise = 1,\r
+ /// Points are ordered counter clockwise\r
+ counterclockwise = 2,\r
+ /// Points might be stored in any order, algorithms will determine it on the\r
+ /// fly (not yet supported)\r
+ order_undetermined = 0\r
+};\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class indicating the order of contained points within a\r
+ ring or (multi)polygon, clockwise, counter clockwise or not known.\r
+\ingroup traits\r
+\tparam Ring ring\r
+*/\r
+template <typename Ring>\r
+struct point_order\r
+{\r
+ static const order_selector value = clockwise;\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace point_order\r
+{\r
+\r
+struct clockwise\r
+{\r
+ static const order_selector value = geometry::clockwise;\r
+};\r
+\r
+\r
+}} // namespace detail::point_order\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry>\r
+struct point_order\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+template <typename Point>\r
+struct point_order<point_tag, Point>\r
+ : public detail::point_order::clockwise {};\r
+\r
+template <typename Segment>\r
+struct point_order<segment_tag, Segment>\r
+ : public detail::point_order::clockwise {};\r
+\r
+\r
+template <typename Box>\r
+struct point_order<box_tag, Box>\r
+ : public detail::point_order::clockwise {};\r
+\r
+template <typename LineString>\r
+struct point_order<linestring_tag, LineString>\r
+ : public detail::point_order::clockwise {};\r
+\r
+\r
+template <typename Ring>\r
+struct point_order<ring_tag, Ring>\r
+{\r
+ static const order_selector value\r
+ = geometry::traits::point_order<Ring>::value;\r
+};\r
+\r
+// Specialization for polygon: the order is the order of its rings\r
+template <typename Polygon>\r
+struct point_order<polygon_tag, Polygon>\r
+{\r
+ static const order_selector value = core_dispatch::point_order\r
+ <\r
+ ring_tag,\r
+ typename ring_type<polygon_tag, Polygon>::type\r
+ >::value ;\r
+};\r
+\r
+template <typename MultiPoint>\r
+struct point_order<multi_point_tag, MultiPoint>\r
+ : public detail::point_order::clockwise {};\r
+\r
+template <typename MultiLinestring>\r
+struct point_order<multi_linestring_tag, MultiLinestring>\r
+ : public detail::point_order::clockwise {};\r
+\r
+\r
+// Specialization for multi_polygon: the order is the order of its polygons\r
+template <typename MultiPolygon>\r
+struct point_order<multi_polygon_tag, MultiPolygon>\r
+{\r
+ static const order_selector value = core_dispatch::point_order\r
+ <\r
+ polygon_tag,\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >::value ;\r
+};\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief \brief_meta{value, point order (clockwise\, counterclockwise),\r
+ \meta_geometry_type}\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/point_order.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct point_order\r
+{\r
+ static const order_selector value = core_dispatch::point_order\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename util::bare_type<Geometry>::type\r
+ >::value;\r
+};\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_POINT_ORDER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_POINT_TYPE_HPP\r
+#define BOOST_GEOMETRY_CORE_POINT_TYPE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class indicating the type of contained points\r
+\ingroup traits\r
+\par Geometries:\r
+ - all geometries except point\r
+\par Specializations should provide:\r
+ - typedef P type (where P should fulfil the Point concept)\r
+\tparam Geometry geometry\r
+*/\r
+template <typename Geometry>\r
+struct point_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry>\r
+struct point_type\r
+{\r
+ // Default: call traits to get point type\r
+ typedef typename boost::remove_const\r
+ <\r
+ typename traits::point_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+// Specialization for point: the point itself\r
+template <typename Point>\r
+struct point_type<point_tag, Point>\r
+{\r
+ typedef Point type;\r
+};\r
+\r
+\r
+// Specializations for linestring/ring, via boost::range\r
+template <typename Linestring>\r
+struct point_type<linestring_tag, Linestring>\r
+{\r
+ typedef typename boost::range_value<Linestring>::type type;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct point_type<ring_tag, Ring>\r
+{\r
+ typedef typename boost::range_value<Ring>::type type;\r
+};\r
+\r
+\r
+// Specialization for polygon: the point-type is the point-type of its rings\r
+template <typename Polygon>\r
+struct point_type<polygon_tag, Polygon>\r
+{\r
+ typedef typename point_type\r
+ <\r
+ ring_tag,\r
+ typename ring_type<polygon_tag, Polygon>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiPoint>\r
+struct point_type<multi_point_tag, MultiPoint>\r
+{\r
+ typedef typename boost::range_value\r
+ <\r
+ MultiPoint\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct point_type<multi_linestring_tag, MultiLinestring>\r
+{\r
+ typedef typename point_type\r
+ <\r
+ linestring_tag,\r
+ typename boost::range_value<MultiLinestring>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct point_type<multi_polygon_tag, MultiPolygon>\r
+{\r
+ typedef typename point_type\r
+ <\r
+ polygon_tag,\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief \brief_meta{type, point_type, \meta_geometry_type}\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/point_type.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct point_type\r
+{\r
+ typedef typename core_dispatch::point_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename boost::geometry::util::bare_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_POINT_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP\r
+#define BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template<std::size_t Dimension, typename Geometry>\r
+struct degree_radian_converter\r
+{\r
+ typedef typename fp_coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(Geometry const& geometry)\r
+ {\r
+ return boost::numeric_cast\r
+ <\r
+ coordinate_type\r
+ >(geometry::get<Dimension>(geometry)\r
+ * math::d2r<coordinate_type>());\r
+ }\r
+\r
+ static inline void set(Geometry& geometry, coordinate_type const& radians)\r
+ {\r
+ geometry::set<Dimension>(geometry, boost::numeric_cast\r
+ <\r
+ coordinate_type\r
+ >(radians * math::r2d<coordinate_type>()));\r
+ }\r
+\r
+};\r
+\r
+\r
+// Default, radian (or any other coordinate system) just works like "get"\r
+template <std::size_t Dimension, typename Geometry, typename DegreeOrRadian>\r
+struct radian_access\r
+{\r
+ typedef typename fp_coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(Geometry const& geometry)\r
+ {\r
+ return geometry::get<Dimension>(geometry);\r
+ }\r
+\r
+ static inline void set(Geometry& geometry, coordinate_type const& radians)\r
+ {\r
+ geometry::set<Dimension>(geometry, radians);\r
+ }\r
+};\r
+\r
+// Specialize, any "degree" coordinate system will be converted to radian\r
+// but only for dimension 0,1 (so: dimension 2 and heigher are untouched)\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ template<typename> class CoordinateSystem\r
+>\r
+struct radian_access<0, Geometry, CoordinateSystem<degree> >\r
+ : degree_radian_converter<0, Geometry>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ template<typename> class CoordinateSystem\r
+>\r
+struct radian_access<1, Geometry, CoordinateSystem<degree> >\r
+ : degree_radian_converter<1, Geometry>\r
+{};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief get coordinate value of a point, result is in Radian\r
+\details Result is in Radian, even if source coordinate system\r
+ is in Degrees\r
+\return coordinate value\r
+\ingroup get\r
+\tparam Dimension dimension\r
+\tparam Geometry geometry\r
+\param geometry geometry to get coordinate value from\r
+\note Only applicable to coordinate systems templatized by units,\r
+ e.g. spherical or geographic coordinate systems\r
+*/\r
+template <std::size_t Dimension, typename Geometry>\r
+inline typename fp_coordinate_type<Geometry>::type get_as_radian(Geometry const& geometry)\r
+{\r
+ return detail::radian_access<Dimension, Geometry,\r
+ typename coordinate_system<Geometry>::type>::get(geometry);\r
+}\r
+\r
+\r
+/*!\r
+\brief set coordinate value (in radian) to a point\r
+\details Coordinate value will be set correctly, if coordinate system of\r
+ point is in Degree, Radian value will be converted to Degree\r
+\ingroup set\r
+\tparam Dimension dimension\r
+\tparam Geometry geometry\r
+\param geometry geometry to assign coordinate to\r
+\param radians coordinate value to assign\r
+\note Only applicable to coordinate systems templatized by units,\r
+ e.g. spherical or geographic coordinate systems\r
+*/\r
+template <std::size_t Dimension, typename Geometry>\r
+inline void set_from_radian(Geometry& geometry,\r
+ typename fp_coordinate_type<Geometry>::type const& radians)\r
+{\r
+ detail::radian_access<Dimension, Geometry,\r
+ typename coordinate_system<Geometry>::type>::set(geometry, radians);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_RADIUS_HPP\r
+#define BOOST_GEOMETRY_CORE_RADIUS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/static_assert.hpp>\r
+#include <boost/type_traits/is_pointer.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+ \brief Traits class to get/set radius of a circle/sphere/(ellipse)\r
+ \details the radius access meta-functions give read/write access to the radius of a circle or a sphere,\r
+ or to the major/minor axis or an ellipse, or to one of the 3 equatorial radii of an ellipsoid.\r
+\r
+ It should be specialized per geometry, in namespace core_dispatch. Those specializations should\r
+ forward the call via traits to the geometry class, which could be specified by the user.\r
+\r
+ There is a corresponding generic radius_get and radius_set function\r
+ \par Geometries:\r
+ - n-sphere (circle,sphere)\r
+ - upcoming ellipse\r
+ \par Specializations should provide:\r
+ - inline static T get(Geometry const& geometry)\r
+ - inline static void set(Geometry& geometry, T const& radius)\r
+ \ingroup traits\r
+*/\r
+template <typename Geometry, std::size_t Dimension>\r
+struct radius_access {};\r
+\r
+\r
+/*!\r
+ \brief Traits class indicating the type (double,float,...) of the radius of a circle or a sphere\r
+ \par Geometries:\r
+ - n-sphere (circle,sphere)\r
+ - upcoming ellipse\r
+ \par Specializations should provide:\r
+ - typedef T type (double,float,int,etc)\r
+ \ingroup traits\r
+*/\r
+template <typename Geometry>\r
+struct radius_type {};\r
+\r
+} // namespace traits\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry>\r
+struct radius_type\r
+{\r
+ //typedef core_dispatch_specialization_required type;\r
+};\r
+\r
+/*!\r
+ \brief radius access meta-functions, used by concept n-sphere and upcoming ellipse.\r
+*/\r
+template <typename Tag,\r
+ typename Geometry,\r
+ std::size_t Dimension,\r
+ typename IsPointer>\r
+struct radius_access\r
+{\r
+ //static inline CoordinateType get(Geometry const& ) {}\r
+ //static inline void set(Geometry& g, CoordinateType const& value) {}\r
+};\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+ \brief Metafunction to get the type of radius of a circle / sphere / ellipse / etc.\r
+ \ingroup access\r
+ \tparam Geometry the type of geometry\r
+*/\r
+template <typename Geometry>\r
+struct radius_type\r
+{\r
+ typedef typename core_dispatch::radius_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename util::bare_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+/*!\r
+ \brief Function to get radius of a circle / sphere / ellipse / etc.\r
+ \return radius The radius for a given axis\r
+ \ingroup access\r
+ \param geometry the geometry to get the radius from\r
+ \tparam I index of the axis\r
+*/\r
+template <std::size_t I, typename Geometry>\r
+inline typename radius_type<Geometry>::type get_radius(Geometry const& geometry)\r
+{\r
+ return core_dispatch::radius_access\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename util::bare_type<Geometry>::type,\r
+ I,\r
+ typename boost::is_pointer<Geometry>::type\r
+ >::get(geometry);\r
+}\r
+\r
+/*!\r
+ \brief Function to set the radius of a circle / sphere / ellipse / etc.\r
+ \ingroup access\r
+ \tparam I index of the axis\r
+ \param geometry the geometry to change\r
+ \param radius the radius to set\r
+*/\r
+template <std::size_t I, typename Geometry>\r
+inline void set_radius(Geometry& geometry,\r
+ typename radius_type<Geometry>::type const& radius)\r
+{\r
+ core_dispatch::radius_access\r
+ <\r
+ typename tag<Geometry>::type,\r
+ typename util::bare_type<Geometry>::type,\r
+ I,\r
+ typename boost::is_pointer<Geometry>::type\r
+ >::set(geometry, radius);\r
+}\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Tag, typename Geometry, std::size_t Dimension>\r
+struct radius_access\r
+{\r
+ static inline typename radius_type<Geometry>::type get(Geometry const& geometry)\r
+ {\r
+ return traits::radius_access<Geometry, Dimension>::get(geometry);\r
+ }\r
+ static inline void set(Geometry& geometry,\r
+ typename radius_type<Geometry>::type const& value)\r
+ {\r
+ traits::radius_access<Geometry, Dimension>::set(geometry, value);\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename Tag,\r
+ typename Geometry,\r
+ std::size_t Dimension>\r
+struct radius_access<Tag, Geometry, Dimension, boost::true_type>\r
+{\r
+ typedef typename geometry::radius_type<Geometry>::type radius_type;\r
+\r
+ static inline radius_type get(const Geometry * geometry)\r
+ {\r
+ return radius_access\r
+ <\r
+ Tag,\r
+ Geometry,\r
+ Dimension,\r
+ typename boost::is_pointer<Geometry>::type\r
+ >::get(*geometry);\r
+ }\r
+\r
+ static inline void set(Geometry * geometry, radius_type const& value)\r
+ {\r
+ return radius_access\r
+ <\r
+ Tag,\r
+ Geometry,\r
+ Dimension,\r
+ typename boost::is_pointer<Geometry>::type\r
+ >::set(*geometry, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct radius_type<srs_sphere_tag, Geometry>\r
+{\r
+ typedef typename traits::radius_type<Geometry>::type type;\r
+};\r
+\r
+template <typename Geometry, std::size_t Dimension>\r
+struct radius_access<srs_sphere_tag, Geometry, Dimension, boost::false_type>\r
+ : detail::radius_access<srs_sphere_tag, Geometry, Dimension>\r
+{\r
+ BOOST_STATIC_ASSERT(Dimension == 0);\r
+ //BOOST_STATIC_ASSERT(Dimension < 3);\r
+};\r
+\r
+template <typename Geometry>\r
+struct radius_type<srs_spheroid_tag, Geometry>\r
+{\r
+ typedef typename traits::radius_type<Geometry>::type type;\r
+};\r
+\r
+template <typename Geometry, std::size_t Dimension>\r
+struct radius_access<srs_spheroid_tag, Geometry, Dimension, boost::false_type>\r
+ : detail::radius_access<srs_spheroid_tag, Geometry, Dimension>\r
+{\r
+ BOOST_STATIC_ASSERT(Dimension == 0 || Dimension == 2);\r
+ //BOOST_STATIC_ASSERT(Dimension < 3);\r
+};\r
+\r
+} // namespace core_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_RADIUS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP\r
+#define BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/integral_constant.hpp>\r
+\r
+#include <boost/geometry/core/geometry_id.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+// Different geometries: reverse_dispatch if second ID < first ID\r
+template <std::size_t GeometryId1, std::size_t GeometryId2>\r
+struct reverse_dispatch : boost::mpl::if_c\r
+ <\r
+ (GeometryId1 > GeometryId2),\r
+ boost::true_type,\r
+ boost::false_type\r
+ >\r
+{};\r
+\r
+\r
+// Same geometry: never reverse_dispatch\r
+template <std::size_t GeometryId>\r
+struct reverse_dispatch<GeometryId, GeometryId> : boost::false_type {};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct reverse_dispatch : detail::reverse_dispatch\r
+ <\r
+ geometry_id<Geometry1>::type::value,\r
+ geometry_id<Geometry2>::type::value\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_RING_TYPE_HPP\r
+#define BOOST_GEOMETRY_CORE_RING_TYPE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+\r
+/*!\r
+\brief Traits class to indicate ring-type of a polygon's exterior ring/interior rings\r
+\ingroup traits\r
+\par Geometries:\r
+ - polygon\r
+\par Specializations should provide:\r
+ - typedef XXX type ( e.g. ring<P> )\r
+\tparam Geometry geometry\r
+*/\r
+template <typename Geometry>\r
+struct ring_const_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+template <typename Geometry>\r
+struct ring_mutable_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct ring_return_type\r
+{};\r
+\r
+\r
+template <typename LineString>\r
+struct ring_return_type<linestring_tag, LineString>\r
+{\r
+ typedef LineString& type;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct ring_return_type<ring_tag, Ring>\r
+{\r
+ typedef Ring& type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct ring_return_type<polygon_tag, Polygon>\r
+{\r
+ typedef typename boost::remove_const<Polygon>::type nc_polygon_type;\r
+\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_const<Polygon>,\r
+ typename traits::ring_const_type<nc_polygon_type>::type,\r
+ typename traits::ring_mutable_type<nc_polygon_type>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct ring_return_type<multi_linestring_tag, MultiLinestring>\r
+{\r
+ typedef typename ring_return_type\r
+ <\r
+ linestring_tag,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_const<MultiLinestring>,\r
+ typename boost::range_value<MultiLinestring>::type const,\r
+ typename boost::range_value<MultiLinestring>::type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct ring_return_type<multi_polygon_tag, MultiPolygon>\r
+{\r
+ typedef typename ring_return_type\r
+ <\r
+ polygon_tag,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_const<MultiPolygon>,\r
+ typename boost::range_value<MultiPolygon>::type const,\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename GeometryTag, typename Geometry>\r
+struct ring_type\r
+{};\r
+\r
+\r
+template <typename Ring>\r
+struct ring_type<ring_tag, Ring>\r
+{\r
+ typedef Ring type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct ring_type<polygon_tag, Polygon>\r
+{\r
+ typedef typename boost::remove_reference\r
+ <\r
+ typename ring_return_type<polygon_tag, Polygon>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct ring_type<multi_linestring_tag, MultiLinestring>\r
+{\r
+ typedef typename boost::remove_reference\r
+ <\r
+ typename ring_return_type<multi_linestring_tag, MultiLinestring>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct ring_type<multi_polygon_tag, MultiPolygon>\r
+{\r
+ typedef typename boost::remove_reference\r
+ <\r
+ typename ring_return_type<multi_polygon_tag, MultiPolygon>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+\brief \brief_meta{type, ring_type, \meta_geometry_type}\r
+\details A polygon contains one exterior ring\r
+ and zero or more interior rings (holes).\r
+ This metafunction retrieves the type of the rings.\r
+ Exterior ring and each of the interior rings all have the same ring_type.\r
+\tparam Geometry A type fullfilling the Ring, Polygon or MultiPolygon concept.\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/ring_type.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct ring_type\r
+{\r
+ typedef typename core_dispatch::ring_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct ring_return_type\r
+{\r
+ typedef typename core_dispatch::ring_return_type\r
+ <\r
+ typename tag<Geometry>::type,\r
+ Geometry\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_RING_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_SRS_HPP\r
+#define BOOST_GEOMETRY_CORE_SRS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/static_assert.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ \r
+namespace srs\r
+{\r
+\r
+/*!\r
+ \brief Defines spheroid radius values for use in geographical CS calculations\r
+ \note See http://en.wikipedia.org/wiki/Figure_of_the_Earth\r
+ and http://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS84\r
+*/\r
+template <typename RadiusType>\r
+class spheroid\r
+{\r
+public:\r
+ spheroid(RadiusType const& a, RadiusType const& b)\r
+ : m_a(a)\r
+ , m_b(b)\r
+ {}\r
+\r
+ spheroid()\r
+ : m_a(RadiusType(6378137.0))\r
+ , m_b(RadiusType(6356752.314245))\r
+ {}\r
+\r
+ template <std::size_t I>\r
+ RadiusType get_radius() const\r
+ {\r
+ BOOST_STATIC_ASSERT(I < 3);\r
+\r
+ return I < 2 ? m_a : m_b;\r
+ }\r
+\r
+ template <std::size_t I>\r
+ void set_radius(RadiusType const& radius)\r
+ {\r
+ BOOST_STATIC_ASSERT(I < 3);\r
+\r
+ (I < 2 ? m_a : m_b) = radius;\r
+ }\r
+\r
+private:\r
+ RadiusType m_a, m_b; // equatorial radius, polar radius\r
+};\r
+\r
+} // namespace srs\r
+\r
+// Traits specializations for spheroid\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename RadiusType>\r
+struct tag< srs::spheroid<RadiusType> >\r
+{\r
+ typedef srs_spheroid_tag type;\r
+};\r
+\r
+template <typename RadiusType>\r
+struct radius_type< srs::spheroid<RadiusType> >\r
+{\r
+ typedef RadiusType type;\r
+};\r
+\r
+template <typename RadiusType, std::size_t Dimension>\r
+struct radius_access<srs::spheroid<RadiusType>, Dimension>\r
+{\r
+ typedef srs::spheroid<RadiusType> spheroid_type;\r
+\r
+ static inline RadiusType get(spheroid_type const& s)\r
+ {\r
+ return s.template get_radius<Dimension>();\r
+ }\r
+\r
+ static inline void set(spheroid_type& s, RadiusType const& value)\r
+ {\r
+ s.template set_radius<Dimension>(value);\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+namespace srs\r
+{\r
+\r
+/*!\r
+ \brief Defines sphere radius value for use in spherical CS calculations\r
+*/\r
+template <typename RadiusType>\r
+class sphere\r
+{\r
+public:\r
+ explicit sphere(RadiusType const& r)\r
+ : m_r(r)\r
+ {}\r
+ sphere()\r
+ : m_r(RadiusType((2.0 * 6378137.0 + 6356752.314245) / 3.0))\r
+ {}\r
+\r
+ template <std::size_t I>\r
+ RadiusType get_radius() const\r
+ {\r
+ BOOST_STATIC_ASSERT(I < 3);\r
+\r
+ return m_r;\r
+ }\r
+\r
+ template <std::size_t I>\r
+ void set_radius(RadiusType const& radius)\r
+ {\r
+ BOOST_STATIC_ASSERT(I < 3);\r
+\r
+ m_r = radius;\r
+ }\r
+\r
+private:\r
+ RadiusType m_r; // radius\r
+};\r
+\r
+} // namespace srs\r
+\r
+// Traits specializations for sphere\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename RadiusType>\r
+struct tag< srs::sphere<RadiusType> >\r
+{\r
+ typedef srs_sphere_tag type;\r
+};\r
+\r
+template <typename RadiusType>\r
+struct radius_type< srs::sphere<RadiusType> >\r
+{\r
+ typedef RadiusType type;\r
+};\r
+\r
+template <typename RadiusType, std::size_t Dimension>\r
+struct radius_access<srs::sphere<RadiusType>, Dimension>\r
+{\r
+ typedef srs::sphere<RadiusType> sphere_type;\r
+\r
+ static inline RadiusType get(sphere_type const& s)\r
+ {\r
+ return s.template get_radius<Dimension>();\r
+ }\r
+\r
+ static inline void set(sphere_type& s, RadiusType const& value)\r
+ {\r
+ s.template set_radius<Dimension>(value);\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_SRS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_TAG_HPP\r
+#define BOOST_GEOMETRY_CORE_TAG_HPP\r
+\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+/*!\r
+\brief Traits class to attach a tag to a geometry\r
+\details All geometries should implement a traits::tag<G>::type metafunction to indicate their\r
+ own geometry type.\r
+\ingroup traits\r
+\par Geometries:\r
+ - all geometries\r
+\par Specializations should provide:\r
+ - typedef XXX_tag type; (point_tag, box_tag, ...)\r
+\tparam Geometry geometry\r
+*/\r
+template <typename Geometry, typename Enable = void>\r
+struct tag\r
+{\r
+ typedef void type;\r
+};\r
+\r
+} // namespace traits\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_meta{type, tag, \meta_geometry_type}\r
+\details With Boost.Geometry, tags are the driving force of the tag dispatching\r
+ mechanism. The tag metafunction is therefore used in every free function.\r
+\tparam Geometry \tparam_geometry\r
+\ingroup core\r
+\r
+\qbk{[include reference/core/tag.qbk]}\r
+*/\r
+template <typename Geometry>\r
+struct tag\r
+{\r
+ typedef typename traits::tag\r
+ <\r
+ typename geometry::util::bare_type<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_TAG_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_TAG_CAST_HPP\r
+#define BOOST_GEOMETRY_CORE_TAG_CAST_HPP\r
+\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_base_of.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Metafunction defining a type being either the specified tag, or one\r
+ of the specified basetags if the type inherits from them.\r
+\details Tags can inherit each other. A multi_point inherits, for example,\r
+ both the multi_tag and the pointlike_tag. Often behaviour can be shared\r
+ between different geometry types. A tag, found by the metafunction tag,\r
+ can be casted to a more basic tag, and then dispatched by that tag.\r
+\ingroup core\r
+\tparam Tag The tag to be casted to one of the base tags\r
+\tparam BaseTag First base tag\r
+\tparam BaseTag2 Optional second base tag\r
+\tparam BaseTag3 Optional third base tag\r
+\tparam BaseTag4 Optional fourth base tag\r
+\tparam BaseTag5 Optional fifth base tag\r
+\tparam BaseTag6 Optional sixth base tag\r
+\tparam BaseTag7 Optional seventh base tag\r
+\r
+\qbk{[include reference/core/tag_cast.qbk]}\r
+*/\r
+template\r
+<\r
+ typename Tag,\r
+ typename BaseTag,\r
+ typename BaseTag2 = void,\r
+ typename BaseTag3 = void,\r
+ typename BaseTag4 = void,\r
+ typename BaseTag5 = void,\r
+ typename BaseTag6 = void,\r
+ typename BaseTag7 = void\r
+>\r
+struct tag_cast\r
+{\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ typename boost::is_base_of<BaseTag, Tag>::type,\r
+ BaseTag,\r
+ // Try next one in line:\r
+ typename tag_cast\r
+ <\r
+ Tag, BaseTag2, BaseTag3, BaseTag4,\r
+ BaseTag5, BaseTag6, BaseTag7, void\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+// Specialization for last one\r
+template <typename Tag>\r
+struct tag_cast<Tag, void, void, void, void, void, void, void>\r
+{\r
+ // If not found, take specified tag, so do not cast\r
+ typedef Tag type;\r
+};\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_TAG_CAST_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_TAGS_HPP\r
+#define BOOST_GEOMETRY_CORE_TAGS_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Tags defining strategies linked to coordinate systems\r
+\r
+/// Tag used for casting spherical/geographic coordinate systems\r
+struct spherical_tag {};\r
+\r
+\r
+/// Tag indicating Cartesian coordinate system family (cartesian,epsg)\r
+struct cartesian_tag {};\r
+\r
+/// Tag indicating Spherical polar coordinate system family\r
+struct spherical_polar_tag : spherical_tag {};\r
+\r
+/// Tag indicating Spherical equatorial coordinate system family\r
+struct spherical_equatorial_tag : spherical_tag {};\r
+\r
+/// Tag indicating Geographic coordinate system family (geographic)\r
+struct geographic_tag : spherical_tag {};\r
+\r
+\r
+// Tags defining coordinate systems reference models\r
+\r
+/// For reference spheroid defining parameters of geographical coordinate system\r
+struct srs_spheroid_tag {};\r
+\r
+/// For reference sphere defining parameters of spherical coordinate system\r
+struct srs_sphere_tag : srs_spheroid_tag {};\r
+\r
+\r
+// Tags defining tag hierarchy\r
+\r
+/// For single-geometries (point, linestring, polygon, box, ring, segment)\r
+struct single_tag {};\r
+\r
+\r
+/// For multiple-geometries (multi_point, multi_linestring, multi_polygon)\r
+struct multi_tag {};\r
+\r
+/// For point-like types (point, multi_point)\r
+struct pointlike_tag {};\r
+\r
+/// For linear types (linestring, multi-linestring, segment)\r
+struct linear_tag {};\r
+\r
+/// For areal types (polygon, multi_polygon, box, ring)\r
+struct areal_tag {};\r
+\r
+// Subset of areal types (polygon, multi_polygon, ring)\r
+struct polygonal_tag : areal_tag {};\r
+\r
+/// For volume types (also box (?), polyhedron)\r
+struct volumetric_tag {};\r
+\r
+\r
+// Tags defining geometry types\r
+\r
+\r
+/// "default" tag\r
+struct geometry_not_recognized_tag {};\r
+\r
+/// OGC Point identifying tag\r
+struct point_tag : single_tag, pointlike_tag {};\r
+\r
+/// OGC Linestring identifying tag\r
+struct linestring_tag : single_tag, linear_tag {};\r
+\r
+/// OGC Polygon identifying tag\r
+struct polygon_tag : single_tag, polygonal_tag {};\r
+\r
+/// Convenience (linear) ring identifying tag\r
+struct ring_tag : single_tag, polygonal_tag {};\r
+\r
+/// Convenience 2D or 3D box (mbr / aabb) identifying tag\r
+struct box_tag : single_tag, areal_tag {};\r
+\r
+/// Convenience segment (2-points) identifying tag\r
+struct segment_tag : single_tag, linear_tag {};\r
+\r
+\r
+/// OGC Multi point identifying tag\r
+struct multi_point_tag : multi_tag, pointlike_tag {};\r
+\r
+/// OGC Multi linestring identifying tag\r
+struct multi_linestring_tag : multi_tag, linear_tag {};\r
+\r
+/// OGC Multi polygon identifying tag\r
+struct multi_polygon_tag : multi_tag, polygonal_tag {};\r
+\r
+/// OGC Geometry Collection identifying tag\r
+struct geometry_collection_tag : multi_tag {};\r
+\r
+\r
+/*!\r
+\brief Meta-function to get for a tag of a multi-geometry\r
+ the tag of the corresponding single-geometry\r
+*/\r
+template <typename Tag>\r
+struct single_tag_of\r
+{};\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+\r
+template <>\r
+struct single_tag_of<multi_point_tag>\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+template <>\r
+struct single_tag_of<multi_linestring_tag>\r
+{\r
+ typedef linestring_tag type;\r
+};\r
+\r
+template <>\r
+struct single_tag_of<multi_polygon_tag>\r
+{\r
+ typedef polygon_tag type;\r
+};\r
+\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_CORE_TAGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP\r
+#define BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP\r
+\r
+\r
+#include <boost/mpl/int.hpp>\r
+\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace core_dispatch\r
+{\r
+\r
+\r
+template <typename GeometryTag>\r
+struct top_dim {};\r
+\r
+\r
+template <>\r
+struct top_dim<point_tag> : boost::mpl::int_<0> {};\r
+\r
+\r
+template <>\r
+struct top_dim<linestring_tag> : boost::mpl::int_<1> {};\r
+\r
+\r
+template <>\r
+struct top_dim<segment_tag> : boost::mpl::int_<1> {};\r
+\r
+\r
+// ring: topological dimension of two, but some people say: 1 !!\r
+// NOTE: This is not OGC LinearRing!\r
+template <>\r
+struct top_dim<ring_tag> : boost::mpl::int_<2> {};\r
+\r
+\r
+// TODO: This is wrong! Boxes may have various topological dimensions\r
+template <>\r
+struct top_dim<box_tag> : boost::mpl::int_<2> {};\r
+\r
+\r
+template <>\r
+struct top_dim<polygon_tag> : boost::mpl::int_<2> {};\r
+\r
+\r
+template <>\r
+struct top_dim<multi_point_tag> : boost::mpl::int_<0> {};\r
+\r
+\r
+template <>\r
+struct top_dim<multi_linestring_tag> : boost::mpl::int_<1> {};\r
+\r
+\r
+template <>\r
+struct top_dim<multi_polygon_tag> : boost::mpl::int_<2> {};\r
+\r
+\r
+} // namespace core_dispatch\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+/*!\r
+ \brief Meta-function returning the topological dimension of a geometry\r
+ \details The topological dimension defines a point as 0-dimensional,\r
+ a linestring as 1-dimensional,\r
+ and a ring or polygon as 2-dimensional.\r
+ \see http://www.math.okstate.edu/mathdept/dynamics/lecnotes/node36.html\r
+ \ingroup core\r
+*/\r
+template <typename Geometry>\r
+struct topological_dimension\r
+ : core_dispatch::top_dim<typename tag<Geometry>::type> {};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+//\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP\r
+\r
+#include <boost/geometry.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// TODO: this is shared with sectionalize, move to somewhere else (assign?)\r
+template <typename Box, typename Value>\r
+inline void enlarge_box(Box& box, Value value)\r
+{\r
+ geometry::set<0, 0>(box, geometry::get<0, 0>(box) - value);\r
+ geometry::set<0, 1>(box, geometry::get<0, 1>(box) - value);\r
+ geometry::set<1, 0>(box, geometry::get<1, 0>(box) + value);\r
+ geometry::set<1, 1>(box, geometry::get<1, 1>(box) + value);\r
+}\r
+\r
+// TODO: when this might be moved outside extensions it should of course\r
+// input/output a Geometry, instead of a WKT\r
+template <typename Geometry, typename Value>\r
+inline std::string inverse(std::string const& wkt, Value margin)\r
+{\r
+ Geometry geometry;\r
+ read_wkt(wkt, geometry);\r
+\r
+ geometry::correct(geometry);\r
+\r
+ geometry::model::box<typename point_type<Geometry>::type> env;\r
+ geometry::envelope(geometry, env);\r
+\r
+ // Make its envelope a bit larger\r
+ enlarge_box(env, margin);\r
+\r
+ Geometry env_as_polygon;\r
+ geometry::convert(env, env_as_polygon);\r
+\r
+ Geometry inversed_result;\r
+ geometry::difference(env_as_polygon, geometry, inversed_result);\r
+\r
+ std::ostringstream out;\r
+\r
+ out << geometry::wkt(inversed_result);\r
+ return out.str();\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_INVERSE_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2016, Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_FORMULAS_SPHERICAL_HPP\r
+#define BOOST_GEOMETRY_FORMULAS_SPHERICAL_HPP\r
+\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+\r
+//#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/arithmetic/cross_product.hpp>\r
+#include <boost/geometry/arithmetic/dot_product.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+ \r
+namespace formula {\r
+\r
+template <typename Point3d, typename PointSph>\r
+static inline Point3d sph_to_cart3d(PointSph const& point_sph)\r
+{\r
+ typedef typename coordinate_type<Point3d>::type calc_t;\r
+\r
+ Point3d res;\r
+\r
+ calc_t lon = get_as_radian<0>(point_sph);\r
+ calc_t lat = get_as_radian<1>(point_sph);\r
+\r
+ calc_t const cos_lat = cos(lat);\r
+ set<0>(res, cos_lat * cos(lon));\r
+ set<1>(res, cos_lat * sin(lon));\r
+ set<2>(res, sin(lat));\r
+\r
+ return res;\r
+}\r
+\r
+template <typename PointSph, typename Point3d>\r
+static inline PointSph cart3d_to_sph(Point3d const& point_3d)\r
+{\r
+ typedef typename coordinate_type<PointSph>::type coord_t;\r
+ typedef typename coordinate_type<Point3d>::type calc_t;\r
+\r
+ PointSph res;\r
+\r
+ calc_t const x = get<0>(point_3d);\r
+ calc_t const y = get<1>(point_3d);\r
+ calc_t const z = get<2>(point_3d);\r
+\r
+ set_from_radian<0>(res, atan2(y, x));\r
+ set_from_radian<1>(res, asin(z));\r
+\r
+ coord_t lon = get<0>(res);\r
+ coord_t lat = get<1>(res);\r
+\r
+ math::normalize_spheroidal_coordinates\r
+ <\r
+ typename coordinate_system<PointSph>::type::units,\r
+ coord_t\r
+ >(lon, lat);\r
+\r
+ set<0>(res, lon);\r
+ set<1>(res, lat);\r
+\r
+ return res;\r
+}\r
+\r
+// -1 right\r
+// 1 left\r
+// 0 on\r
+template <typename Point3d1, typename Point3d2>\r
+static inline int sph_side_value(Point3d1 const& norm, Point3d2 const& pt)\r
+{\r
+ typedef typename select_coordinate_type<Point3d1, Point3d2>::type calc_t;\r
+ calc_t c0 = 0;\r
+ calc_t d = dot_product(norm, pt);\r
+ return math::equals(d, c0) ? 0\r
+ : d > c0 ? 1\r
+ : -1; // d < 0\r
+}\r
+\r
+} // namespace formula\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_FORMULAS_SPHERICAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010 Alfredo Correa\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_HPP\r
+\r
+\r
+#ifdef BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_TAG_DEFINED\r
+#error Include either "boost_array_as_point" or \\r
+ "boost_array_as_linestring" or "boost_array_as_ring" \\r
+ or "boost_array_as_multi_point" to adapt a boost_array\r
+#endif\r
+\r
+#define BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_TAG_DEFINED\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/type_traits/is_arithmetic.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/array.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+// Create class and specialization to indicate the tag\r
+// for normal cases and the case that the type of the c-array is arithmetic\r
+template <bool>\r
+struct boost_array_tag\r
+{\r
+ typedef geometry_not_recognized_tag type;\r
+};\r
+\r
+\r
+template <>\r
+struct boost_array_tag<true>\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+// Assign the point-tag, preventing arrays of points getting a point-tag\r
+template <typename CoordinateType, std::size_t DimensionCount>\r
+struct tag<boost::array<CoordinateType, DimensionCount> >\r
+ : detail::boost_array_tag<boost::is_arithmetic<CoordinateType>::value> {};\r
+\r
+\r
+template <typename CoordinateType, std::size_t DimensionCount>\r
+struct coordinate_type<boost::array<CoordinateType, DimensionCount> >\r
+{\r
+ typedef CoordinateType type;\r
+};\r
+\r
+\r
+template <typename CoordinateType, std::size_t DimensionCount>\r
+struct dimension<boost::array<CoordinateType, DimensionCount> >: boost::mpl::int_<DimensionCount> {};\r
+\r
+\r
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>\r
+struct access<boost::array<CoordinateType, DimensionCount>, Dimension>\r
+{\r
+ static inline CoordinateType get(boost::array<CoordinateType, DimensionCount> const& a)\r
+ {\r
+ return a[Dimension];\r
+ }\r
+\r
+ static inline void set(boost::array<CoordinateType, DimensionCount>& a,\r
+ CoordinateType const& value)\r
+ {\r
+ a[Dimension] = value;\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#define BOOST_GEOMETRY_REGISTER_BOOST_ARRAY_CS(CoordinateSystem) \\r
+ namespace boost { namespace geometry { namespace traits { \\r
+ template <class T, std::size_t N> \\r
+ struct coordinate_system<boost::array<T, N> > \\r
+ { \\r
+ typedef CoordinateSystem type; \\r
+ }; \\r
+ }}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2015 Akira Takahashi\r
+// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/core/enable_if.hpp>\r
+\r
+#include <boost/fusion/include/is_sequence.hpp>\r
+#include <boost/fusion/include/size.hpp>\r
+#include <boost/fusion/include/tag_of.hpp>\r
+#include <boost/fusion/include/front.hpp>\r
+#include <boost/fusion/include/at.hpp>\r
+#include <boost/fusion/mpl.hpp>\r
+\r
+#include <boost/mpl/and.hpp>\r
+#include <boost/mpl/count_if.hpp>\r
+#include <boost/mpl/front.hpp>\r
+#include <boost/mpl/placeholders.hpp>\r
+#include <boost/mpl/pop_front.hpp>\r
+#include <boost/mpl/size.hpp>\r
+\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace fusion_adapt_detail\r
+{\r
+\r
+template <class Sequence>\r
+struct all_same :\r
+ boost::mpl::bool_<\r
+ boost::mpl::count_if<\r
+ Sequence,\r
+ boost::is_same<\r
+ typename boost::mpl::front<Sequence>::type,\r
+ boost::mpl::_\r
+ >\r
+ >::value == boost::mpl::size<Sequence>::value\r
+ >\r
+{};\r
+\r
+template <class Sequence>\r
+struct is_coordinate_size : boost::mpl::bool_<\r
+ boost::fusion::result_of::size<Sequence>::value == 2 ||\r
+ boost::fusion::result_of::size<Sequence>::value == 3> {};\r
+\r
+template<typename Sequence>\r
+struct is_fusion_sequence\r
+ : boost::mpl::and_<boost::fusion::traits::is_sequence<Sequence>,\r
+ fusion_adapt_detail::is_coordinate_size<Sequence>,\r
+ fusion_adapt_detail::all_same<Sequence> >\r
+{};\r
+\r
+\r
+} // namespace fusion_adapt_detail\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+// Boost Fusion Sequence, 2D or 3D\r
+template <typename Sequence>\r
+struct coordinate_type\r
+ <\r
+ Sequence,\r
+ typename boost::enable_if\r
+ <\r
+ fusion_adapt_detail::is_fusion_sequence<Sequence>\r
+ >::type\r
+ >\r
+{\r
+ typedef typename boost::mpl::front<Sequence>::type type;\r
+};\r
+\r
+\r
+template <typename Sequence>\r
+struct dimension\r
+ <\r
+ Sequence,\r
+ typename boost::enable_if\r
+ <\r
+ fusion_adapt_detail::is_fusion_sequence<Sequence>\r
+ >::type\r
+ > : boost::mpl::size<Sequence>\r
+{};\r
+\r
+\r
+template <typename Sequence, std::size_t Dimension>\r
+struct access\r
+ <\r
+ Sequence,\r
+ Dimension,\r
+ typename boost::enable_if\r
+ <\r
+ fusion_adapt_detail::is_fusion_sequence<Sequence>\r
+ >::type\r
+ >\r
+{\r
+ typedef typename coordinate_type<Sequence>::type ctype;\r
+\r
+ static inline ctype get(Sequence const& point)\r
+ {\r
+ return boost::fusion::at_c<Dimension>(point);\r
+ }\r
+\r
+ template <class CoordinateType>\r
+ static inline void set(Sequence& point, CoordinateType const& value)\r
+ {\r
+ boost::fusion::at_c<Dimension>(point) = value;\r
+ }\r
+};\r
+\r
+\r
+template <typename Sequence>\r
+struct tag\r
+ <\r
+ Sequence,\r
+ typename boost::enable_if\r
+ <\r
+ fusion_adapt_detail::is_fusion_sequence<Sequence>\r
+ >::type\r
+ >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+// Convenience registration macro to bind a Fusion sequence to a CS\r
+#define BOOST_GEOMETRY_REGISTER_BOOST_FUSION_CS(CoordinateSystem) \\r
+ namespace boost { namespace geometry { namespace traits { \\r
+ template <typename Sequence> \\r
+ struct coordinate_system \\r
+ < \\r
+ Sequence, \\r
+ typename boost::enable_if \\r
+ < \\r
+ fusion_adapt_detail::is_fusion_sequence<Sequence> \\r
+ >::type \\r
+ > \\r
+ { typedef CoordinateSystem type; }; \\r
+ }}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HPP\r
+\r
+#include <boost/geometry/geometries/adapted/boost_polygon/point.hpp>\r
+#include <boost/geometry/geometries/adapted/boost_polygon/box.hpp>\r
+#include <boost/geometry/geometries/adapted/boost_polygon/ring.hpp>\r
+#include <boost/geometry/geometries/adapted/boost_polygon/polygon.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_BOX_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_BOX_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::rectangle_data -> boost::geometry::box\r
+\r
+\r
+#include <boost/polygon/polygon.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+template <typename CoordinateType>\r
+struct tag<boost::polygon::rectangle_data<CoordinateType> >\r
+{\r
+ typedef box_tag type;\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct point_type<boost::polygon::rectangle_data<CoordinateType> >\r
+{\r
+ // Not sure what to do here. Boost.Polygon's rectangle does NOT define its\r
+ // point_type (but uses it...)\r
+ typedef boost::polygon::point_data<CoordinateType> type;\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct indexed_access\r
+<\r
+ boost::polygon::rectangle_data<CoordinateType>,\r
+ min_corner, 0\r
+>\r
+{\r
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;\r
+\r
+ static inline CoordinateType get(box_type const& b)\r
+ {\r
+ return boost::polygon::xl(b);\r
+ }\r
+\r
+ static inline void set(box_type& b, CoordinateType const& value)\r
+ {\r
+ boost::polygon::xl(b, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct indexed_access\r
+<\r
+ boost::polygon::rectangle_data<CoordinateType>,\r
+ min_corner, 1\r
+>\r
+{\r
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;\r
+\r
+ static inline CoordinateType get(box_type const& b)\r
+ {\r
+ return boost::polygon::yl(b);\r
+ }\r
+\r
+ static inline void set(box_type& b, CoordinateType const& value)\r
+ {\r
+ boost::polygon::yl(b, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct indexed_access\r
+<\r
+ boost::polygon::rectangle_data<CoordinateType>,\r
+ max_corner, 0\r
+>\r
+{\r
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;\r
+\r
+ static inline CoordinateType get(box_type const& b)\r
+ {\r
+ return boost::polygon::xh(b);\r
+ }\r
+\r
+ static inline void set(box_type& b, CoordinateType const& value)\r
+ {\r
+ boost::polygon::xh(b, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct indexed_access\r
+<\r
+ boost::polygon::rectangle_data<CoordinateType>,\r
+ max_corner, 1\r
+>\r
+{\r
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;\r
+\r
+ static inline CoordinateType get(box_type const& b)\r
+ {\r
+ return boost::polygon::yh(b);\r
+ }\r
+\r
+ static inline void set(box_type& b, CoordinateType const& value)\r
+ {\r
+ boost::polygon::yh(b, value);\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLE_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLE_ITERATOR_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon\r
+// hole_iterator -> returning ring_proxy's instead of normal polygon_data\r
+\r
+#include <boost/polygon/polygon.hpp>\r
+\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace adapt { namespace bp\r
+{\r
+\r
+\r
+template <typename Polygon, typename RingProxy>\r
+class hole_iterator\r
+ : public ::boost::iterator_facade\r
+ <\r
+ hole_iterator<Polygon, RingProxy>,\r
+ RingProxy, // value type\r
+ boost::forward_traversal_tag,\r
+ RingProxy // reference type\r
+ >\r
+{\r
+public :\r
+ typedef typename boost::polygon::polygon_with_holes_traits\r
+ <\r
+ Polygon\r
+ >::iterator_holes_type ith_type;\r
+\r
+ explicit inline hole_iterator(Polygon& polygon, ith_type const it)\r
+ : m_polygon(polygon)\r
+ , m_base(it)\r
+ {\r
+ }\r
+\r
+ typedef std::ptrdiff_t difference_type;\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ inline RingProxy dereference() const\r
+ {\r
+ return RingProxy(m_polygon, this->m_base);\r
+ }\r
+\r
+ inline void increment() { ++m_base; }\r
+ inline void decrement() { --m_base; }\r
+ inline void advance(difference_type n)\r
+ {\r
+ for (int i = 0; i < n; i++)\r
+ {\r
+ ++m_base;\r
+ }\r
+ }\r
+\r
+ inline bool equal(hole_iterator<Polygon, RingProxy> const& other) const\r
+ {\r
+ return this->m_base == other.m_base;\r
+ }\r
+\r
+ Polygon& m_polygon;\r
+ ith_type m_base;\r
+};\r
+\r
+\r
+}}}}\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLE_ITERATOR_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLES_PROXY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLES_PROXY_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon\r
+// pair{begin_holes, begin_holes} -> interior_proxy\r
+\r
+#include <boost/polygon/polygon.hpp>\r
+\r
+#include <boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp>\r
+#include <boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace adapt { namespace bp\r
+{\r
+\r
+\r
+// Polygon should implement the boost::polygon::polygon_with_holes_concept\r
+// Specify constness in the template parameter if necessary\r
+template<typename Polygon>\r
+struct holes_proxy\r
+{\r
+ typedef ring_proxy\r
+ <\r
+ typename boost::mpl::if_\r
+ <\r
+ typename boost::is_const<Polygon>,\r
+ Polygon const,\r
+ Polygon\r
+ >::type\r
+ > proxy_type;\r
+ typedef hole_iterator<Polygon, proxy_type> iterator_type;\r
+\r
+ // The next line does not work probably because coordinate_type is part of the\r
+ // polygon_traits, but not of the polygon_with_holes_traits\r
+ // typedef typename boost::polygon::polygon_traits<Polygon>::coordinate_type coordinate_type;\r
+\r
+ // So we use:\r
+ typedef typename Polygon::coordinate_type coordinate_type;\r
+\r
+ inline holes_proxy(Polygon& p)\r
+ : polygon(p)\r
+ {}\r
+\r
+ inline void clear()\r
+ {\r
+ Polygon empty;\r
+ // Clear the holes\r
+ polygon.set_holes\r
+ (\r
+ boost::polygon::begin_holes(empty),\r
+ boost::polygon::end_holes(empty)\r
+ );\r
+ }\r
+\r
+ inline void resize(std::size_t new_size)\r
+ {\r
+ std::vector<boost::polygon::polygon_data<coordinate_type> > temporary_copy\r
+ (\r
+ boost::polygon::begin_holes(polygon),\r
+ boost::polygon::end_holes(polygon)\r
+ );\r
+ temporary_copy.resize(new_size);\r
+ polygon.set_holes(temporary_copy.begin(), temporary_copy.end());\r
+ }\r
+\r
+ template <typename Ring>\r
+ inline void push_back(Ring const& ring)\r
+ {\r
+ std::vector<boost::polygon::polygon_data<coordinate_type> > temporary_copy\r
+ (\r
+ boost::polygon::begin_holes(polygon),\r
+ boost::polygon::end_holes(polygon)\r
+ );\r
+ boost::polygon::polygon_data<coordinate_type> added;\r
+ boost::polygon::set_points(added, ring.begin(), ring.end());\r
+ temporary_copy.push_back(added);\r
+ polygon.set_holes(temporary_copy.begin(), temporary_copy.end());\r
+ }\r
+\r
+\r
+ Polygon& polygon;\r
+};\r
+\r
+\r
+// Support holes_proxy for Boost.Range ADP\r
+\r
+// Const versions\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type\r
+ range_begin(boost::geometry::adapt::bp::holes_proxy<Polygon const> const& proxy)\r
+{\r
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type\r
+ begin(proxy.polygon, boost::polygon::begin_holes(proxy.polygon));\r
+ return begin;\r
+}\r
+\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type\r
+ range_end(boost::geometry::adapt::bp::holes_proxy<Polygon const> const& proxy)\r
+{\r
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type\r
+ end(proxy.polygon, boost::polygon::end_holes(proxy.polygon));\r
+ return end;\r
+}\r
+\r
+// Mutable versions\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type\r
+ range_begin(boost::geometry::adapt::bp::holes_proxy<Polygon>& proxy)\r
+{\r
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type\r
+ begin(proxy.polygon, boost::polygon::begin_holes(proxy.polygon));\r
+ return begin;\r
+}\r
+\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type\r
+ range_end(boost::geometry::adapt::bp::holes_proxy<Polygon>& proxy)\r
+{\r
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type\r
+ end(proxy.polygon, boost::polygon::end_holes(proxy.polygon));\r
+ return end;\r
+}\r
+\r
+\r
+}}\r
+\r
+namespace traits\r
+{\r
+\r
+template <typename Polygon>\r
+struct rvalue_type<adapt::bp::holes_proxy<Polygon> >\r
+{\r
+ typedef adapt::bp::holes_proxy<Polygon> type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct clear<adapt::bp::holes_proxy<Polygon> >\r
+{\r
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy)\r
+ {\r
+ proxy.clear();\r
+ }\r
+};\r
+\r
+template <typename Polygon>\r
+struct resize<adapt::bp::holes_proxy<Polygon> >\r
+{\r
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy, std::size_t new_size)\r
+ {\r
+ proxy.resize(new_size);\r
+ }\r
+};\r
+\r
+template <typename Polygon>\r
+struct push_back<adapt::bp::holes_proxy<Polygon> >\r
+{\r
+ template <typename Ring>\r
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy, Ring const& ring)\r
+ {\r
+ proxy.push_back(ring);\r
+ }\r
+};\r
+\r
+\r
+\r
+} // namespace traits\r
+\r
+\r
+}}\r
+\r
+\r
+// Specialize holes_proxy for Boost.Range\r
+namespace boost\r
+{\r
+ template<typename Polygon>\r
+ struct range_mutable_iterator<geometry::adapt::bp::holes_proxy<Polygon> >\r
+ {\r
+ typedef typename geometry::adapt::bp::holes_proxy<Polygon>::iterator_type type;\r
+ };\r
+\r
+ template<typename Polygon>\r
+ struct range_const_iterator<geometry::adapt::bp::holes_proxy<Polygon> >\r
+ {\r
+ typedef typename geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type type;\r
+ };\r
+\r
+} // namespace boost\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLES_PROXY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::point_data -> boost::geometry::point\r
+\r
+\r
+#include <boost/polygon/polygon.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+template <typename CoordinateType>\r
+struct tag<boost::polygon::point_data<CoordinateType> >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct coordinate_type<boost::polygon::point_data<CoordinateType> >\r
+{\r
+ typedef CoordinateType type;\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct coordinate_system<boost::polygon::point_data<CoordinateType> >\r
+{\r
+ typedef cs::cartesian type;\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct dimension<boost::polygon::point_data<CoordinateType> >\r
+ : boost::mpl::int_<2>\r
+{};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct access<boost::polygon::point_data<CoordinateType>, 0>\r
+{\r
+ typedef boost::polygon::point_data<CoordinateType> point_type;\r
+\r
+ static inline CoordinateType get(point_type const& p)\r
+ {\r
+ return p.x();\r
+ }\r
+\r
+ static inline void set(point_type& p, CoordinateType const& value)\r
+ {\r
+ p.x(value);\r
+ }\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct access<boost::polygon::point_data<CoordinateType>, 1>\r
+{\r
+ typedef boost::polygon::point_data<CoordinateType> point_type;\r
+\r
+ static inline CoordinateType get(point_type const& p)\r
+ {\r
+ return p.y();\r
+ }\r
+\r
+ static inline void set(point_type& p, CoordinateType const& value)\r
+ {\r
+ p.y(value);\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POLYGON_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POLYGON_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon\r
+\r
+#include <boost/polygon/polygon.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+\r
+#include <boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp>\r
+#include <boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp>\r
+#include <boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename CoordinateType>\r
+struct tag<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef polygon_tag type;\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct ring_const_type<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef adapt::bp::ring_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> const> type;\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct ring_mutable_type<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef adapt::bp::ring_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> > type;\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct interior_const_type<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef adapt::bp::holes_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> const> type;\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct interior_mutable_type<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef adapt::bp::holes_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> > type;\r
+};\r
+\r
+\r
+template <typename CoordinateType>\r
+struct exterior_ring<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef boost::polygon::polygon_with_holes_data<CoordinateType> polygon_type;\r
+ typedef adapt::bp::ring_proxy<polygon_type> proxy;\r
+ typedef adapt::bp::ring_proxy<polygon_type const> const_proxy;\r
+\r
+ static inline proxy get(polygon_type& p)\r
+ {\r
+ return proxy(p);\r
+ }\r
+\r
+ static inline const_proxy get(polygon_type const& p)\r
+ {\r
+ return const_proxy(p);\r
+ }\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct interior_rings<boost::polygon::polygon_with_holes_data<CoordinateType> >\r
+{\r
+ typedef boost::polygon::polygon_with_holes_data<CoordinateType> polygon_type;\r
+ typedef adapt::bp::holes_proxy<polygon_type> proxy;\r
+ typedef adapt::bp::holes_proxy<polygon_type const> const_proxy;\r
+\r
+ static inline proxy get(polygon_type& p)\r
+ {\r
+ return proxy(p);\r
+ }\r
+\r
+ static inline const_proxy get(polygon_type const& p)\r
+ {\r
+ return const_proxy(p);\r
+ }\r
+};\r
+\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POLYGON_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::polygon_data -> boost::geometry::ring\r
+\r
+#include <cstddef>\r
+#include <boost/polygon/polygon.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template <typename CoordinateType>\r
+struct tag<boost::polygon::polygon_data<CoordinateType> >\r
+{\r
+ typedef ring_tag type;\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct clear<boost::polygon::polygon_data<CoordinateType> >\r
+{\r
+ static inline void apply(boost::polygon::polygon_data<CoordinateType>& data)\r
+ {\r
+ // There is no "clear" function but we can assign\r
+ // a newly (and therefore empty) constructed polygon\r
+ boost::polygon::assign(data, boost::polygon::polygon_data<CoordinateType>());\r
+ }\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct push_back<boost::polygon::polygon_data<CoordinateType> >\r
+{\r
+ typedef boost::polygon::point_data<CoordinateType> point_type;\r
+\r
+ static inline void apply(boost::polygon::polygon_data<CoordinateType>& data,\r
+ point_type const& point)\r
+ {\r
+ // Boost.Polygon's polygons are not appendable. So create a temporary vector,\r
+ // add a record and set it to the original. Of course: this is not efficient.\r
+ // But there seems no other way (without using a wrapper)\r
+ std::vector<point_type> temporary_vector\r
+ (\r
+ boost::polygon::begin_points(data),\r
+ boost::polygon::end_points(data)\r
+ );\r
+ temporary_vector.push_back(point);\r
+ data.set(temporary_vector.begin(), temporary_vector.end());\r
+ }\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct resize<boost::polygon::polygon_data<CoordinateType> >\r
+{\r
+ typedef boost::polygon::point_data<CoordinateType> point_type;\r
+\r
+ static inline void apply(boost::polygon::polygon_data<CoordinateType>& data,\r
+ std::size_t new_size)\r
+ {\r
+ // Boost.Polygon's polygons are not resizable. So create a temporary vector,\r
+ // resize it and set it to the original. Of course: this is not efficient.\r
+ // But there seems no other way (without using a wrapper)\r
+ std::vector<point_type> temporary_vector\r
+ (\r
+ boost::polygon::begin_points(data),\r
+ boost::polygon::end_points(data)\r
+ );\r
+ temporary_vector.resize(new_size);\r
+ data.set(temporary_vector.begin(), temporary_vector.end());\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+// Adapt Boost.Polygon's polygon_data to Boost.Range\r
+// This just translates to\r
+// polygon_data.begin() and polygon_data.end()\r
+namespace boost\r
+{\r
+ template<typename CoordinateType>\r
+ struct range_mutable_iterator<boost::polygon::polygon_data<CoordinateType> >\r
+ {\r
+ typedef typename boost::polygon::polygon_traits\r
+ <\r
+ boost::polygon::polygon_data<CoordinateType>\r
+ >::iterator_type type;\r
+ };\r
+\r
+ template<typename CoordinateType>\r
+ struct range_const_iterator<boost::polygon::polygon_data<CoordinateType> >\r
+ {\r
+ typedef typename boost::polygon::polygon_traits\r
+ <\r
+ boost::polygon::polygon_data<CoordinateType>\r
+ >::iterator_type type;\r
+ };\r
+\r
+ template<typename CoordinateType>\r
+ struct range_size<boost::polygon::polygon_data<CoordinateType> >\r
+ {\r
+ typedef std::size_t type;\r
+ };\r
+\r
+} // namespace boost\r
+\r
+\r
+// Support Boost.Polygon's polygon_data for Boost.Range ADP\r
+namespace boost { namespace polygon\r
+{\r
+\r
+template<typename CoordinateType>\r
+inline typename polygon_traits\r
+ <\r
+ polygon_data<CoordinateType>\r
+ >::iterator_type range_begin(polygon_data<CoordinateType>& polygon)\r
+{\r
+ return polygon.begin();\r
+}\r
+\r
+template<typename CoordinateType>\r
+inline typename polygon_traits\r
+ <\r
+ polygon_data<CoordinateType>\r
+ >::iterator_type range_begin(polygon_data<CoordinateType> const& polygon)\r
+{\r
+ return polygon.begin();\r
+}\r
+\r
+template<typename CoordinateType>\r
+inline typename polygon_traits\r
+ <\r
+ polygon_data<CoordinateType>\r
+ >::iterator_type range_end(polygon_data<CoordinateType>& polygon)\r
+{\r
+ return polygon.end();\r
+}\r
+\r
+template<typename CoordinateType>\r
+inline typename polygon_traits\r
+ <\r
+ polygon_data<CoordinateType>\r
+ >::iterator_type range_end(polygon_data<CoordinateType> const& polygon)\r
+{\r
+ return polygon.end();\r
+}\r
+\r
+template<typename CoordinateType>\r
+inline std::size_t range_calculate_size(polygon_data<CoordinateType> const& polygon)\r
+{\r
+ return polygon.size();\r
+}\r
+\r
+}}\r
+\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP\r
+\r
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry\r
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon\r
+// pair{begin_points, end_points} -> ring_proxy\r
+\r
+#include <boost/polygon/polygon.hpp>\r
+#include <boost/range.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace adapt { namespace bp\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+template <bool Mutable>\r
+struct modify\r
+{};\r
+\r
+template <>\r
+struct modify<true>\r
+{\r
+ template <typename Ring, typename Point>\r
+ static inline void push_back(Ring& ring, Point const& point)\r
+ {\r
+ // Boost.Polygon's polygons are not appendable. So create a temporary vector,\r
+ // add a record and set it to the original. Of course: this is not efficient.\r
+ // But there seems no other way (without using a wrapper)\r
+ std::vector<Point> temporary_vector\r
+ (\r
+ boost::polygon::begin_points(ring),\r
+ boost::polygon::end_points(ring)\r
+ );\r
+ temporary_vector.push_back(point);\r
+ boost::polygon::set_points(ring, temporary_vector.begin(), temporary_vector.end());\r
+ }\r
+\r
+};\r
+\r
+template <>\r
+struct modify<false>\r
+{\r
+ template <typename Ring, typename Point>\r
+ static inline void push_back(Ring& /*ring*/, Point const& /*point*/)\r
+ {\r
+ }\r
+\r
+};\r
+\r
+\r
+}\r
+\r
+\r
+// Polygon should implement the boost::polygon::polygon_with_holes_concept\r
+// Specify constness in the template parameter if necessary\r
+template<typename Polygon>\r
+class ring_proxy\r
+{\r
+public :\r
+ typedef typename boost::polygon::polygon_traits\r
+ <\r
+ typename boost::remove_const<Polygon>::type\r
+ >::iterator_type iterator_type;\r
+\r
+ typedef typename boost::polygon::polygon_with_holes_traits\r
+ <\r
+ typename boost::remove_const<Polygon>::type\r
+ >::iterator_holes_type hole_iterator_type;\r
+\r
+ static const bool is_mutable = !boost::is_const<Polygon>::type::value;\r
+\r
+ inline ring_proxy(Polygon& p)\r
+ : m_polygon_pointer(&p)\r
+ , m_do_hole(false)\r
+ {}\r
+\r
+ // Constructor used from hole_iterator\r
+ inline ring_proxy(Polygon& p, hole_iterator_type hole_it)\r
+ : m_polygon_pointer(&p)\r
+ , m_do_hole(true)\r
+ , m_hole_it(hole_it)\r
+ {}\r
+\r
+ // Default constructor, for mutable polygons / appending (interior) rings\r
+ inline ring_proxy()\r
+ : m_polygon_pointer(&m_polygon_for_default_constructor)\r
+ , m_do_hole(false)\r
+ {}\r
+\r
+\r
+ iterator_type begin() const\r
+ {\r
+ return m_do_hole\r
+ ? boost::polygon::begin_points(*m_hole_it)\r
+ : boost::polygon::begin_points(*m_polygon_pointer)\r
+ ;\r
+ }\r
+\r
+ iterator_type begin()\r
+ {\r
+ return m_do_hole\r
+ ? boost::polygon::begin_points(*m_hole_it)\r
+ : boost::polygon::begin_points(*m_polygon_pointer)\r
+ ;\r
+ }\r
+\r
+ iterator_type end() const\r
+ {\r
+ return m_do_hole\r
+ ? boost::polygon::end_points(*m_hole_it)\r
+ : boost::polygon::end_points(*m_polygon_pointer)\r
+ ;\r
+ }\r
+\r
+ iterator_type end()\r
+ {\r
+ return m_do_hole\r
+ ? boost::polygon::end_points(*m_hole_it)\r
+ : boost::polygon::end_points(*m_polygon_pointer)\r
+ ;\r
+ }\r
+\r
+ // Mutable\r
+ void clear()\r
+ {\r
+ Polygon p;\r
+ if (m_do_hole)\r
+ {\r
+ // Does NOT work see comment above\r
+ }\r
+ else\r
+ {\r
+ boost::polygon::set_points(*m_polygon_pointer,\r
+ boost::polygon::begin_points(p),\r
+ boost::polygon::end_points(p));\r
+ }\r
+ }\r
+\r
+ void resize(std::size_t /*new_size*/)\r
+ {\r
+ if (m_do_hole)\r
+ {\r
+ // Does NOT work see comment above\r
+ }\r
+ else\r
+ {\r
+ // TODO: implement this by resizing the container\r
+ }\r
+ }\r
+\r
+\r
+\r
+ template <typename Point>\r
+ void push_back(Point const& point)\r
+ {\r
+ if (m_do_hole)\r
+ {\r
+ //detail::modify<is_mutable>::push_back(*m_hole_it, point);\r
+ //std::cout << "HOLE: " << typeid(*m_hole_it).name() << std::endl;\r
+ //std::cout << "HOLE: " << typeid(m_hole_it).name() << std::endl;\r
+ //std::cout << "HOLE: " << typeid(hole_iterator_type).name() << std::endl;\r
+\r
+ // Note, ths does NOT work because hole_iterator_type is defined\r
+ // as a const_iterator by Boost.Polygon\r
+\r
+ }\r
+ else\r
+ {\r
+ detail::modify<is_mutable>::push_back(*m_polygon_pointer, point);\r
+ }\r
+ }\r
+\r
+private :\r
+ Polygon* m_polygon_pointer;\r
+ bool m_do_hole;\r
+ hole_iterator_type m_hole_it;\r
+\r
+ Polygon m_polygon_for_default_constructor;\r
+};\r
+\r
+\r
+\r
+\r
+// Support geometry::adapt::bp::ring_proxy for Boost.Range ADP\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon>::iterator_type\r
+ range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon>& proxy)\r
+{\r
+ return proxy.begin();\r
+}\r
+\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type\r
+ range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon const> const& proxy)\r
+{\r
+ return proxy.begin();\r
+}\r
+\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon>::iterator_type\r
+ range_end(boost::geometry::adapt::bp::ring_proxy<Polygon>& proxy)\r
+{\r
+ return proxy.end();\r
+}\r
+\r
+template<typename Polygon>\r
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type\r
+ range_end(boost::geometry::adapt::bp::ring_proxy<Polygon const> const& proxy)\r
+{\r
+ return proxy.end();\r
+}\r
+\r
+\r
+\r
+\r
+}} // namespace adapt::bp\r
+\r
+\r
+namespace traits\r
+{\r
+\r
+template <typename Polygon>\r
+struct tag<adapt::bp::ring_proxy<Polygon> >\r
+{\r
+ typedef ring_tag type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct rvalue_type<adapt::bp::ring_proxy<Polygon> >\r
+{\r
+ typedef adapt::bp::ring_proxy<Polygon> type;\r
+};\r
+\r
+template <typename Polygon>\r
+struct clear<adapt::bp::ring_proxy<Polygon> >\r
+{\r
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy)\r
+ {\r
+ proxy.clear();\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct resize<adapt::bp::ring_proxy<Polygon> >\r
+{\r
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy, std::size_t new_size)\r
+ {\r
+ proxy.resize(new_size);\r
+ }\r
+};\r
+\r
+template <typename Polygon>\r
+struct push_back<adapt::bp::ring_proxy<Polygon> >\r
+{\r
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy,\r
+ typename boost::polygon::polygon_traits<Polygon>::point_type const& point)\r
+ {\r
+ proxy.push_back(point);\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+\r
+}} // namespace boost::geometry\r
+\r
+// Specialize ring_proxy for Boost.Range\r
+namespace boost\r
+{\r
+ template<typename Polygon>\r
+ struct range_mutable_iterator<geometry::adapt::bp::ring_proxy<Polygon> >\r
+ {\r
+ typedef typename geometry::adapt::bp::ring_proxy<Polygon>::iterator_type type;\r
+ };\r
+\r
+ template<typename Polygon>\r
+ struct range_const_iterator<geometry::adapt::bp::ring_proxy<Polygon> >\r
+ {\r
+ typedef typename geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type type;\r
+ };\r
+\r
+} // namespace boost\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_ADJACENT_FILTERED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_ADJACENT_FILTERED_HPP\r
+\r
+\r
+#include <boost/range/adaptor/adjacent_filtered.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template<typename Filter, typename Geometry, bool DefaultPass>\r
+#if BOOST_VERSION > 104500\r
+struct tag<boost::adjacent_filtered_range<Filter, Geometry, DefaultPass> >\r
+#else\r
+struct tag<boost::range_detail::adjacent_filter_range<Filter, Geometry, DefaultPass> >\r
+#endif\r
+{\r
+ typedef typename geometry::tag<Geometry>::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_ADJACENT_FILTERED_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_FILTERED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_FILTERED_HPP\r
+\r
+\r
+#include <boost/range/adaptor/filtered.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template<typename Filter, typename Geometry>\r
+#if BOOST_VERSION > 104500\r
+struct tag<boost::filtered_range<Filter, Geometry> >\r
+#else\r
+struct tag<boost::range_detail::filter_range<Filter, Geometry> >\r
+#endif\r
+{\r
+ typedef typename geometry::tag<Geometry>::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_FILTERED_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_REVERSED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_REVERSED_HPP\r
+\r
+\r
+#include <boost/range/adaptor/reversed.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template<typename Geometry>\r
+#if BOOST_VERSION > 104500\r
+struct tag<boost::reversed_range<Geometry> >\r
+#else\r
+struct tag<boost::range_detail::reverse_range<Geometry> >\r
+#endif\r
+{\r
+ typedef typename geometry::tag<Geometry>::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_REVERSED_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_SLICED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_SLICED_HPP\r
+\r
+\r
+#include <boost/range/adaptor/sliced.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template<typename Geometry>\r
+struct tag<boost::adaptors::sliced_range<Geometry> >\r
+{\r
+ typedef typename geometry::tag<Geometry>::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_SLICED_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_STRIDED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_STRIDED_HPP\r
+\r
+\r
+#include <boost/range/adaptor/strided.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template<typename Geometry>\r
+struct tag<boost::strided_range<Geometry> >\r
+{\r
+ typedef typename geometry::tag<Geometry>::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_STRIDED_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_UNIQUED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_UNIQUED_HPP\r
+\r
+\r
+#include <boost/range/adaptor/uniqued.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace traits\r
+{\r
+\r
+template<typename Geometry>\r
+#if BOOST_VERSION > 104500\r
+struct tag<boost::uniqued_range<Geometry> >\r
+#else\r
+struct tag<boost::range_detail::unique_range<Geometry> >\r
+#endif\r
+{\r
+ typedef typename geometry::tag<Geometry>::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_UNIQUED_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_TUPLE_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_TUPLE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/tuple/tuple.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+template <typename T1, typename T2, typename T3, typename T4, typename T5,\r
+ typename T6, typename T7, typename T8, typename T9, typename T10>\r
+struct tag<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+\r
+template <typename T1, typename T2, typename T3, typename T4, typename T5,\r
+ typename T6, typename T7, typename T8, typename T9, typename T10>\r
+struct coordinate_type<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >\r
+{\r
+ typedef T1 type;\r
+};\r
+\r
+\r
+template <typename T1, typename T2, typename T3, typename T4, typename T5,\r
+ typename T6, typename T7, typename T8, typename T9, typename T10>\r
+struct dimension<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >\r
+ : boost::mpl::int_\r
+ <\r
+ boost::tuples::length\r
+ <\r
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>\r
+ >::value\r
+ >\r
+{};\r
+\r
+\r
+template <typename T1, typename T2, typename T3, typename T4, typename T5,\r
+ typename T6, typename T7, typename T8, typename T9, typename T10,\r
+ std::size_t Dimension>\r
+struct access\r
+ <\r
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>,\r
+ Dimension\r
+ >\r
+{\r
+ static inline T1 get(\r
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> const& point)\r
+ {\r
+ return point.template get<Dimension>();\r
+ }\r
+\r
+ static inline void set(\r
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& point,\r
+ T1 const& value)\r
+ {\r
+ point.template get<Dimension>() = value;\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+// Convenience registration macro to bind boost::tuple to a CS\r
+#define BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(CoordinateSystem) \\r
+ namespace boost { namespace geometry { namespace traits { \\r
+ template <typename T1, typename T2, typename T3, typename T4, typename T5, \\r
+ typename T6, typename T7, typename T8, typename T9, typename T10> \\r
+ struct coordinate_system<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> > \\r
+ { \\r
+ typedef CoordinateSystem type; \\r
+ }; \\r
+ }}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/type_traits/is_arithmetic.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+// Create class and specialization to indicate the tag\r
+// for normal cases and the case that the type of the c-array is arithmetic\r
+template <bool>\r
+struct c_array_tag\r
+{\r
+ typedef geometry_not_recognized_tag type;\r
+};\r
+\r
+\r
+template <>\r
+struct c_array_tag<true>\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+// Assign the point-tag, preventing arrays of points getting a point-tag\r
+template <typename CoordinateType, std::size_t DimensionCount>\r
+struct tag<CoordinateType[DimensionCount]>\r
+ : detail::c_array_tag<boost::is_arithmetic<CoordinateType>::value> {};\r
+\r
+\r
+template <typename CoordinateType, std::size_t DimensionCount>\r
+struct coordinate_type<CoordinateType[DimensionCount]>\r
+{\r
+ typedef CoordinateType type;\r
+};\r
+\r
+\r
+template <typename CoordinateType, std::size_t DimensionCount>\r
+struct dimension<CoordinateType[DimensionCount]>: boost::mpl::int_<DimensionCount> {};\r
+\r
+\r
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>\r
+struct access<CoordinateType[DimensionCount], Dimension>\r
+{\r
+ static inline CoordinateType get(CoordinateType const p[DimensionCount])\r
+ {\r
+ return p[Dimension];\r
+ }\r
+\r
+ static inline void set(CoordinateType p[DimensionCount],\r
+ CoordinateType const& value)\r
+ {\r
+ p[Dimension] = value;\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#define BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(CoordinateSystem) \\r
+ namespace boost { namespace geometry { namespace traits { \\r
+ template <typename T, std::size_t N> \\r
+ struct coordinate_system<T[N]> \\r
+ { \\r
+ typedef CoordinateSystem type; \\r
+ }; \\r
+ }}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP\r
+\r
+// Only possible if the std::pair is not used for iterator/pair\r
+// (maybe it is possible to avoid that by detecting in the other file\r
+// if an iterator was used in the pair)\r
+\r
+#ifdef BOOST_GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED\r
+#error Include only one headerfile to register tag for adapted std:: containers or iterator pair\r
+#endif\r
+\r
+#define BOOST_GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED\r
+\r
+\r
+#include <cstddef>\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+template <typename Point>\r
+struct tag<std::pair<Point, Point> >\r
+{\r
+ typedef segment_tag type;\r
+};\r
+\r
+template <typename Point>\r
+struct point_type<std::pair<Point, Point> >\r
+{\r
+ typedef Point type;\r
+};\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<std::pair<Point, Point>, 0, Dimension>\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(std::pair<Point, Point> const& s)\r
+ {\r
+ return geometry::get<Dimension>(s.first);\r
+ }\r
+\r
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(s.first, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<std::pair<Point, Point>, 1, Dimension>\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(std::pair<Point, Point> const& s)\r
+ {\r
+ return geometry::get<Dimension>(s.second);\r
+ }\r
+\r
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(s.second, value);\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_BOX_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_BOX_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/assert.hpp>\r
+#include <boost/config.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+#include <boost/geometry/core/assert.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+/*!\r
+\brief Class box: defines a box made of two describing points\r
+\ingroup geometries\r
+\details Box is always described by a min_corner() and a max_corner() point. If another\r
+ rectangle is used, use linear_ring or polygon.\r
+\note Boxes are for selections and for calculating the envelope of geometries. Not all algorithms\r
+are implemented for box. Boxes are also used in Spatial Indexes.\r
+\tparam Point point type. The box takes a point type as template parameter.\r
+The point type can be any point type.\r
+It can be 2D but can also be 3D or more dimensional.\r
+The box can also take a latlong point type as template parameter.\r
+\r
+\qbk{[include reference/geometries/box.qbk]}\r
+\qbk{before.synopsis, [heading Model of]}\r
+\qbk{before.synopsis, [link geometry.reference.concepts.concept_box Box Concept]}\r
+ */\r
+\r
+template<typename Point>\r
+class box\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+public:\r
+\r
+#if !defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)\r
+ /// \constructor_default_no_init\r
+ box() = default;\r
+#else\r
+ /// \constructor_default_no_init\r
+ inline box()\r
+ {}\r
+#endif\r
+#else // defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ inline box()\r
+ {\r
+ m_created = 1;\r
+ }\r
+ ~box()\r
+ {\r
+ m_created = 0;\r
+ }\r
+#endif\r
+\r
+ /*!\r
+ \brief Constructor taking the minimum corner point and the maximum corner point\r
+ */\r
+ inline box(Point const& min_corner, Point const& max_corner)\r
+ {\r
+ geometry::convert(min_corner, m_min_corner);\r
+ geometry::convert(max_corner, m_max_corner);\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ m_created = 1;\r
+#endif\r
+ }\r
+\r
+ inline Point const& min_corner() const\r
+ {\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ BOOST_GEOMETRY_ASSERT(m_created == 1);\r
+#endif\r
+ return m_min_corner;\r
+ }\r
+ inline Point const& max_corner() const\r
+ {\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ BOOST_GEOMETRY_ASSERT(m_created == 1);\r
+#endif\r
+ return m_max_corner;\r
+ }\r
+\r
+ inline Point& min_corner()\r
+ {\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ BOOST_GEOMETRY_ASSERT(m_created == 1);\r
+#endif\r
+ return m_min_corner;\r
+ }\r
+ inline Point& max_corner()\r
+ {\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ BOOST_GEOMETRY_ASSERT(m_created == 1);\r
+#endif\r
+ return m_max_corner;\r
+ }\r
+\r
+private:\r
+\r
+ Point m_min_corner;\r
+ Point m_max_corner;\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ int m_created;\r
+#endif\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+\r
+// Traits specializations for box above\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename Point>\r
+struct tag<model::box<Point> >\r
+{\r
+ typedef box_tag type;\r
+};\r
+\r
+template <typename Point>\r
+struct point_type<model::box<Point> >\r
+{\r
+ typedef Point type;\r
+};\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<model::box<Point>, min_corner, Dimension>\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(model::box<Point> const& b)\r
+ {\r
+ return geometry::get<Dimension>(b.min_corner());\r
+ }\r
+\r
+ static inline void set(model::box<Point>& b, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(b.min_corner(), value);\r
+ }\r
+};\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<model::box<Point>, max_corner, Dimension>\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(model::box<Point> const& b)\r
+ {\r
+ return geometry::get<Dimension>(b.max_corner());\r
+ }\r
+\r
+ static inline void set(model::box<Point>& b, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(b.max_corner(), value);\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief Box concept\r
+\ingroup concepts\r
+\par Formal definition:\r
+The box concept is defined as following:\r
+- there must be a specialization of traits::tag defining box_tag as type\r
+- there must be a specialization of traits::point_type to define the\r
+ underlying point type (even if it does not consist of points, it should define\r
+ this type, to indicate the points it can work with)\r
+- there must be a specialization of traits::indexed_access, per index\r
+ (min_corner, max_corner) and per dimension, with two functions:\r
+ - get to get a coordinate value\r
+ - set to set a coordinate value (this one is not checked for ConstBox)\r
+*/\r
+template <typename Geometry>\r
+class Box\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+\r
+ template\r
+ <\r
+ std::size_t Index,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+ >\r
+ struct dimension_checker\r
+ {\r
+ static void apply()\r
+ {\r
+ Geometry* b = 0;\r
+ geometry::set<Index, Dimension>(*b, geometry::get<Index, Dimension>(*b));\r
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();\r
+ }\r
+ };\r
+\r
+ template <std::size_t Index, std::size_t DimensionCount>\r
+ struct dimension_checker<Index, DimensionCount, DimensionCount>\r
+ {\r
+ static void apply() {}\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(Box)\r
+ {\r
+ static const std::size_t n = dimension<Geometry>::type::value;\r
+ dimension_checker<min_corner, 0, n>::apply();\r
+ dimension_checker<max_corner, 0, n>::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief Box concept (const version)\r
+\ingroup const_concepts\r
+\details The ConstBox concept apply the same as the Box concept,\r
+but does not apply write access.\r
+*/\r
+template <typename Geometry>\r
+class ConstBox\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef typename coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ template\r
+ <\r
+ std::size_t Index,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+ >\r
+ struct dimension_checker\r
+ {\r
+ static void apply()\r
+ {\r
+ const Geometry* b = 0;\r
+ coordinate_type coord(geometry::get<Index, Dimension>(*b));\r
+ boost::ignore_unused_variable_warning(coord);\r
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();\r
+ }\r
+ };\r
+\r
+ template <std::size_t Index, std::size_t DimensionCount>\r
+ struct dimension_checker<Index, DimensionCount, DimensionCount>\r
+ {\r
+ static void apply() {}\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(ConstBox)\r
+ {\r
+ static const std::size_t n = dimension<Geometry>::type::value;\r
+ dimension_checker<min_corner, 0, n>::apply();\r
+ dimension_checker<max_corner, 0, n>::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/box_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/multi_point_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/multi_linestring_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/multi_polygon_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/ring_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace concept_check\r
+{\r
+\r
+template <typename Concept>\r
+class check\r
+{\r
+ BOOST_CONCEPT_ASSERT((Concept ));\r
+};\r
+\r
+}} // namespace detail::concept_check\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename GeometryTag = typename geometry::tag<Geometry>::type,\r
+ bool IsConst = boost::is_const<Geometry>::type::value\r
+>\r
+struct check : not_implemented<GeometryTag>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, point_tag, true>\r
+ : detail::concept_check::check<concepts::ConstPoint<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, point_tag, false>\r
+ : detail::concept_check::check<concepts::Point<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, linestring_tag, true>\r
+ : detail::concept_check::check<concepts::ConstLinestring<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, linestring_tag, false>\r
+ : detail::concept_check::check<concepts::Linestring<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, ring_tag, true>\r
+ : detail::concept_check::check<concepts::ConstRing<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, ring_tag, false>\r
+ : detail::concept_check::check<concepts::Ring<Geometry> >\r
+{};\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, polygon_tag, true>\r
+ : detail::concept_check::check<concepts::ConstPolygon<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, polygon_tag, false>\r
+ : detail::concept_check::check<concepts::Polygon<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, box_tag, true>\r
+ : detail::concept_check::check<concepts::ConstBox<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, box_tag, false>\r
+ : detail::concept_check::check<concepts::Box<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, segment_tag, true>\r
+ : detail::concept_check::check<concepts::ConstSegment<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, segment_tag, false>\r
+ : detail::concept_check::check<concepts::Segment<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, multi_point_tag, true>\r
+ : detail::concept_check::check<concepts::ConstMultiPoint<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, multi_point_tag, false>\r
+ : detail::concept_check::check<concepts::MultiPoint<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, multi_linestring_tag, true>\r
+ : detail::concept_check::check<concepts::ConstMultiLinestring<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, multi_linestring_tag, false>\r
+ : detail::concept_check::check<concepts::MultiLinestring<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, multi_polygon_tag, true>\r
+ : detail::concept_check::check<concepts::ConstMultiPolygon<Geometry> >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct check<Geometry, multi_polygon_tag, false>\r
+ : detail::concept_check::check<concepts::MultiPolygon<Geometry> >\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+\r
+\r
+namespace concepts\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename Geometry>\r
+struct checker : dispatch::check<Geometry>\r
+{};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct checker<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct checker<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const>\r
+{};\r
+\r
+\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+ \brief Checks, in compile-time, the concept of any geometry\r
+ \ingroup concepts\r
+*/\r
+template <typename Geometry>\r
+inline void check()\r
+{\r
+ detail::checker<Geometry> c;\r
+ boost::ignore_unused_variable_warning(c);\r
+}\r
+\r
+\r
+/*!\r
+ \brief Checks, in compile-time, the concept of two geometries, and if they\r
+ have equal dimensions\r
+ \ingroup concepts\r
+*/\r
+template <typename Geometry1, typename Geometry2>\r
+inline void check_concepts_and_equal_dimensions()\r
+{\r
+ check<Geometry1>();\r
+ check<Geometry2>();\r
+ assert_dimension_equal<Geometry1, Geometry2>();\r
+}\r
+\r
+\r
+} // namespace concepts\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range/concepts.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief Linestring concept\r
+\ingroup concepts\r
+\par Formal definition:\r
+The linestring concept is defined as following:\r
+- there must be a specialization of traits::tag defining linestring_tag as type\r
+- it must behave like a Boost.Range\r
+- it must implement a std::back_insert_iterator\r
+ - either by implementing push_back\r
+ - or by specializing std::back_insert_iterator\r
+\r
+\note to fulfill the concepts, no traits class has to be specialized to\r
+define the point type.\r
+\r
+\par Example:\r
+\r
+A custom linestring, defining the necessary specializations to fulfill to the concept.\r
+\r
+Suppose that the following linestring is defined:\r
+\dontinclude doxygen_5.cpp\r
+\skip custom_linestring1\r
+\until };\r
+\r
+It can then be adapted to the concept as following:\r
+\dontinclude doxygen_5.cpp\r
+\skip adapt custom_linestring1\r
+\until }}\r
+\r
+\note\r
+- There is also the registration macro BOOST_GEOMETRY_REGISTER_LINESTRING\r
+- For registration of std::vector<P> (and deque, and list) it is enough to\r
+include the header-file geometries/adapted/std_as_linestring.hpp. That registers\r
+a vector as a linestring (so it cannot be registered as a linear ring then,\r
+in the same source code).\r
+\r
+\r
+*/\r
+\r
+template <typename Geometry>\r
+class Linestring\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(Linestring)\r
+ {\r
+ Geometry* ls = 0;\r
+ traits::clear<Geometry>::apply(*ls);\r
+ traits::resize<Geometry>::apply(*ls, 0);\r
+ point_type* point = 0;\r
+ traits::push_back<Geometry>::apply(*ls, *point);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief Linestring concept (const version)\r
+\ingroup const_concepts\r
+\details The ConstLinestring concept check the same as the Linestring concept,\r
+but does not check write access.\r
+*/\r
+template <typename Geometry>\r
+class ConstLinestring\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point_type>) );\r
+ //BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+ // Relaxed the concept.\r
+ BOOST_CONCEPT_ASSERT( (boost::ForwardRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(ConstLinestring)\r
+ {\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range/concepts.hpp>\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+\r
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief multi-linestring concept\r
+\ingroup concepts\r
+\par Formal definition:\r
+The multi linestring concept is defined as following:\r
+- there must be a specialization of traits::tag defining multi_linestring_tag as\r
+ type\r
+- it must behave like a Boost.Range\r
+- its range value must fulfil the Linestring concept\r
+\r
+*/\r
+template <typename Geometry>\r
+class MultiLinestring\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::range_value<Geometry>::type linestring_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Linestring<linestring_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(MultiLinestring)\r
+ {\r
+ Geometry* mls = 0;\r
+ traits::clear<Geometry>::apply(*mls);\r
+ traits::resize<Geometry>::apply(*mls, 0);\r
+ linestring_type* ls = 0;\r
+ traits::push_back<Geometry>::apply(*mls, *ls);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief concept for multi-linestring (const version)\r
+\ingroup const_concepts\r
+*/\r
+template <typename Geometry>\r
+class ConstMultiLinestring\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::range_value<Geometry>::type linestring_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstLinestring<linestring_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(ConstMultiLinestring)\r
+ {\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range/concepts.hpp>\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief MultiPoint concept\r
+\ingroup concepts\r
+\par Formal definition:\r
+The multi point concept is defined as following:\r
+- there must be a specialization of traits::tag defining multi_point_tag as type\r
+- it must behave like a Boost.Range\r
+- its range value must fulfil the Point concept\r
+\r
+*/\r
+template <typename Geometry>\r
+class MultiPoint\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::range_value<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(MultiPoint)\r
+ {\r
+ Geometry* mp = 0;\r
+ traits::clear<Geometry>::apply(*mp);\r
+ traits::resize<Geometry>::apply(*mp, 0);\r
+ point_type* point = 0;\r
+ traits::push_back<Geometry>::apply(*mp, *point);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief concept for multi-point (const version)\r
+\ingroup const_concepts\r
+*/\r
+template <typename Geometry>\r
+class ConstMultiPoint\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::range_value<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(ConstMultiPoint)\r
+ {\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range/concepts.hpp>\r
+#include <boost/range/metafunctions.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief multi-polygon concept\r
+\ingroup concepts\r
+\par Formal definition:\r
+The multi polygon concept is defined as following:\r
+- there must be a specialization of traits::tag defining multi_polygon_tag\r
+ as type\r
+- it must behave like a Boost.Range\r
+- its range value must fulfil the Polygon concept\r
+\r
+*/\r
+template <typename Geometry>\r
+class MultiPolygon\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::range_value<Geometry>::type polygon_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Polygon<polygon_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(MultiPolygon)\r
+ {\r
+ Geometry* mp = 0;\r
+ traits::clear<Geometry>::apply(*mp);\r
+ traits::resize<Geometry>::apply(*mp, 0);\r
+ polygon_type* poly = 0;\r
+ traits::push_back<Geometry>::apply(*mp, *poly);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief concept for multi-polygon (const version)\r
+\ingroup const_concepts\r
+*/\r
+template <typename Geometry>\r
+class ConstMultiPolygon\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::range_value<Geometry>::type polygon_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPolygon<polygon_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(ConstMultiPolygon)\r
+ {\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+//\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+/*!\r
+\brief Point concept.\r
+\ingroup concepts\r
+\r
+\par Formal definition:\r
+The point concept is defined as following:\r
+- there must be a specialization of traits::tag defining point_tag as type\r
+- there must be a specialization of traits::coordinate_type defining the type\r
+ of its coordinates\r
+- there must be a specialization of traits::coordinate_system defining its\r
+ coordinate system (cartesian, spherical, etc)\r
+- there must be a specialization of traits::dimension defining its number\r
+ of dimensions (2, 3, ...) (derive it conveniently\r
+ from boost::mpl::int_<X> for X-D)\r
+- there must be a specialization of traits::access, per dimension,\r
+ with two functions:\r
+ - \b get to get a coordinate value\r
+ - \b set to set a coordinate value (this one is not checked for ConstPoint)\r
+- for non-Cartesian coordinate systems, the coordinate system's units\r
+ must either be boost::geometry::degree or boost::geometry::radian\r
+\r
+\r
+\par Example:\r
+\r
+A legacy point, defining the necessary specializations to fulfil to the concept.\r
+\r
+Suppose that the following point is defined:\r
+\dontinclude doxygen_5.cpp\r
+\skip legacy_point1\r
+\until };\r
+\r
+It can then be adapted to the concept as following:\r
+\dontinclude doxygen_5.cpp\r
+\skip adapt legacy_point1\r
+\until }}\r
+\r
+Note that it is done like above to show the system. Users will normally use the registration macro.\r
+\r
+\par Example:\r
+\r
+A read-only legacy point, using a macro to fulfil to the ConstPoint concept.\r
+It cannot be modified by the library but can be used in all algorithms where\r
+points are not modified.\r
+\r
+The point looks like the following:\r
+\r
+\dontinclude doxygen_5.cpp\r
+\skip legacy_point2\r
+\until };\r
+\r
+It uses the macro as following:\r
+\dontinclude doxygen_5.cpp\r
+\skip adapt legacy_point2\r
+\until end adaptation\r
+\r
+*/\r
+\r
+template <typename Geometry>\r
+class Point\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ typedef typename coordinate_type<Geometry>::type ctype;\r
+ typedef typename coordinate_system<Geometry>::type csystem;\r
+\r
+ // The following enum is used to fully instantiate the coordinate\r
+ // system class; this is needed in order to check the units passed\r
+ // to it for non-Cartesian coordinate systems.\r
+ enum { cs_check = sizeof(csystem) };\r
+\r
+ enum { ccount = dimension<Geometry>::value };\r
+\r
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>\r
+ struct dimension_checker\r
+ {\r
+ static void apply()\r
+ {\r
+ P* p = 0;\r
+ geometry::set<Dimension>(*p, geometry::get<Dimension>(*p));\r
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();\r
+ }\r
+ };\r
+\r
+\r
+ template <typename P, std::size_t DimensionCount>\r
+ struct dimension_checker<P, DimensionCount, DimensionCount>\r
+ {\r
+ static void apply() {}\r
+ };\r
+\r
+public:\r
+\r
+ /// BCCL macro to apply the Point concept\r
+ BOOST_CONCEPT_USAGE(Point)\r
+ {\r
+ dimension_checker<Geometry, 0, ccount>::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief point concept (const version).\r
+\r
+\ingroup const_concepts\r
+\r
+\details The ConstPoint concept apply the same as the Point concept,\r
+but does not apply write access.\r
+\r
+*/\r
+template <typename Geometry>\r
+class ConstPoint\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ typedef typename coordinate_type<Geometry>::type ctype;\r
+ typedef typename coordinate_system<Geometry>::type csystem;\r
+\r
+ // The following enum is used to fully instantiate the coordinate\r
+ // system class; this is needed in order to check the units passed\r
+ // to it for non-Cartesian coordinate systems.\r
+ enum { cs_check = sizeof(csystem) };\r
+\r
+ enum { ccount = dimension<Geometry>::value };\r
+\r
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>\r
+ struct dimension_checker\r
+ {\r
+ static void apply()\r
+ {\r
+ const P* p = 0;\r
+ ctype coord(geometry::get<Dimension>(*p));\r
+ boost::ignore_unused(p, coord);\r
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();\r
+ }\r
+ };\r
+\r
+\r
+ template <typename P, std::size_t DimensionCount>\r
+ struct dimension_checker<P, DimensionCount, DimensionCount>\r
+ {\r
+ static void apply() {}\r
+ };\r
+\r
+public:\r
+\r
+ /// BCCL macro to apply the ConstPoint concept\r
+ BOOST_CONCEPT_USAGE(ConstPoint)\r
+ {\r
+ dimension_checker<Geometry, 0, ccount>::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range/concepts.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/ring_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+/*!\r
+\brief Checks polygon concept\r
+\ingroup concepts\r
+*/\r
+template <typename PolygonType>\r
+class Polygon\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename boost::remove_const<PolygonType>::type polygon_type;\r
+\r
+ typedef typename traits::ring_const_type<polygon_type>::type ring_const_type;\r
+ typedef typename traits::ring_mutable_type<polygon_type>::type ring_mutable_type;\r
+ typedef typename traits::interior_const_type<polygon_type>::type interior_const_type;\r
+ typedef typename traits::interior_mutable_type<polygon_type>::type interior_mutable_type;\r
+\r
+ typedef typename point_type<PolygonType>::type point_type;\r
+ typedef typename ring_type<PolygonType>::type ring_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::Ring<ring_type>) );\r
+\r
+ //BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<interior_type>) );\r
+\r
+ struct checker\r
+ {\r
+ static inline void apply()\r
+ {\r
+ polygon_type* poly = 0;\r
+ polygon_type const* cpoly = poly;\r
+\r
+ ring_mutable_type e = traits::exterior_ring<PolygonType>::get(*poly);\r
+ interior_mutable_type i = traits::interior_rings<PolygonType>::get(*poly);\r
+ ring_const_type ce = traits::exterior_ring<PolygonType>::get(*cpoly);\r
+ interior_const_type ci = traits::interior_rings<PolygonType>::get(*cpoly);\r
+\r
+ boost::ignore_unused_variable_warning(e);\r
+ boost::ignore_unused_variable_warning(i);\r
+ boost::ignore_unused_variable_warning(ce);\r
+ boost::ignore_unused_variable_warning(ci);\r
+ boost::ignore_unused_variable_warning(poly);\r
+ boost::ignore_unused_variable_warning(cpoly);\r
+ }\r
+ };\r
+\r
+public:\r
+\r
+ BOOST_CONCEPT_USAGE(Polygon)\r
+ {\r
+ checker::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief Checks polygon concept (const version)\r
+\ingroup const_concepts\r
+*/\r
+template <typename PolygonType>\r
+class ConstPolygon\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ typedef typename boost::remove_const<PolygonType>::type const_polygon_type;\r
+\r
+ typedef typename traits::ring_const_type<const_polygon_type>::type ring_const_type;\r
+ typedef typename traits::interior_const_type<const_polygon_type>::type interior_const_type;\r
+\r
+ typedef typename point_type<const_polygon_type>::type point_type;\r
+ typedef typename ring_type<const_polygon_type>::type ring_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstRing<ring_type>) );\r
+\r
+ ////BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<interior_type>) );\r
+\r
+ struct checker\r
+ {\r
+ static inline void apply()\r
+ {\r
+ const_polygon_type const* cpoly = 0;\r
+\r
+ ring_const_type ce = traits::exterior_ring<const_polygon_type>::get(*cpoly);\r
+ interior_const_type ci = traits::interior_rings<const_polygon_type>::get(*cpoly);\r
+\r
+ boost::ignore_unused_variable_warning(ce);\r
+ boost::ignore_unused_variable_warning(ci);\r
+ boost::ignore_unused_variable_warning(cpoly);\r
+ }\r
+ };\r
+\r
+public:\r
+\r
+ BOOST_CONCEPT_USAGE(ConstPolygon)\r
+ {\r
+ checker::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range/concepts.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief ring concept\r
+\ingroup concepts\r
+\par Formal definition:\r
+The ring concept is defined as following:\r
+- there must be a specialization of traits::tag defining ring_tag as type\r
+- it must behave like a Boost.Range\r
+- there can optionally be a specialization of traits::point_order defining the\r
+ order or orientation of its points, clockwise or counterclockwise.\r
+- it must implement a std::back_insert_iterator\r
+ (This is the same as the for the concept Linestring, and described there)\r
+\r
+\note to fulfill the concepts, no traits class has to be specialized to\r
+define the point type.\r
+*/\r
+template <typename Geometry>\r
+class Ring\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(Ring)\r
+ {\r
+ Geometry* ring = 0;\r
+ traits::clear<Geometry>::apply(*ring);\r
+ traits::resize<Geometry>::apply(*ring, 0);\r
+ point_type* point = 0;\r
+ traits::push_back<Geometry>::apply(*ring, *point);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief (linear) ring concept (const version)\r
+\ingroup const_concepts\r
+\details The ConstLinearRing concept check the same as the Geometry concept,\r
+but does not check write access.\r
+*/\r
+template <typename Geometry>\r
+class ConstRing\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point_type>) );\r
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );\r
+\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(ConstRing)\r
+ {\r
+ }\r
+#endif\r
+};\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief Segment concept.\r
+\ingroup concepts\r
+\details Formal definition:\r
+The segment concept is defined as following:\r
+- there must be a specialization of traits::tag defining segment_tag as type\r
+- there must be a specialization of traits::point_type to define the\r
+ underlying point type (even if it does not consist of points, it should define\r
+ this type, to indicate the points it can work with)\r
+- there must be a specialization of traits::indexed_access, per index\r
+ and per dimension, with two functions:\r
+ - get to get a coordinate value\r
+ - set to set a coordinate value (this one is not checked for ConstSegment)\r
+\r
+\note The segment concept is similar to the box concept, defining another tag.\r
+However, the box concept assumes the index as min_corner, max_corner, while\r
+for the segment concept there is no assumption.\r
+*/\r
+template <typename Geometry>\r
+class Segment\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<point_type>) );\r
+\r
+\r
+ template <size_t Index, size_t Dimension, size_t DimensionCount>\r
+ struct dimension_checker\r
+ {\r
+ static void apply()\r
+ {\r
+ Geometry* s = 0;\r
+ geometry::set<Index, Dimension>(*s, geometry::get<Index, Dimension>(*s));\r
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();\r
+ }\r
+ };\r
+\r
+ template <size_t Index, size_t DimensionCount>\r
+ struct dimension_checker<Index, DimensionCount, DimensionCount>\r
+ {\r
+ static void apply() {}\r
+ };\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(Segment)\r
+ {\r
+ static const size_t n = dimension<point_type>::type::value;\r
+ dimension_checker<0, 0, n>::apply();\r
+ dimension_checker<1, 0, n>::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+\brief Segment concept (const version).\r
+\ingroup const_concepts\r
+\details The ConstSegment concept verifies the same as the Segment concept,\r
+but does not verify write access.\r
+*/\r
+template <typename Geometry>\r
+class ConstSegment\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef typename coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point_type>) );\r
+\r
+\r
+ template <size_t Index, size_t Dimension, size_t DimensionCount>\r
+ struct dimension_checker\r
+ {\r
+ static void apply()\r
+ {\r
+ const Geometry* s = 0;\r
+ coordinate_type coord(geometry::get<Index, Dimension>(*s));\r
+ boost::ignore_unused_variable_warning(coord);\r
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();\r
+ }\r
+ };\r
+\r
+ template <size_t Index, size_t DimensionCount>\r
+ struct dimension_checker<Index, DimensionCount, DimensionCount>\r
+ {\r
+ static void apply() {}\r
+ };\r
+\r
+public :\r
+\r
+ BOOST_CONCEPT_USAGE(ConstSegment)\r
+ {\r
+ static const size_t n = dimension<point_type>::type::value;\r
+ dimension_checker<0, 0, n>::apply();\r
+ dimension_checker<1, 0, n>::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_HPP\r
+\r
+#include <boost/geometry/geometries/point.hpp>\r
+#include <boost/geometry/geometries/linestring.hpp>\r
+#include <boost/geometry/geometries/polygon.hpp>\r
+\r
+#include <boost/geometry/geometries/multi_point.hpp>\r
+#include <boost/geometry/geometries/multi_linestring.hpp>\r
+#include <boost/geometry/geometries/multi_polygon.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+#include <boost/geometry/geometries/ring.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/box.hpp>\r
+#include <boost/geometry/geometries/point.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail { namespace helper_geometries\r
+{\r
+\r
+template <typename Geometry, typename CS_Tag = typename cs_tag<Geometry>::type>\r
+struct default_units\r
+{\r
+ typedef typename coordinate_system<Geometry>::type::units type;\r
+};\r
+\r
+// The Cartesian coordinate system does not define the type units.\r
+// For that reason the generic implementation for default_units cannot be used\r
+// and specialization needs to be defined.\r
+// Moreover, it makes sense to define the units for the Cartesian\r
+// coordinate system to be radians, as this way a Cartesian point can\r
+// potentially be used in algorithms taking non-Cartesian strategies\r
+// and work as if it was as point in the non-Cartesian coordinate\r
+// system with radian units.\r
+template <typename Geometry>\r
+struct default_units<Geometry, cartesian_tag>\r
+{\r
+ typedef radian type;\r
+};\r
+\r
+\r
+template <typename Units, typename CS_Tag>\r
+struct cs_tag_to_coordinate_system\r
+{\r
+ typedef cs::cartesian type;\r
+};\r
+\r
+template <typename Units>\r
+struct cs_tag_to_coordinate_system<Units, spherical_equatorial_tag>\r
+{\r
+ typedef cs::spherical_equatorial<Units> type;\r
+};\r
+\r
+template <typename Units>\r
+struct cs_tag_to_coordinate_system<Units, spherical_tag>\r
+{\r
+ typedef cs::spherical<Units> type;\r
+};\r
+\r
+template <typename Units>\r
+struct cs_tag_to_coordinate_system<Units, geographic_tag>\r
+{\r
+ typedef cs::geographic<Units> type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename NewCoordinateType,\r
+ typename NewUnits,\r
+ typename CS_Tag = typename cs_tag<Point>::type\r
+>\r
+struct helper_point\r
+{\r
+ typedef model::point\r
+ <\r
+ NewCoordinateType,\r
+ dimension<Point>::value,\r
+ typename cs_tag_to_coordinate_system<NewUnits, CS_Tag>::type\r
+ > type;\r
+};\r
+\r
+\r
+}} // detail::helper_geometries\r
+\r
+\r
+namespace detail_dispatch\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename NewCoordinateType,\r
+ typename NewUnits,\r
+ typename Tag = typename tag<Geometry>::type>\r
+struct helper_geometry : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+template <typename Point, typename NewCoordinateType, typename NewUnits>\r
+struct helper_geometry<Point, NewCoordinateType, NewUnits, point_tag>\r
+{\r
+ typedef typename detail::helper_geometries::helper_point\r
+ <\r
+ Point, NewCoordinateType, NewUnits\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename Box, typename NewCoordinateType, typename NewUnits>\r
+struct helper_geometry<Box, NewCoordinateType, NewUnits, box_tag>\r
+{\r
+ typedef model::box\r
+ <\r
+ typename helper_geometry\r
+ <\r
+ typename point_type<Box>::type, NewCoordinateType, NewUnits\r
+ >::type\r
+ > type;\r
+};\r
+\r
+\r
+} // detail_dispatch\r
+\r
+\r
+// Meta-function that provides a new helper geometry of the same kind as\r
+// the input geometry and the same coordinate system type,\r
+// but with a possibly different coordinate type and coordinate system units\r
+template\r
+<\r
+ typename Geometry,\r
+ typename NewCoordinateType = typename coordinate_type<Geometry>::type,\r
+ typename NewUnits = typename detail::helper_geometries::default_units\r
+ <\r
+ Geometry\r
+ >::type\r
+>\r
+struct helper_geometry\r
+{\r
+ typedef typename detail_dispatch::helper_geometry\r
+ <\r
+ Geometry, NewCoordinateType, NewUnits\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include <boost/concept/assert.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+#include <initializer_list>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+/*!\r
+\brief A linestring (named so by OGC) is a collection (default a vector) of points.\r
+\ingroup geometries\r
+\tparam Point \tparam_point\r
+\tparam Container \tparam_container\r
+\tparam Allocator \tparam_allocator\r
+\r
+\qbk{[include reference/geometries/linestring.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_linestring Linestring Concept]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ template<typename,typename> class Container = std::vector,\r
+ template<typename> class Allocator = std::allocator\r
+>\r
+class linestring : public Container<Point, Allocator<Point> >\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ typedef Container<Point, Allocator<Point> > base_type;\r
+\r
+public :\r
+ /// \constructor_default{linestring}\r
+ inline linestring()\r
+ : base_type()\r
+ {}\r
+\r
+ /// \constructor_begin_end{linestring}\r
+ template <typename Iterator>\r
+ inline linestring(Iterator begin, Iterator end)\r
+ : base_type(begin, end)\r
+ {}\r
+\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+\r
+ /// \constructor_initializer_list{linestring}\r
+ inline linestring(std::initializer_list<Point> l)\r
+ : base_type(l.begin(), l.end())\r
+ {}\r
+\r
+// Commented out for now in order to support Boost.Assign\r
+// Without this assignment operator first the object should be created\r
+// from initializer list, then it should be moved.\r
+//// Without this workaround in MSVC the assignment operator is ambiguous\r
+//#ifndef BOOST_MSVC\r
+// /// \assignment_initializer_list{linestring}\r
+// inline linestring & operator=(std::initializer_list<Point> l)\r
+// {\r
+// base_type::assign(l.begin(), l.end());\r
+// return *this;\r
+// }\r
+//#endif\r
+\r
+#endif\r
+};\r
+\r
+} // namespace model\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template<typename,typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct tag<model::linestring<Point, Container, Allocator> >\r
+{\r
+ typedef linestring_tag type;\r
+};\r
+} // namespace traits\r
+\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_MULTI_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_MULTI_LINESTRING_HPP\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include <boost/concept/requires.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>\r
+\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+#include <initializer_list>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace model\r
+{\r
+\r
+/*!\r
+\brief multi_line, a collection of linestring\r
+\details Multi-linestring can be used to group lines belonging to each other,\r
+ e.g. a highway (with interruptions)\r
+\ingroup geometries\r
+\r
+\qbk{[include reference/geometries/multi_linestring.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_multi_linestring MultiLineString Concept]\r
+}\r
+*/\r
+template\r
+<\r
+ typename LineString,\r
+ template<typename, typename> class Container = std::vector,\r
+ template<typename> class Allocator = std::allocator\r
+>\r
+class multi_linestring : public Container<LineString, Allocator<LineString> >\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Linestring<LineString>) );\r
+\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+\r
+ // default constructor and base_type definitions are required only\r
+ // if the constructor taking std::initializer_list is defined\r
+\r
+ typedef Container<LineString, Allocator<LineString> > base_type;\r
+\r
+public:\r
+ /// \constructor_default{multi_linestring}\r
+ multi_linestring()\r
+ : base_type()\r
+ {}\r
+\r
+ /// \constructor_initializer_list{multi_linestring}\r
+ inline multi_linestring(std::initializer_list<LineString> l)\r
+ : base_type(l.begin(), l.end())\r
+ {}\r
+\r
+// Commented out for now in order to support Boost.Assign\r
+// Without this assignment operator first the object should be created\r
+// from initializer list, then it shoudl be moved.\r
+//// Without this workaround in MSVC the assignment operator is ambiguous\r
+//#ifndef BOOST_MSVC\r
+// /// \assignment_initializer_list{multi_linestring}\r
+// inline multi_linestring & operator=(std::initializer_list<LineString> l)\r
+// {\r
+// base_type::assign(l.begin(), l.end());\r
+// return *this;\r
+// }\r
+//#endif\r
+\r
+#endif\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template\r
+<\r
+ typename LineString,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct tag< model::multi_linestring<LineString, Container, Allocator> >\r
+{\r
+ typedef multi_linestring_tag type;\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_MULTI_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_MULTI_POINT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_MULTI_POINT_HPP\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include <boost/concept/requires.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+#include <initializer_list>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+\r
+/*!\r
+\brief multi_point, a collection of points\r
+\ingroup geometries\r
+\tparam Point \tparam_point\r
+\tparam Container \tparam_container\r
+\tparam Allocator \tparam_allocator\r
+\details Multipoint can be used to group points belonging to each other,\r
+ e.g. a constellation, or the result set of an intersection\r
+\r
+\qbk{[include reference/geometries/multi_point.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_multi_point MultiPoint Concept]\r
+}\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ template<typename, typename> class Container = std::vector,\r
+ template<typename> class Allocator = std::allocator\r
+>\r
+class multi_point : public Container<Point, Allocator<Point> >\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ typedef Container<Point, Allocator<Point> > base_type;\r
+\r
+public :\r
+ /// \constructor_default{multi_point}\r
+ inline multi_point()\r
+ : base_type()\r
+ {}\r
+\r
+ /// \constructor_begin_end{multi_point}\r
+ template <typename Iterator>\r
+ inline multi_point(Iterator begin, Iterator end)\r
+ : base_type(begin, end)\r
+ {}\r
+\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+\r
+ /// \constructor_initializer_list{multi_point}\r
+ inline multi_point(std::initializer_list<Point> l)\r
+ : base_type(l.begin(), l.end())\r
+ {}\r
+\r
+// Commented out for now in order to support Boost.Assign\r
+// Without this assignment operator first the object should be created\r
+// from initializer list, then it shoudl be moved.\r
+//// Without this workaround in MSVC the assignment operator is ambiguous\r
+//#ifndef BOOST_MSVC\r
+// /// \assignment_initializer_list{multi_point}\r
+// inline multi_point & operator=(std::initializer_list<Point> l)\r
+// {\r
+// base_type::assign(l.begin(), l.end());\r
+// return *this;\r
+// }\r
+//#endif\r
+\r
+#endif\r
+};\r
+\r
+} // namespace model\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct tag< model::multi_point<Point, Container, Allocator> >\r
+{\r
+ typedef multi_point_tag type;\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_MULTI_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_MULTI_POLYGON_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_MULTI_POLYGON_HPP\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include <boost/concept/requires.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>\r
+\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+#include <initializer_list>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+/*!\r
+\brief multi_polygon, a collection of polygons\r
+\details Multi-polygon can be used to group polygons belonging to each other,\r
+ e.g. Hawaii\r
+\ingroup geometries\r
+\r
+\qbk{[include reference/geometries/multi_polygon.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_multi_polygon MultiPolygon Concept]\r
+}\r
+*/\r
+template\r
+<\r
+ typename Polygon,\r
+ template<typename, typename> class Container = std::vector,\r
+ template<typename> class Allocator = std::allocator\r
+>\r
+class multi_polygon : public Container<Polygon, Allocator<Polygon> >\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Polygon<Polygon>) );\r
+\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+\r
+ // default constructor and base_type definitions are required only\r
+ // if the constructor taking std::initializer_list is defined\r
+\r
+ typedef Container<Polygon, Allocator<Polygon> > base_type;\r
+\r
+public:\r
+ /// \constructor_default{multi_polygon}\r
+ multi_polygon()\r
+ : base_type()\r
+ {}\r
+\r
+ /// \constructor_initializer_list{multi_polygon}\r
+ inline multi_polygon(std::initializer_list<Polygon> l)\r
+ : base_type(l.begin(), l.end())\r
+ {}\r
+\r
+// Commented out for now in order to support Boost.Assign\r
+// Without this assignment operator first the object should be created\r
+// from initializer list, then it shoudl be moved.\r
+//// Without this workaround in MSVC the assignment operator is ambiguous\r
+//#ifndef BOOST_MSVC\r
+// /// \assignment_initializer_list{multi_polygon}\r
+// inline multi_polygon & operator=(std::initializer_list<Polygon> l)\r
+// {\r
+// base_type::assign(l.begin(), l.end());\r
+// return *this;\r
+// }\r
+//#endif\r
+\r
+#endif\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template\r
+<\r
+ typename Polygon,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct tag< model::multi_polygon<Polygon, Container, Allocator> >\r
+{\r
+ typedef multi_polygon_tag type;\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_MULTI_POLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_POINT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/int.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+#include <algorithm>\r
+#include <boost/geometry/core/assert.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+\r
+namespace model\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+template <std::size_t DimensionCount, std::size_t Index>\r
+struct array_assign\r
+{\r
+ template <typename T>\r
+ static inline void apply(T values[], T const& value)\r
+ {\r
+ values[Index] = value;\r
+ }\r
+};\r
+\r
+// Specialization avoiding assigning element [2] for only 2 dimensions\r
+template <> struct array_assign<2, 2>\r
+{\r
+ template <typename T> static inline void apply(T [], T const& ) {}\r
+};\r
+\r
+// Specialization avoiding assigning elements for (rarely used) points in 1 dim\r
+template <> struct array_assign<1, 1>\r
+{\r
+ template <typename T> static inline void apply(T [], T const& ) {}\r
+};\r
+\r
+template <> struct array_assign<1, 2>\r
+{\r
+ template <typename T> static inline void apply(T [], T const& ) {}\r
+};\r
+\r
+}\r
+/*!\r
+\brief Basic point class, having coordinates defined in a neutral way\r
+\details Defines a neutral point class, fulfilling the Point Concept.\r
+ Library users can use this point class, or use their own point classes.\r
+ This point class is used in most of the samples and tests of Boost.Geometry\r
+ This point class is used occasionally within the library, where a temporary\r
+ point class is necessary.\r
+\ingroup geometries\r
+\tparam CoordinateType \tparam_numeric\r
+\tparam DimensionCount number of coordinates, usually 2 or 3\r
+\tparam CoordinateSystem coordinate system, for example cs::cartesian\r
+\r
+\qbk{[include reference/geometries/point.qbk]}\r
+\qbk{before.synopsis, [heading Model of]}\r
+\qbk{before.synopsis, [link geometry.reference.concepts.concept_point Point Concept]}\r
+\r
+\r
+*/\r
+template\r
+<\r
+ typename CoordinateType,\r
+ std::size_t DimensionCount,\r
+ typename CoordinateSystem\r
+>\r
+class point\r
+{\r
+ BOOST_MPL_ASSERT_MSG((DimensionCount >= 1),\r
+ DIMENSION_GREATER_THAN_ZERO_EXPECTED,\r
+ (boost::mpl::int_<DimensionCount>));\r
+\r
+ // The following enum is used to fully instantiate the\r
+ // CoordinateSystem class and check the correctness of the units\r
+ // passed for non-Cartesian coordinate systems.\r
+ enum { cs_check = sizeof(CoordinateSystem) };\r
+\r
+public:\r
+\r
+#if !defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)\r
+ /// \constructor_default_no_init\r
+ point() = default;\r
+#else\r
+ /// \constructor_default_no_init\r
+ inline point()\r
+ {}\r
+#endif\r
+#else // defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ point()\r
+ {\r
+ m_created = 1;\r
+ std::fill_n(m_values_initialized, DimensionCount, 0);\r
+ }\r
+ ~point()\r
+ {\r
+ m_created = 0;\r
+ std::fill_n(m_values_initialized, DimensionCount, 0);\r
+ }\r
+#endif\r
+\r
+ /// @brief Constructor to set one value\r
+ explicit inline point(CoordinateType const& v0)\r
+ {\r
+ detail::array_assign<DimensionCount, 0>::apply(m_values, v0);\r
+ detail::array_assign<DimensionCount, 1>::apply(m_values, CoordinateType());\r
+ detail::array_assign<DimensionCount, 2>::apply(m_values, CoordinateType());\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ m_created = 1;\r
+ std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);\r
+#endif\r
+ }\r
+\r
+ /// @brief Constructor to set two values\r
+ inline point(CoordinateType const& v0, CoordinateType const& v1)\r
+ {\r
+ detail::array_assign<DimensionCount, 0>::apply(m_values, v0);\r
+ detail::array_assign<DimensionCount, 1>::apply(m_values, v1);\r
+ detail::array_assign<DimensionCount, 2>::apply(m_values, CoordinateType());\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ m_created = 1;\r
+ std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);\r
+#endif\r
+ }\r
+\r
+ /// @brief Constructor to set three values\r
+ inline point(CoordinateType const& v0, CoordinateType const& v1,\r
+ CoordinateType const& v2)\r
+ {\r
+ detail::array_assign<DimensionCount, 0>::apply(m_values, v0);\r
+ detail::array_assign<DimensionCount, 1>::apply(m_values, v1);\r
+ detail::array_assign<DimensionCount, 2>::apply(m_values, v2);\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ m_created = 1;\r
+ std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);\r
+#endif\r
+ }\r
+\r
+ /// @brief Get a coordinate\r
+ /// @tparam K coordinate to get\r
+ /// @return the coordinate\r
+ template <std::size_t K>\r
+ inline CoordinateType const& get() const\r
+ {\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ BOOST_GEOMETRY_ASSERT(m_created == 1);\r
+ BOOST_GEOMETRY_ASSERT(m_values_initialized[K] == 1);\r
+#endif\r
+ BOOST_STATIC_ASSERT(K < DimensionCount);\r
+ return m_values[K];\r
+ }\r
+\r
+ /// @brief Set a coordinate\r
+ /// @tparam K coordinate to set\r
+ /// @param value value to set\r
+ template <std::size_t K>\r
+ inline void set(CoordinateType const& value)\r
+ {\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ BOOST_GEOMETRY_ASSERT(m_created == 1);\r
+ m_values_initialized[K] = 1;\r
+#endif\r
+ BOOST_STATIC_ASSERT(K < DimensionCount);\r
+ m_values[K] = value;\r
+ }\r
+\r
+private:\r
+\r
+ CoordinateType m_values[DimensionCount];\r
+\r
+#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)\r
+ int m_created;\r
+ int m_values_initialized[DimensionCount];\r
+#endif\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+// Adapt the point to the concept\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+template\r
+<\r
+ typename CoordinateType,\r
+ std::size_t DimensionCount,\r
+ typename CoordinateSystem\r
+>\r
+struct tag<model::point<CoordinateType, DimensionCount, CoordinateSystem> >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+template\r
+<\r
+ typename CoordinateType,\r
+ std::size_t DimensionCount,\r
+ typename CoordinateSystem\r
+>\r
+struct coordinate_type<model::point<CoordinateType, DimensionCount, CoordinateSystem> >\r
+{\r
+ typedef CoordinateType type;\r
+};\r
+\r
+template\r
+<\r
+ typename CoordinateType,\r
+ std::size_t DimensionCount,\r
+ typename CoordinateSystem\r
+>\r
+struct coordinate_system<model::point<CoordinateType, DimensionCount, CoordinateSystem> >\r
+{\r
+ typedef CoordinateSystem type;\r
+};\r
+\r
+template\r
+<\r
+ typename CoordinateType,\r
+ std::size_t DimensionCount,\r
+ typename CoordinateSystem\r
+>\r
+struct dimension<model::point<CoordinateType, DimensionCount, CoordinateSystem> >\r
+ : boost::mpl::int_<DimensionCount>\r
+{};\r
+\r
+template\r
+<\r
+ typename CoordinateType,\r
+ std::size_t DimensionCount,\r
+ typename CoordinateSystem,\r
+ std::size_t Dimension\r
+>\r
+struct access<model::point<CoordinateType, DimensionCount, CoordinateSystem>, Dimension>\r
+{\r
+ static inline CoordinateType get(\r
+ model::point<CoordinateType, DimensionCount, CoordinateSystem> const& p)\r
+ {\r
+ return p.template get<Dimension>();\r
+ }\r
+\r
+ static inline void set(\r
+ model::point<CoordinateType, DimensionCount, CoordinateSystem>& p,\r
+ CoordinateType const& value)\r
+ {\r
+ p.template set<Dimension>(value);\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/mpl/int.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/geometries/point.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model { namespace d2\r
+{\r
+\r
+/*!\r
+\brief 2D point in Cartesian coordinate system\r
+\tparam CoordinateType numeric type, for example, double, float, int\r
+\tparam CoordinateSystem coordinate system, defaults to cs::cartesian\r
+\r
+\qbk{[include reference/geometries/point_xy.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_point Point Concept]\r
+}\r
+\r
+\qbk{[include reference/geometries/point_assign_warning.qbk]}\r
+\r
+*/\r
+template<typename CoordinateType, typename CoordinateSystem = cs::cartesian>\r
+class point_xy : public model::point<CoordinateType, 2, CoordinateSystem>\r
+{\r
+public:\r
+\r
+#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS\r
+ /// \constructor_default_no_init\r
+ point_xy() = default;\r
+#else\r
+ /// \constructor_default_no_init\r
+ inline point_xy()\r
+ {}\r
+#endif\r
+\r
+ /// Constructor with x/y values\r
+ inline point_xy(CoordinateType const& x, CoordinateType const& y)\r
+ : model::point<CoordinateType, 2, CoordinateSystem>(x, y)\r
+ {}\r
+\r
+ /// Get x-value\r
+ inline CoordinateType const& x() const\r
+ { return this->template get<0>(); }\r
+\r
+ /// Get y-value\r
+ inline CoordinateType const& y() const\r
+ { return this->template get<1>(); }\r
+\r
+ /// Set x-value\r
+ inline void x(CoordinateType const& v)\r
+ { this->template set<0>(v); }\r
+\r
+ /// Set y-value\r
+ inline void y(CoordinateType const& v)\r
+ { this->template set<1>(v); }\r
+};\r
+\r
+\r
+}} // namespace model::d2\r
+\r
+\r
+// Adapt the point_xy to the concept\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename CoordinateType, typename CoordinateSystem>\r
+struct tag<model::d2::point_xy<CoordinateType, CoordinateSystem> >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+template<typename CoordinateType, typename CoordinateSystem>\r
+struct coordinate_type<model::d2::point_xy<CoordinateType, CoordinateSystem> >\r
+{\r
+ typedef CoordinateType type;\r
+};\r
+\r
+template<typename CoordinateType, typename CoordinateSystem>\r
+struct coordinate_system<model::d2::point_xy<CoordinateType, CoordinateSystem> >\r
+{\r
+ typedef CoordinateSystem type;\r
+};\r
+\r
+template<typename CoordinateType, typename CoordinateSystem>\r
+struct dimension<model::d2::point_xy<CoordinateType, CoordinateSystem> >\r
+ : boost::mpl::int_<2>\r
+{};\r
+\r
+template<typename CoordinateType, typename CoordinateSystem, std::size_t Dimension>\r
+struct access<model::d2::point_xy<CoordinateType, CoordinateSystem>, Dimension >\r
+{\r
+ static inline CoordinateType get(\r
+ model::d2::point_xy<CoordinateType, CoordinateSystem> const& p)\r
+ {\r
+ return p.template get<Dimension>();\r
+ }\r
+\r
+ static inline void set(model::d2::point_xy<CoordinateType, CoordinateSystem>& p,\r
+ CoordinateType const& value)\r
+ {\r
+ p.template set<Dimension>(value);\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINTING_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_POINTING_SEGMENT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/assert.hpp>\r
+#include <boost/core/addressof.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+// const or non-const segment type that is meant to be\r
+// * default constructible\r
+// * copy constructible\r
+// * assignable\r
+// referring_segment does not fit these requirements, hence the\r
+// pointing_segment class\r
+//\r
+// this class is used by the segment_iterator as its value type\r
+template <typename ConstOrNonConstPoint>\r
+class pointing_segment\r
+{\r
+ BOOST_CONCEPT_ASSERT( (\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_const<ConstOrNonConstPoint>,\r
+ concepts::Point<ConstOrNonConstPoint>,\r
+ concepts::ConstPoint<ConstOrNonConstPoint>\r
+ >\r
+ ) );\r
+\r
+ typedef ConstOrNonConstPoint point_type;\r
+\r
+public:\r
+ point_type* first;\r
+ point_type* second;\r
+\r
+ inline pointing_segment()\r
+ : first(NULL)\r
+ , second(NULL)\r
+ {}\r
+\r
+ inline pointing_segment(point_type const& p1, point_type const& p2)\r
+ : first(boost::addressof(p1))\r
+ , second(boost::addressof(p2))\r
+ {}\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+\r
+// Traits specializations for segment above\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename Point>\r
+struct tag<model::pointing_segment<Point> >\r
+{\r
+ typedef segment_tag type;\r
+};\r
+\r
+template <typename Point>\r
+struct point_type<model::pointing_segment<Point> >\r
+{\r
+ typedef Point type;\r
+};\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<model::pointing_segment<Point>, 0, Dimension>\r
+{\r
+ typedef model::pointing_segment<Point> segment_type;\r
+ typedef typename geometry::coordinate_type\r
+ <\r
+ segment_type\r
+ >::type coordinate_type;\r
+\r
+ static inline coordinate_type get(segment_type const& s)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( s.first != NULL );\r
+ return geometry::get<Dimension>(*s.first);\r
+ }\r
+\r
+ static inline void set(segment_type& s, coordinate_type const& value)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( s.first != NULL );\r
+ geometry::set<Dimension>(*s.first, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<model::pointing_segment<Point>, 1, Dimension>\r
+{\r
+ typedef model::pointing_segment<Point> segment_type;\r
+ typedef typename geometry::coordinate_type\r
+ <\r
+ segment_type\r
+ >::type coordinate_type;\r
+\r
+ static inline coordinate_type get(segment_type const& s)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( s.second != NULL );\r
+ return geometry::get<Dimension>(*s.second);\r
+ }\r
+\r
+ static inline void set(segment_type& s, coordinate_type const& value)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( s.second != NULL );\r
+ geometry::set<Dimension>(*s.second, value);\r
+ }\r
+};\r
+\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINTING_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include <boost/concept/assert.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/geometries/ring.hpp>\r
+\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+#include <initializer_list>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+/*!\r
+\brief The polygon contains an outer ring and zero or more inner rings.\r
+\ingroup geometries\r
+\tparam Point point type\r
+\tparam ClockWise true for clockwise direction,\r
+ false for CounterClockWise direction\r
+\tparam Closed true for closed polygons (last point == first point),\r
+ false open points\r
+\tparam PointList container type for points,\r
+ for example std::vector, std::list, std::deque\r
+\tparam RingList container type for inner rings,\r
+ for example std::vector, std::list, std::deque\r
+\tparam PointAlloc container-allocator-type, for the points\r
+\tparam RingAlloc container-allocator-type, for the rings\r
+\note The container collecting the points in the rings can be different\r
+ from the container collecting the inner rings. They all default to vector.\r
+\r
+\qbk{[include reference/geometries/polygon.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_polygon Polygon Concept]\r
+}\r
+\r
+\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise = true,\r
+ bool Closed = true,\r
+ template<typename, typename> class PointList = std::vector,\r
+ template<typename, typename> class RingList = std::vector,\r
+ template<typename> class PointAlloc = std::allocator,\r
+ template<typename> class RingAlloc = std::allocator\r
+>\r
+class polygon\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+public:\r
+\r
+ // Member types\r
+ typedef Point point_type;\r
+ typedef ring<Point, ClockWise, Closed, PointList, PointAlloc> ring_type;\r
+ typedef RingList<ring_type , RingAlloc<ring_type > > inner_container_type;\r
+\r
+ inline ring_type const& outer() const { return m_outer; }\r
+ inline inner_container_type const& inners() const { return m_inners; }\r
+\r
+ inline ring_type& outer() { return m_outer; }\r
+ inline inner_container_type & inners() { return m_inners; }\r
+\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+\r
+ // default constructor definition is required only\r
+ // if the constructor taking std::initializer_list is defined\r
+\r
+ /// \constructor_default{polygon}\r
+ inline polygon()\r
+ : m_outer()\r
+ , m_inners()\r
+ {}\r
+\r
+ /// \constructor_initializer_list{polygon}\r
+ inline polygon(std::initializer_list<ring_type> l)\r
+ : m_outer(l.size() > 0 ? *l.begin() : ring_type())\r
+ , m_inners(l.size() > 0 ? l.begin() + 1 : l.begin(), l.end())\r
+ {}\r
+\r
+// Commented out for now in order to support Boost.Assign\r
+// Without this assignment operator first the object should be created\r
+// from initializer list, then it shoudl be moved.\r
+//// Without this workaround in MSVC the assignment operator is ambiguous\r
+//#ifndef BOOST_MSVC\r
+// /// \assignment_initializer_list{polygon}\r
+// inline polygon & operator=(std::initializer_list<ring_type> l)\r
+// {\r
+// if ( l.size() > 0 )\r
+// {\r
+// m_outer = *l.begin();\r
+// m_inners.assign(l.begin() + 1, l.end());\r
+// }\r
+// else\r
+// {\r
+// m_outer.clear();\r
+// m_inners.clear();\r
+// }\r
+// return *this;\r
+// }\r
+//#endif\r
+\r
+#endif\r
+\r
+ /// Utility method, clears outer and inner rings\r
+ inline void clear()\r
+ {\r
+ m_outer.clear();\r
+ m_inners.clear();\r
+ }\r
+\r
+private:\r
+\r
+ ring_type m_outer;\r
+ inner_container_type m_inners;\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct tag\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList, PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef polygon_tag type;\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct ring_const_type\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList, PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef typename model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >::ring_type const& type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct ring_mutable_type\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList, PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef typename model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >::ring_type& type;\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct interior_const_type\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef typename model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >::inner_container_type const& type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct interior_mutable_type\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef typename model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >::inner_container_type& type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct exterior_ring\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList, PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ > polygon_type;\r
+\r
+ static inline typename polygon_type::ring_type& get(polygon_type& p)\r
+ {\r
+ return p.outer();\r
+ }\r
+\r
+ static inline typename polygon_type::ring_type const& get(\r
+ polygon_type const& p)\r
+ {\r
+ return p.outer();\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class PointList,\r
+ template<typename, typename> class RingList,\r
+ template<typename> class PointAlloc,\r
+ template<typename> class RingAlloc\r
+>\r
+struct interior_rings\r
+<\r
+ model::polygon\r
+ <\r
+ Point, ClockWise, Closed,\r
+ PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ >\r
+>\r
+{\r
+ typedef model::polygon\r
+ <\r
+ Point, ClockWise, Closed, PointList, RingList,\r
+ PointAlloc, RingAlloc\r
+ > polygon_type;\r
+\r
+ static inline typename polygon_type::inner_container_type& get(\r
+ polygon_type& p)\r
+ {\r
+ return p.inners();\r
+ }\r
+\r
+ static inline typename polygon_type::inner_container_type const& get(\r
+ polygon_type const& p)\r
+ {\r
+ return p.inners();\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP\r
+\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \\r
+template <size_t D> \\r
+struct indexed_access<Box, min_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<Point>::type ct; \\r
+ static inline ct get(Box const& b) \\r
+ { return geometry::get<D>(b. MinCorner); } \\r
+ static inline void set(Box& b, ct const& value) \\r
+ { geometry::set<D>(b. MinCorner, value); } \\r
+}; \\r
+template <size_t D> \\r
+struct indexed_access<Box, max_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<Point>::type ct; \\r
+ static inline ct get(Box const& b) \\r
+ { return geometry::get<D>(b. MaxCorner); } \\r
+ static inline void set(Box& b, ct const& value) \\r
+ { geometry::set<D>(b. MaxCorner, value); } \\r
+};\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATED(Box, MinCorner, MaxCorner) \\r
+template <typename P, size_t D> \\r
+struct indexed_access<Box<P>, min_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<P>::type ct; \\r
+ static inline ct get(Box<P> const& b) \\r
+ { return geometry::get<D>(b. MinCorner); } \\r
+ static inline void set(Box<P>& b, ct const& value) \\r
+ { geometry::set<D>(b. MinCorner, value); } \\r
+}; \\r
+template <typename P, size_t D> \\r
+struct indexed_access<Box<P>, max_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<P>::type ct; \\r
+ static inline ct get(Box<P> const& b) \\r
+ { return geometry::get<D>(b. MaxCorner); } \\r
+ static inline void set(Box<P>& b, ct const& value) \\r
+ { geometry::set<D>(b. MaxCorner, value); } \\r
+};\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \\r
+template <> struct indexed_access<Box, min_corner, 0> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Box const& b) { return b. Left; } \\r
+ static inline void set(Box& b, ct const& value) { b. Left = value; } \\r
+}; \\r
+template <> struct indexed_access<Box, min_corner, 1> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Box const& b) { return b. Bottom; } \\r
+ static inline void set(Box& b, ct const& value) { b. Bottom = value; } \\r
+}; \\r
+template <> struct indexed_access<Box, max_corner, 0> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Box const& b) { return b. Right; } \\r
+ static inline void set(Box& b, ct const& value) { b. Right = value; } \\r
+}; \\r
+template <> struct indexed_access<Box, max_corner, 1> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Box const& b) { return b. Top; } \\r
+ static inline void set(Box& b, ct const& value) { b. Top = value; } \\r
+};\r
+\r
+\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \\r
+ template<> struct tag<Box > { typedef box_tag type; }; \\r
+ template<> struct point_type<Box > { typedef PointType type; };\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATED(Box) \\r
+ template<typename P> struct tag<Box<P> > { typedef box_tag type; }; \\r
+ template<typename P> struct point_type<Box<P> > { typedef P type; };\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+\r
+/*!\r
+\brief \brief_macro{box}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_BOX, box} The\r
+ box may contain template parameters, which must be specified then.\r
+\param Box \param_macro_type{Box}\r
+\param Point Point type on which box is based. Might be two or three-dimensional\r
+\param MinCorner minimum corner (should be public member or method)\r
+\param MaxCorner maximum corner (should be public member or method)\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_box]\r
+[register_box_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_BOX(Box, Point, MinCorner, MaxCorner) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, Point) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \\r
+}}}\r
+\r
+\r
+/*!\r
+\brief \brief_macro{box}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_BOX_TEMPLATED, box}\r
+ \details_macro_templated{box, point}\r
+\param Box \param_macro_type{Box}\r
+\param MinCorner minimum corner (should be public member or method)\r
+\param MaxCorner maximum corner (should be public member or method)\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_box_templated]\r
+[register_box_templated_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_BOX_TEMPLATED(Box, MinCorner, MaxCorner) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATED(Box) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATED(Box, MinCorner, MaxCorner) \\r
+}}}\r
+\r
+/*!\r
+\brief \brief_macro{box}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_BOX_2D_4VALUES, box}\r
+\param Box \param_macro_type{Box}\r
+\param Point Point type reported as point_type by box. Must be two dimensional.\r
+ Note that these box tyeps do not contain points, but they must have a\r
+ related point_type\r
+\param Left Left side (must be public member or method)\r
+\param Bottom Bottom side (must be public member or method)\r
+\param Right Right side (must be public member or method)\r
+\param Top Top side (must be public member or method)\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_box_2d_4values]\r
+[register_box_2d_4values_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_BOX_2D_4VALUES(Box, Point, Left, Bottom, Right, Top) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, Point) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \\r
+}}}\r
+\r
+\r
+\r
+// CONST versions are for boxes probably not that common. Postponed.\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP\r
+\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+/*!\r
+\brief \brief_macro{linestring}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_LINESTRING, linestring} The\r
+ linestring may contain template parameters, which must be specified then.\r
+\param Linestring \param_macro_type{linestring}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_linestring]\r
+[register_linestring_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_LINESTRING(Linestring) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<> struct tag<Linestring> { typedef linestring_tag type; }; \\r
+}}}\r
+\r
+\r
+/*!\r
+\brief \brief_macro{templated linestring}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED, templated linestring}\r
+ \details_macro_templated{linestring, point}\r
+\param Linestring \param_macro_type{linestring (without template parameters)}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_linestring_templated]\r
+[register_linestring_templated_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(Linestring) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<typename P> struct tag< Linestring<P> > { typedef linestring_tag type; }; \\r
+}}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+/*!\r
+\brief \brief_macro{multi_linestring}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING, multi_linestring} The\r
+ multi_linestring may contain template parameters, which must be specified then.\r
+\param MultiLineString \param_macro_type{multi_linestring}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_multi_linestring]\r
+[register_multi_linestring_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING(MultiLineString) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<> struct tag<MultiLineString> { typedef multi_linestring_tag type; }; \\r
+}}}\r
+\r
+\r
+/*!\r
+\brief \brief_macro{templated multi_linestring}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING_TEMPLATED, templated multi_linestring}\r
+ \details_macro_templated{multi_linestring, linestring}\r
+\param MultiLineString \param_macro_type{multi_linestring (without template parameters)}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_multi_linestring_templated]\r
+[register_multi_linestring_templated_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING_TEMPLATED(MultiLineString) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<typename LineString> struct tag< MultiLineString<LineString> > { typedef multi_linestring_tag type; }; \\r
+}}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_POINT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_POINT_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+/*!\r
+\brief \brief_macro{multi_point}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POINT, multi_point} The\r
+ multi_point may contain template parameters, which must be specified then.\r
+\param MultiPoint \param_macro_type{multi_point}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_multi_point]\r
+[register_multi_point_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_MULTI_POINT(MultiPoint) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<> struct tag<MultiPoint> { typedef multi_point_tag type; }; \\r
+}}}\r
+\r
+\r
+/*!\r
+\brief \brief_macro{templated multi_point}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED, templated multi_point}\r
+ \details_macro_templated{multi_point, point}\r
+\param MultiPoint \param_macro_type{multi_point (without template parameters)}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_multi_point_templated]\r
+[register_multi_point_templated_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED(MultiPoint) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<typename Point> struct tag< MultiPoint<Point> > { typedef multi_point_tag type; }; \\r
+}}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+/*!\r
+\brief \brief_macro{multi_polygon}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POLYGON, multi_polygon} The\r
+ multi_polygon may contain template parameters, which must be specified then.\r
+\param MultiPolygon \param_macro_type{multi_polygon}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_multi_polygon]\r
+[register_multi_polygon_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_MULTI_POLYGON(MultiPolygon) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<> struct tag<MultiPolygon> { typedef multi_polygon_tag type; }; \\r
+}}}\r
+\r
+\r
+/*!\r
+\brief \brief_macro{templated multi_polygon}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POLYGON_TEMPLATED, templated multi_polygon}\r
+ \details_macro_templated{multi_polygon, polygon}\r
+\param MultiPolygon \param_macro_type{multi_polygon (without template parameters)}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_multi_polygon_templated]\r
+[register_multi_polygon_templated_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_MULTI_POLYGON_TEMPLATED(MultiPolygon) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<typename Polygon> struct tag< MultiPolygon<Polygon> > { typedef multi_polygon_tag type; }; \\r
+}}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+// Starting point, specialize basic traits necessary to register a point\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, Dim, CoordinateType, CoordinateSystem) \\r
+ template<> struct tag<Point> { typedef point_tag type; }; \\r
+ template<> struct dimension<Point> : boost::mpl::int_<Dim> {}; \\r
+ template<> struct coordinate_type<Point> { typedef CoordinateType type; }; \\r
+ template<> struct coordinate_system<Point> { typedef CoordinateSystem type; };\r
+\r
+// Specialize access class per dimension\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, Dim, CoordinateType, Get, Set) \\r
+ template<> struct access<Point, Dim> \\r
+ { \\r
+ static inline CoordinateType get(Point const& p) { return p. Get; } \\r
+ static inline void set(Point& p, CoordinateType const& value) { p. Set = value; } \\r
+ };\r
+\r
+// Const version\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, Dim, CoordinateType, Get) \\r
+ template<> struct access<Point, Dim> \\r
+ { \\r
+ static inline CoordinateType get(Point const& p) { return p. Get; } \\r
+ };\r
+\r
+\r
+// Getter/setter version\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, Dim, CoordinateType, Get, Set) \\r
+ template<> struct access<Point, Dim> \\r
+ { \\r
+ static inline CoordinateType get(Point const& p) \\r
+ { return p. Get (); } \\r
+ static inline void set(Point& p, CoordinateType const& value) \\r
+ { p. Set ( value ); } \\r
+ };\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+/*!\r
+\brief \brief_macro{2D point type}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_2D, two-dimensional point type}\r
+\param Point \param_macro_type{Point}\r
+\param CoordinateType \param_macro_coortype{point}\r
+\param CoordinateSystem \param_macro_coorsystem\r
+\param Field0 \param_macro_member{\macro_x}\r
+\param Field1 \param_macro_member{\macro_y}\r
+\r
+\qbk{[include reference/geometries/register/point.qbk]}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_POINT_2D(Point, CoordinateType, CoordinateSystem, Field0, Field1) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 0, CoordinateType, Field0, Field0) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 1, CoordinateType, Field1, Field1) \\r
+}}}\r
+\r
+/*!\r
+\brief \brief_macro{3D point type}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_3D, three-dimensional point type}\r
+\param Point \param_macro_type{Point}\r
+\param CoordinateType \param_macro_coortype{point}\r
+\param CoordinateSystem \param_macro_coorsystem\r
+\param Field0 \param_macro_member{\macro_x}\r
+\param Field1 \param_macro_member{\macro_y}\r
+\param Field2 \param_macro_member{\macro_z}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_POINT_3D(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 0, CoordinateType, Field0, Field0) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 1, CoordinateType, Field1, Field1) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 2, CoordinateType, Field2, Field2) \\r
+}}}\r
+\r
+/*!\r
+\brief \brief_macro{2D point type} \brief_macro_const\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_2D_CONST, two-dimensional point type}. \details_macro_const\r
+\param Point \param_macro_type{Point}\r
+\param CoordinateType \param_macro_coortype{point}\r
+\param CoordinateSystem \param_macro_coorsystem\r
+\param Field0 \param_macro_member{\macro_x}\r
+\param Field1 \param_macro_member{\macro_y}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_POINT_2D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 0, CoordinateType, Field0) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 1, CoordinateType, Field1) \\r
+}}}\r
+\r
+/*!\r
+\brief \brief_macro{3D point type} \brief_macro_const\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_3D_CONST, three-dimensional point type}. \details_macro_const\r
+\param Point \param_macro_type{Point}\r
+\param CoordinateType \param_macro_coortype{point}\r
+\param CoordinateSystem \param_macro_coorsystem\r
+\param Field0 \param_macro_member{\macro_x}\r
+\param Field1 \param_macro_member{\macro_y}\r
+\param Field2 \param_macro_member{\macro_z}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_POINT_3D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 0, CoordinateType, Field0) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 1, CoordinateType, Field1) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 2, CoordinateType, Field2) \\r
+}}}\r
+\r
+/*!\r
+\brief \brief_macro{2D point type} \brief_macro_getset\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET, two-dimensional point type}. \details_macro_getset\r
+\param Point \param_macro_type{Point}\r
+\param CoordinateType \param_macro_coortype{point}\r
+\param CoordinateSystem \param_macro_coorsystem\r
+\param Get0 \param_macro_getset{get, \macro_x}\r
+\param Get1 \param_macro_getset{get, \macro_y}\r
+\param Set0 \param_macro_getset{set, \macro_x}\r
+\param Set1 \param_macro_getset{set, \macro_y}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Set0, Set1) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 0, CoordinateType, Get0, Set0) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 1, CoordinateType, Get1, Set1) \\r
+}}}\r
+\r
+/*!\r
+\brief \brief_macro{3D point type} \brief_macro_getset\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET, three-dimensional point type}. \details_macro_getset\r
+\param Point \param_macro_type{Point}\r
+\param CoordinateType \param_macro_coortype{point}\r
+\param CoordinateSystem \param_macro_coorsystem\r
+\param Get0 \param_macro_getset{get, \macro_x}\r
+\param Get1 \param_macro_getset{get, \macro_y}\r
+\param Get2 \param_macro_getset{get, \macro_z}\r
+\param Set0 \param_macro_getset{set, \macro_x}\r
+\param Set1 \param_macro_getset{set, \macro_y}\r
+\param Set2 \param_macro_getset{set, \macro_z}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Get2, Set0, Set1, Set2) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 0, CoordinateType, Get0, Set0) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 1, CoordinateType, Get1, Set1) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 2, CoordinateType, Get2, Set2) \\r
+}}}\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP\r
+\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+/*!\r
+\brief \brief_macro{ring}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_RING, ring} The\r
+ ring may contain template parameters, which must be specified then.\r
+\param Ring \param_macro_type{ring}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_ring]\r
+[register_ring_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_RING(Ring) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<> struct tag<Ring> { typedef ring_tag type; }; \\r
+}}}\r
+\r
+\r
+/*!\r
+\brief \brief_macro{templated ring}\r
+\ingroup register\r
+\details \details_macro{BOOST_GEOMETRY_REGISTER_RING_TEMPLATED, templated ring}\r
+ \details_macro_templated{ring, point}\r
+\param Ring \param_macro_type{ring (without template parameters)}\r
+\r
+\qbk{\r
+[heading Example]\r
+[register_ring_templated]\r
+[register_ring_templated_output]\r
+}\r
+*/\r
+#define BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(Ring) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ template<typename P> struct tag< Ring<P> > { typedef ring_tag type; }; \\r
+}}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP\r
+\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, Point, Index0, Index1) \\r
+template <size_t D> \\r
+struct indexed_access<Segment, min_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<Point>::type ct; \\r
+ static inline ct get(Segment const& b) \\r
+ { return geometry::get<D>(b. Index0); } \\r
+ static inline void set(Segment& b, ct const& value) \\r
+ { geometry::set<D>(b. Index0, value); } \\r
+}; \\r
+template <size_t D> \\r
+struct indexed_access<Segment, max_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<Point>::type ct; \\r
+ static inline ct get(Segment const& b) \\r
+ { return geometry::get<D>(b. Index1); } \\r
+ static inline void set(Segment& b, ct const& value) \\r
+ { geometry::set<D>(b. Index1, value); } \\r
+};\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \\r
+template <typename P, size_t D> \\r
+struct indexed_access<Segment<P>, min_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<P>::type ct; \\r
+ static inline ct get(Segment<P> const& b) \\r
+ { return geometry::get<D>(b. Index0); } \\r
+ static inline void set(Segment<P>& b, ct const& value) \\r
+ { geometry::set<D>(b. Index0, value); } \\r
+}; \\r
+template <typename P, size_t D> \\r
+struct indexed_access<Segment<P>, max_corner, D> \\r
+{ \\r
+ typedef typename coordinate_type<P>::type ct; \\r
+ static inline ct get(Segment<P> const& b) \\r
+ { return geometry::get<D>(b. Index1); } \\r
+ static inline void set(Segment<P>& b, ct const& value) \\r
+ { geometry::set<D>(b. Index1, value); } \\r
+};\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, Point, Left, Bottom, Right, Top) \\r
+template <> struct indexed_access<Segment, min_corner, 0> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Segment const& b) { return b. Left; } \\r
+ static inline void set(Segment& b, ct const& value) { b. Left = value; } \\r
+}; \\r
+template <> struct indexed_access<Segment, min_corner, 1> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Segment const& b) { return b. Bottom; } \\r
+ static inline void set(Segment& b, ct const& value) { b. Bottom = value; } \\r
+}; \\r
+template <> struct indexed_access<Segment, max_corner, 0> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Segment const& b) { return b. Right; } \\r
+ static inline void set(Segment& b, ct const& value) { b. Right = value; } \\r
+}; \\r
+template <> struct indexed_access<Segment, max_corner, 1> \\r
+{ \\r
+ typedef coordinate_type<Point>::type ct; \\r
+ static inline ct get(Segment const& b) { return b. Top; } \\r
+ static inline void set(Segment& b, ct const& value) { b. Top = value; } \\r
+};\r
+\r
+\r
+\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \\r
+ template<> struct tag<Segment > { typedef segment_tag type; }; \\r
+ template<> struct point_type<Segment > { typedef PointType type; };\r
+\r
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \\r
+ template<typename P> struct tag<Segment<P> > { typedef segment_tag type; }; \\r
+ template<typename P> struct point_type<Segment<P> > { typedef P type; };\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+\r
+#define BOOST_GEOMETRY_REGISTER_SEGMENT(Segment, PointType, Index0, Index1) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, PointType, Index0, Index1) \\r
+}}}\r
+\r
+\r
+#define BOOST_GEOMETRY_REGISTER_SEGMENT_TEMPLATIZED(Segment, Index0, Index1) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \\r
+}}}\r
+\r
+#define BOOST_GEOMETRY_REGISTER_SEGMENT_2D_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \\r
+namespace boost { namespace geometry { namespace traits { \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \\r
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \\r
+}}}\r
+\r
+\r
+\r
+// CONST versions are for segments probably not that common. Postponed.\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_RING_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_RING_HPP\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include <boost/concept/assert.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+#include <boost/config.hpp>\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+#include <initializer_list>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+/*!\r
+\brief A ring (aka linear ring) is a closed line which should not be selfintersecting\r
+\ingroup geometries\r
+\tparam Point point type\r
+\tparam ClockWise true for clockwise direction,\r
+ false for CounterClockWise direction\r
+\tparam Closed true for closed polygons (last point == first point),\r
+ false open points\r
+\tparam Container container type, for example std::vector, std::deque\r
+\tparam Allocator container-allocator-type\r
+\r
+\qbk{[include reference/geometries/ring.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_ring Ring Concept]\r
+}\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise = true, bool Closed = true,\r
+ template<typename, typename> class Container = std::vector,\r
+ template<typename> class Allocator = std::allocator\r
+>\r
+class ring : public Container<Point, Allocator<Point> >\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ typedef Container<Point, Allocator<Point> > base_type;\r
+\r
+public :\r
+ /// \constructor_default{ring}\r
+ inline ring()\r
+ : base_type()\r
+ {}\r
+\r
+ /// \constructor_begin_end{ring}\r
+ template <typename Iterator>\r
+ inline ring(Iterator begin, Iterator end)\r
+ : base_type(begin, end)\r
+ {}\r
+\r
+#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST\r
+\r
+ /// \constructor_initializer_list{ring}\r
+ inline ring(std::initializer_list<Point> l)\r
+ : base_type(l.begin(), l.end())\r
+ {}\r
+\r
+// Commented out for now in order to support Boost.Assign\r
+// Without this assignment operator first the object should be created\r
+// from initializer list, then it shoudl be moved.\r
+//// Without this workaround in MSVC the assignment operator is ambiguous\r
+//#ifndef BOOST_MSVC\r
+// /// \assignment_initializer_list{ring}\r
+// inline ring & operator=(std::initializer_list<Point> l)\r
+// {\r
+// base_type::assign(l.begin(), l.end());\r
+// return *this;\r
+// }\r
+//#endif\r
+\r
+#endif\r
+};\r
+\r
+} // namespace model\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool ClockWise, bool Closed,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct tag<model::ring<Point, ClockWise, Closed, Container, Allocator> >\r
+{\r
+ typedef ring_tag type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool Closed,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct point_order<model::ring<Point, false, Closed, Container, Allocator> >\r
+{\r
+ static const order_selector value = counterclockwise;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool Closed,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct point_order<model::ring<Point, true, Closed, Container, Allocator> >\r
+{\r
+ static const order_selector value = clockwise;\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool PointOrder,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct closure<model::ring<Point, PointOrder, true, Container, Allocator> >\r
+{\r
+ static const closure_selector value = closed;\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool PointOrder,\r
+ template<typename, typename> class Container,\r
+ template<typename> class Allocator\r
+>\r
+struct closure<model::ring<Point, PointOrder, false, Container, Allocator> >\r
+{\r
+ static const closure_selector value = open;\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/concept/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace model\r
+{\r
+\r
+/*!\r
+\brief Class segment: small class containing two points\r
+\ingroup geometries\r
+\details From Wikipedia: In geometry, a line segment is a part of a line that is bounded\r
+ by two distinct end points, and contains every point on the line between its end points.\r
+\note There is also a point-referring-segment, class referring_segment,\r
+ containing point references, where points are NOT copied\r
+\r
+\qbk{[include reference/geometries/segment.qbk]}\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_segment Segment Concept]\r
+}\r
+*/\r
+template<typename Point>\r
+class segment : public std::pair<Point, Point>\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+public :\r
+\r
+#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS\r
+ /// \constructor_default_no_init\r
+ segment() = default;\r
+#else\r
+ /// \constructor_default_no_init\r
+ inline segment()\r
+ {}\r
+#endif\r
+\r
+ /*!\r
+ \brief Constructor taking the first and the second point\r
+ */\r
+ inline segment(Point const& p1, Point const& p2)\r
+ {\r
+ this->first = p1;\r
+ this->second = p2;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Class segment: small class containing two (templatized) point references\r
+\ingroup geometries\r
+\details From Wikipedia: In geometry, a line segment is a part of a line that is bounded\r
+ by two distinct end points, and contains every point on the line between its end points.\r
+\note The structure is like std::pair, and can often be used interchangeable.\r
+Difference is that it refers to points, does not have points.\r
+\note Like std::pair, points are public available.\r
+\note type is const or non const, so geometry::segment<P> or geometry::segment<P const>\r
+\note We cannot derive from std::pair<P&, P&> because of\r
+reference assignments.\r
+\tparam ConstOrNonConstPoint point type of the segment, maybe a point or a const point\r
+*/\r
+template<typename ConstOrNonConstPoint>\r
+class referring_segment\r
+{\r
+ BOOST_CONCEPT_ASSERT( (\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_const<ConstOrNonConstPoint>,\r
+ concepts::Point<ConstOrNonConstPoint>,\r
+ concepts::ConstPoint<ConstOrNonConstPoint>\r
+ >\r
+ ) );\r
+\r
+ typedef ConstOrNonConstPoint point_type;\r
+\r
+public:\r
+\r
+ point_type& first;\r
+ point_type& second;\r
+\r
+ /*!\r
+ \brief Constructor taking the first and the second point\r
+ */\r
+ inline referring_segment(point_type& p1, point_type& p2)\r
+ : first(p1)\r
+ , second(p2)\r
+ {}\r
+};\r
+\r
+\r
+} // namespace model\r
+\r
+\r
+// Traits specializations for segment above\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename Point>\r
+struct tag<model::segment<Point> >\r
+{\r
+ typedef segment_tag type;\r
+};\r
+\r
+template <typename Point>\r
+struct point_type<model::segment<Point> >\r
+{\r
+ typedef Point type;\r
+};\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<model::segment<Point>, 0, Dimension>\r
+{\r
+ typedef model::segment<Point> segment_type;\r
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(segment_type const& s)\r
+ {\r
+ return geometry::get<Dimension>(s.first);\r
+ }\r
+\r
+ static inline void set(segment_type& s, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(s.first, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, std::size_t Dimension>\r
+struct indexed_access<model::segment<Point>, 1, Dimension>\r
+{\r
+ typedef model::segment<Point> segment_type;\r
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(segment_type const& s)\r
+ {\r
+ return geometry::get<Dimension>(s.second);\r
+ }\r
+\r
+ static inline void set(segment_type& s, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(s.second, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename ConstOrNonConstPoint>\r
+struct tag<model::referring_segment<ConstOrNonConstPoint> >\r
+{\r
+ typedef segment_tag type;\r
+};\r
+\r
+template <typename ConstOrNonConstPoint>\r
+struct point_type<model::referring_segment<ConstOrNonConstPoint> >\r
+{\r
+ typedef ConstOrNonConstPoint type;\r
+};\r
+\r
+template <typename ConstOrNonConstPoint, std::size_t Dimension>\r
+struct indexed_access<model::referring_segment<ConstOrNonConstPoint>, 0, Dimension>\r
+{\r
+ typedef model::referring_segment<ConstOrNonConstPoint> segment_type;\r
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(segment_type const& s)\r
+ {\r
+ return geometry::get<Dimension>(s.first);\r
+ }\r
+\r
+ static inline void set(segment_type& s, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(s.first, value);\r
+ }\r
+};\r
+\r
+\r
+template <typename ConstOrNonConstPoint, std::size_t Dimension>\r
+struct indexed_access<model::referring_segment<ConstOrNonConstPoint>, 1, Dimension>\r
+{\r
+ typedef model::referring_segment<ConstOrNonConstPoint> segment_type;\r
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(segment_type const& s)\r
+ {\r
+ return geometry::get<Dimension>(s.second);\r
+ }\r
+\r
+ static inline void set(segment_type& s, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension>(s.second, value);\r
+ }\r
+};\r
+\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP\r
+\r
+\r
+#include <boost/variant/variant_fwd.hpp>\r
+#include <boost/mpl/front.hpp>\r
+\r
+\r
+namespace boost { namespace geometry {\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct point_type<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+ : point_type<\r
+ typename boost::mpl::front<\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types\r
+ >::type\r
+ >\r
+{};\r
+\r
+\r
+} // namespace geometry\r
+} // namespace boost\r
+\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015, 2016.\r
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_GEOMETRY_HPP\r
+\r
+// Shortcut to include all header files\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/interior_type.hpp>\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+// Core algorithms\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/topological_dimension.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/arithmetic/dot_product.hpp>\r
+\r
+#include <boost/geometry/strategies/strategies.hpp>\r
+\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/area.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/buffer.hpp>\r
+#include <boost/geometry/algorithms/centroid.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/comparable_distance.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/convex_hull.hpp>\r
+#include <boost/geometry/algorithms/correct.hpp>\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/crosses.hpp>\r
+#include <boost/geometry/algorithms/difference.hpp>\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+#include <boost/geometry/algorithms/distance.hpp>\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/for_each.hpp>\r
+#include <boost/geometry/algorithms/intersection.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+#include <boost/geometry/algorithms/is_simple.hpp>\r
+#include <boost/geometry/algorithms/is_valid.hpp>\r
+#include <boost/geometry/algorithms/length.hpp>\r
+#include <boost/geometry/algorithms/make.hpp>\r
+#include <boost/geometry/algorithms/num_geometries.hpp>\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+#include <boost/geometry/algorithms/num_segments.hpp>\r
+#include <boost/geometry/algorithms/overlaps.hpp>\r
+#include <boost/geometry/algorithms/perimeter.hpp>\r
+#include <boost/geometry/algorithms/relate.hpp>\r
+#include <boost/geometry/algorithms/relation.hpp>\r
+#include <boost/geometry/algorithms/remove_spikes.hpp>\r
+#include <boost/geometry/algorithms/reverse.hpp>\r
+#include <boost/geometry/algorithms/simplify.hpp>\r
+#include <boost/geometry/algorithms/sym_difference.hpp>\r
+#include <boost/geometry/algorithms/touches.hpp>\r
+#include <boost/geometry/algorithms/transform.hpp>\r
+#include <boost/geometry/algorithms/union.hpp>\r
+#include <boost/geometry/algorithms/unique.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+// check includes all concepts\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/util/for_each_coordinate.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/views/box_view.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/views/identity_view.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+#include <boost/geometry/views/segment_view.hpp>\r
+\r
+#include <boost/geometry/io/io.hpp>\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+#include <boost/geometry/io/svg/svg_mapper.hpp>\r
+#include <boost/geometry/io/svg/write.hpp>\r
+#include <boost/geometry/io/wkt/read.hpp>\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Query range adaptor\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP\r
+#define BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP\r
+\r
+/*!\r
+\defgroup adaptors Adaptors (boost::geometry::index::adaptors::)\r
+*/\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace adaptors {\r
+\r
+namespace detail {\r
+\r
+template <typename Index>\r
+class query_range\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_INDEX,\r
+ (query_range));\r
+\r
+ typedef int* iterator;\r
+ typedef const int* const_iterator;\r
+\r
+ template <typename Predicates>\r
+ inline query_range(\r
+ Index const&,\r
+ Predicates const&)\r
+ {}\r
+\r
+ inline iterator begin() { return 0; }\r
+ inline iterator end() { return 0; }\r
+ inline const_iterator begin() const { return 0; }\r
+ inline const_iterator end() const { return 0; }\r
+};\r
+\r
+// TODO: awulkiew - consider removing reference from predicates\r
+\r
+template<typename Predicates>\r
+struct query\r
+{\r
+ inline explicit query(Predicates const& pred)\r
+ : predicates(pred)\r
+ {}\r
+\r
+ Predicates const& predicates;\r
+};\r
+\r
+template<typename Index, typename Predicates>\r
+index::adaptors::detail::query_range<Index>\r
+operator|(\r
+ Index const& si,\r
+ index::adaptors::detail::query<Predicates> const& f)\r
+{\r
+ return index::adaptors::detail::query_range<Index>(si, f.predicates);\r
+}\r
+\r
+} // namespace detail\r
+\r
+/*!\r
+\brief The query index adaptor generator.\r
+\r
+\ingroup adaptors\r
+\r
+\param pred Predicates.\r
+*/\r
+template <typename Predicates>\r
+detail::query<Predicates>\r
+queried(Predicates const& pred)\r
+{\r
+ return detail::query<Predicates>(pred);\r
+}\r
+\r
+} // namespace adaptors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// n-dimensional bounds\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP\r
+\r
+#include <boost/geometry/index/detail/bounded_view.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+namespace dispatch {\r
+\r
+template <typename Geometry,\r
+ typename Bounds,\r
+ typename TagGeometry = typename geometry::tag<Geometry>::type,\r
+ typename TagBounds = typename geometry::tag<Bounds>::type>\r
+struct bounds\r
+{\r
+ static inline void apply(Geometry const& g, Bounds & b)\r
+ {\r
+ geometry::convert(g, b);\r
+ }\r
+};\r
+\r
+template <typename Geometry, typename Bounds>\r
+struct bounds<Geometry, Bounds, segment_tag, box_tag>\r
+{\r
+ static inline void apply(Geometry const& g, Bounds & b)\r
+ {\r
+ index::detail::bounded_view<Geometry, Bounds> v(g);\r
+ geometry::convert(v, b);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Geometry, typename Bounds>\r
+inline void bounds(Geometry const& g, Bounds & b)\r
+{\r
+ concepts::check_concepts_and_equal_dimensions<Geometry const, Bounds>();\r
+ dispatch::bounds<Geometry, Bounds>::apply(g, b);\r
+}\r
+\r
+namespace dispatch {\r
+\r
+template <typename Geometry,\r
+ typename TagGeometry = typename geometry::tag<Geometry>::type>\r
+struct return_ref_or_bounds\r
+{\r
+ typedef Geometry const& result_type;\r
+\r
+ static inline result_type apply(Geometry const& g)\r
+ {\r
+ return g;\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct return_ref_or_bounds<Geometry, segment_tag>\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef geometry::model::box<point_type> bounds_type;\r
+ typedef index::detail::bounded_view<Geometry, bounds_type> result_type;\r
+\r
+ static inline result_type apply(Geometry const& g)\r
+ {\r
+ return result_type(g);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Geometry>\r
+inline\r
+typename dispatch::return_ref_or_bounds<Geometry>::result_type\r
+return_ref_or_bounds(Geometry const& g)\r
+{\r
+ return dispatch::return_ref_or_bounds<Geometry>::apply(g);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// squared distance between point and centroid of the box or point\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>\r
+#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+struct comparable_distance_centroid_tag {};\r
+\r
+template <\r
+ typename Point,\r
+ typename PointIndexable,\r
+ size_t N>\r
+struct sum_for_indexable<Point, PointIndexable, point_tag, comparable_distance_centroid_tag, N>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, PointIndexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, PointIndexable const& i)\r
+ {\r
+ return geometry::comparable_distance(pt, i);\r
+ }\r
+};\r
+\r
+template <\r
+ typename Point,\r
+ typename BoxIndexable,\r
+ size_t DimensionIndex>\r
+struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_centroid_tag, DimensionIndex>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, BoxIndexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, BoxIndexable const& i)\r
+ {\r
+ typedef typename coordinate_type<Point>::type point_coord_t;\r
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;\r
+\r
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);\r
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);\r
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);\r
+ \r
+ indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;\r
+ // TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?\r
+\r
+ result_type diff = detail::diff_abs(ind_c_avg, pt_c);\r
+\r
+ return diff * diff;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+typename geometry::default_comparable_distance_result<Point, Indexable>::type\r
+comparable_distance_centroid(Point const& pt, Indexable const& i)\r
+{\r
+ return detail::sum_for_indexable<\r
+ Point,\r
+ Indexable,\r
+ typename tag<Indexable>::type,\r
+ detail::comparable_distance_centroid_tag,\r
+ dimension<Indexable>::value\r
+ >::apply(pt, i);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP\r
+\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// squared distance between point and furthest point of the box or point\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>\r
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+// minmaxdist component\r
+\r
+struct comparable_distance_far_tag {};\r
+\r
+template <\r
+ typename Point,\r
+ typename BoxIndexable,\r
+ size_t DimensionIndex>\r
+struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_far_tag, DimensionIndex>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, BoxIndexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, BoxIndexable const& i)\r
+ {\r
+ typedef typename coordinate_type<Point>::type point_coord_t;\r
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;\r
+\r
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);\r
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);\r
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);\r
+\r
+ result_type further_diff = 0;\r
+\r
+ if ( (ind_c_min + ind_c_max) / 2 <= pt_c )\r
+ further_diff = pt_c - ind_c_min;\r
+ else\r
+ further_diff = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection\r
+\r
+ return further_diff * further_diff;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+typename geometry::default_comparable_distance_result<Point, Indexable>::type\r
+comparable_distance_far(Point const& pt, Indexable const& i)\r
+{\r
+ return detail::sum_for_indexable<\r
+ Point,\r
+ Indexable,\r
+ typename tag<Indexable>::type,\r
+ detail::comparable_distance_far_tag,\r
+ dimension<Indexable>::value\r
+ >::apply(pt, i);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// squared distance between point and nearest point of the box or point\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+struct comparable_distance_near_tag {};\r
+\r
+template <\r
+ typename Point,\r
+ typename PointIndexable,\r
+ size_t N>\r
+struct sum_for_indexable<Point, PointIndexable, point_tag, comparable_distance_near_tag, N>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, PointIndexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, PointIndexable const& i)\r
+ {\r
+ return geometry::comparable_distance(pt, i);\r
+ }\r
+};\r
+\r
+template <\r
+ typename Point,\r
+ typename BoxIndexable,\r
+ size_t DimensionIndex>\r
+struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_near_tag, DimensionIndex>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, BoxIndexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, BoxIndexable const& i)\r
+ {\r
+ typedef typename coordinate_type<Point>::type point_coord_t;\r
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;\r
+\r
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);\r
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);\r
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);\r
+\r
+ result_type diff = 0;\r
+\r
+ if ( pt_c < ind_c_min )\r
+ diff = ind_c_min - pt_c;\r
+ else if ( ind_c_max < pt_c )\r
+ diff = pt_c - ind_c_max;\r
+\r
+ return diff * diff;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+typename geometry::default_comparable_distance_result<Point, Indexable>::type\r
+comparable_distance_near(Point const& pt, Indexable const& i)\r
+{\r
+ return detail::sum_for_indexable<\r
+ Point,\r
+ Indexable,\r
+ typename tag<Indexable>::type,\r
+ detail::comparable_distance_near_tag,\r
+ dimension<Indexable>::value\r
+ >::apply(pt, i);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// n-dimensional content (hypervolume) - 2d area, 3d volume, ...\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename Indexable>\r
+struct default_content_result\r
+{\r
+ typedef typename select_most_precise<\r
+ typename coordinate_type<Indexable>::type,\r
+ long double\r
+ >::type type;\r
+};\r
+\r
+namespace dispatch {\r
+\r
+template <typename Box,\r
+ std::size_t CurrentDimension = dimension<Box>::value>\r
+struct content_box\r
+{\r
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+\r
+ static inline typename detail::default_content_result<Box>::type apply(Box const& b)\r
+ {\r
+ return content_box<Box, CurrentDimension - 1>::apply(b) *\r
+ ( get<max_corner, CurrentDimension - 1>(b) - get<min_corner, CurrentDimension - 1>(b) );\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct content_box<Box, 1>\r
+{\r
+ static inline typename detail::default_content_result<Box>::type apply(Box const& b)\r
+ {\r
+ return get<max_corner, 0>(b) - get<min_corner, 0>(b);\r
+ }\r
+};\r
+\r
+template <typename Indexable, typename Tag>\r
+struct content\r
+{\r
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_AND_TAG, (Indexable, Tag));\r
+};\r
+\r
+template <typename Indexable>\r
+struct content<Indexable, point_tag>\r
+{\r
+ static typename detail::default_content_result<Indexable>::type apply(Indexable const&)\r
+ {\r
+ return 0;\r
+ }\r
+};\r
+\r
+template <typename Indexable>\r
+struct content<Indexable, box_tag>\r
+{\r
+ static typename default_content_result<Indexable>::type apply(Indexable const& b)\r
+ {\r
+ return dispatch::content_box<Indexable>::apply(b);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Indexable>\r
+typename default_content_result<Indexable>::type content(Indexable const& b)\r
+{\r
+ return dispatch::content\r
+ <\r
+ Indexable,\r
+ typename tag<Indexable>::type\r
+ >::apply(b);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Abs of difference\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename T>\r
+inline T diff_abs_dispatch(T const& v1, T const& v2, boost::mpl::bool_<true> const& /*is_integral*/)\r
+{\r
+ return v1 < v2 ? v2 - v1 : v1 - v2;\r
+}\r
+\r
+template <typename T>\r
+inline T diff_abs_dispatch(T const& v1, T const& v2, boost::mpl::bool_<false> const& /*is_integral*/)\r
+{\r
+ return ::fabs(v1 - v2);\r
+}\r
+\r
+template <typename T>\r
+inline T diff_abs(T const& v1, T const& v2)\r
+{\r
+ typedef boost::mpl::bool_<\r
+ boost::is_integral<T>::value\r
+ > is_integral;\r
+ return diff_abs_dispatch(v1, v2, is_integral());\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// boxes union/intersection area/volume\r
+//\r
+// Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP\r
+\r
+#include <boost/geometry/algorithms/intersection.hpp>\r
+#include <boost/geometry/strategies/intersection_strategies.hpp>\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+/**\r
+ * \brief Compute the area of the intersection of b1 and b2\r
+ */\r
+template <typename Box>\r
+inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)\r
+{\r
+ if ( geometry::intersects(box1, box2) )\r
+ {\r
+ Box box_intersection;\r
+ if ( geometry::intersection(box1, box2, box_intersection) )\r
+ return detail::content(box_intersection);\r
+ }\r
+ return 0;\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// n-dimensional Indexable validity check\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_IS_VALID_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_IS_VALID_HPP\r
+\r
+#include <cstddef>\r
+#include <boost/geometry/core/access.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+namespace dispatch {\r
+\r
+template <typename Box,\r
+ std::size_t Dimension = geometry::dimension<Box>::value>\r
+struct is_valid_box\r
+{\r
+ static inline bool apply(Box const& b)\r
+ {\r
+ return is_valid_box<Box, Dimension - 1>::apply(b) &&\r
+ ( get<min_corner, Dimension - 1>(b) <= get<max_corner, Dimension - 1>(b) );\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct is_valid_box<Box, 1>\r
+{\r
+ static inline bool apply(Box const& b)\r
+ {\r
+ return get<min_corner, 0>(b) <= get<max_corner, 0>(b);\r
+ }\r
+};\r
+\r
+template <typename Indexable,\r
+ typename Tag = typename geometry::tag<Indexable>::type>\r
+struct is_valid\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE,\r
+ (is_valid));\r
+};\r
+\r
+template <typename Indexable>\r
+struct is_valid<Indexable, point_tag>\r
+{\r
+ static inline bool apply(Indexable const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Indexable>\r
+struct is_valid<Indexable, box_tag>\r
+{\r
+ static inline bool apply(Indexable const& b)\r
+ {\r
+ return dispatch::is_valid_box<Indexable>::apply(b);\r
+ }\r
+};\r
+\r
+template <typename Indexable>\r
+struct is_valid<Indexable, segment_tag>\r
+{\r
+ static inline bool apply(Indexable const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Indexable>\r
+inline bool is_valid(Indexable const& b)\r
+{\r
+ // CONSIDER: detection of NaNs\r
+ // e.g. by comparison of b with copy of b\r
+\r
+ return dispatch::is_valid<Indexable>::apply(b);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_DETAIL_INDEX_ALGORITHMS_IS_VALID_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// n-dimensional box's margin value (hypersurface), 2d perimeter, 3d surface, etc...\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP\r
+\r
+// WARNING! comparable_margin() will work only if the same Geometries are compared\r
+// so it shouldn't be used in the case of Variants!\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename Box>\r
+struct default_margin_result\r
+{\r
+ typedef typename select_most_precise<\r
+ typename coordinate_type<Box>::type,\r
+ long double\r
+ >::type type;\r
+};\r
+\r
+//template <typename Box,\r
+// std::size_t CurrentDimension,\r
+// std::size_t EdgeDimension = dimension<Box>::value>\r
+//struct margin_for_each_edge\r
+//{\r
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+// BOOST_STATIC_ASSERT(0 < EdgeDimension);\r
+//\r
+// static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+// {\r
+// return margin_for_each_edge<Box, CurrentDimension, EdgeDimension - 1>::apply(b) *\r
+// ( geometry::get<max_corner, EdgeDimension - 1>(b) - geometry::get<min_corner, EdgeDimension - 1>(b) );\r
+// }\r
+//};\r
+//\r
+//template <typename Box, std::size_t CurrentDimension>\r
+//struct margin_for_each_edge<Box, CurrentDimension, CurrentDimension>\r
+//{\r
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+//\r
+// static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+// {\r
+// return margin_for_each_edge<Box, CurrentDimension, CurrentDimension - 1>::apply(b);\r
+// }\r
+//};\r
+//\r
+//template <typename Box, std::size_t CurrentDimension>\r
+//struct margin_for_each_edge<Box, CurrentDimension, 1>\r
+//{\r
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+//\r
+// static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+// {\r
+// return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);\r
+// }\r
+//};\r
+//\r
+//template <typename Box>\r
+//struct margin_for_each_edge<Box, 1, 1>\r
+//{\r
+// static inline typename default_margin_result<Box>::type apply(Box const& /*b*/)\r
+// {\r
+// return 1;\r
+// }\r
+//};\r
+//\r
+//template <typename Box,\r
+// std::size_t CurrentDimension = dimension<Box>::value>\r
+//struct margin_for_each_dimension\r
+//{\r
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+//\r
+// static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+// {\r
+// return margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +\r
+// margin_for_each_edge<Box, CurrentDimension>::apply(b);\r
+// }\r
+//};\r
+//\r
+//template <typename Box>\r
+//struct margin_for_each_dimension<Box, 1>\r
+//{\r
+// static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+// {\r
+// return margin_for_each_edge<Box, 1>::apply(b);\r
+// }\r
+//};\r
+\r
+// TODO - test if this definition of margin is ok for Dimension > 2\r
+// Now it's sum of edges lengths\r
+// maybe margin_for_each_dimension should be used to get more or less hypersurface?\r
+\r
+template <typename Box,\r
+ std::size_t CurrentDimension = dimension<Box>::value>\r
+struct simple_margin_for_each_dimension\r
+{\r
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+\r
+ static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+ {\r
+ return simple_margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +\r
+ geometry::get<max_corner, CurrentDimension - 1>(b) - geometry::get<min_corner, CurrentDimension - 1>(b);\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct simple_margin_for_each_dimension<Box, 1>\r
+{\r
+ static inline typename default_margin_result<Box>::type apply(Box const& b)\r
+ {\r
+ return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);\r
+ }\r
+};\r
+\r
+namespace dispatch {\r
+\r
+template <typename Geometry, typename Tag>\r
+struct comparable_margin\r
+{\r
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (Geometry, Tag));\r
+};\r
+\r
+template <typename Geometry>\r
+struct comparable_margin<Geometry, point_tag>\r
+{\r
+ typedef typename default_margin_result<Geometry>::type result_type;\r
+\r
+ static inline result_type apply(Geometry const& ) { return 0; }\r
+};\r
+\r
+template <typename Box>\r
+struct comparable_margin<Box, box_tag>\r
+{\r
+ typedef typename default_margin_result<Box>::type result_type;\r
+\r
+ static inline result_type apply(Box const& g)\r
+ {\r
+ //return detail::margin_for_each_dimension<Box>::apply(g);\r
+ return detail::simple_margin_for_each_dimension<Box>::apply(g);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Geometry>\r
+typename default_margin_result<Geometry>::type comparable_margin(Geometry const& g)\r
+{\r
+ return dispatch::comparable_margin<\r
+ Geometry,\r
+ typename tag<Geometry>::type\r
+ >::apply(g);\r
+}\r
+\r
+//template <typename Box>\r
+//typename default_margin_result<Box>::type margin(Box const& b)\r
+//{\r
+// return 2 * detail::margin_for_each_dimension<Box>::apply(b);\r
+//}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// minmaxdist used in R-tree k nearest neighbors query\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP\r
+\r
+#include <boost/geometry/algorithms/distance.hpp>\r
+#include <boost/geometry/algorithms/comparable_distance.hpp>\r
+\r
+#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>\r
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>\r
+#include <boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+struct minmaxdist_tag {};\r
+\r
+template <\r
+ typename Point,\r
+ typename BoxIndexable,\r
+ size_t DimensionIndex>\r
+struct smallest_for_indexable_dimension<Point, BoxIndexable, box_tag, minmaxdist_tag, DimensionIndex>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, BoxIndexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, BoxIndexable const& i, result_type const& maxd)\r
+ {\r
+ typedef typename coordinate_type<Point>::type point_coord_t;\r
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;\r
+\r
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);\r
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);\r
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);\r
+\r
+ indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;\r
+ // TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?\r
+\r
+ // TODO: awulkiew - optimize! don't calculate 2x pt_c <= ind_c_avg\r
+ // take particular case pt_c == ind_c_avg into account\r
+\r
+ result_type closer_comp = 0;\r
+ if ( pt_c <= ind_c_avg )\r
+ closer_comp = detail::diff_abs(pt_c, ind_c_min); // unsigned values protection\r
+ else\r
+ closer_comp = ind_c_max - pt_c;\r
+ \r
+ result_type further_comp = 0;\r
+ if ( ind_c_avg <= pt_c )\r
+ further_comp = pt_c - ind_c_min;\r
+ else\r
+ further_comp = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection\r
+\r
+ return (maxd + closer_comp * closer_comp) - further_comp * further_comp;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable, typename IndexableTag>\r
+struct minmaxdist_impl\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,\r
+ (minmaxdist_impl));\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+struct minmaxdist_impl<Point, Indexable, point_tag>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, Indexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, Indexable const& i)\r
+ {\r
+ return geometry::comparable_distance(pt, i);\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+struct minmaxdist_impl<Point, Indexable, box_tag>\r
+{\r
+ typedef typename geometry::default_comparable_distance_result<Point, Indexable>::type result_type;\r
+\r
+ inline static result_type apply(Point const& pt, Indexable const& i)\r
+ {\r
+ result_type maxd = geometry::comparable_distance(pt, i);\r
+\r
+ return smallest_for_indexable<\r
+ Point,\r
+ Indexable,\r
+ box_tag,\r
+ minmaxdist_tag,\r
+ dimension<Indexable>::value\r
+ >::apply(pt, i, maxd);\r
+ }\r
+};\r
+\r
+/**\r
+ * This is comparable distace.\r
+ */\r
+template <typename Point, typename Indexable>\r
+typename geometry::default_comparable_distance_result<Point, Indexable>::type\r
+minmaxdist(Point const& pt, Indexable const& i)\r
+{\r
+ return detail::minmaxdist_impl<\r
+ Point,\r
+ Indexable,\r
+ typename tag<Indexable>::type\r
+ >::apply(pt, i);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// n-dimensional box-linestring intersection\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+namespace dispatch {\r
+\r
+template <typename Indexable, typename Geometry, typename IndexableTag, typename GeometryTag>\r
+struct path_intersection\r
+{\r
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_OR_INDEXABLE, (path_intersection));\r
+};\r
+\r
+// TODO: FP type must be used as a relative distance type!\r
+// and default_distance_result can be some user-defined int type\r
+// BUT! This code is experimental and probably won't be released at all\r
+// since more flexible user-defined-nearest predicate should be added instead\r
+\r
+template <typename Indexable, typename Segment>\r
+struct path_intersection<Indexable, Segment, box_tag, segment_tag>\r
+{\r
+ typedef typename default_distance_result<typename point_type<Segment>::type>::type comparable_distance_type;\r
+\r
+ static inline bool apply(Indexable const& b, Segment const& segment, comparable_distance_type & comparable_distance)\r
+ {\r
+ typedef typename point_type<Segment>::type point_type;\r
+ point_type p1, p2;\r
+ geometry::detail::assign_point_from_index<0>(segment, p1);\r
+ geometry::detail::assign_point_from_index<1>(segment, p2);\r
+ return index::detail::segment_intersection(b, p1, p2, comparable_distance);\r
+ }\r
+};\r
+\r
+template <typename Indexable, typename Linestring>\r
+struct path_intersection<Indexable, Linestring, box_tag, linestring_tag>\r
+{\r
+ typedef typename default_length_result<Linestring>::type comparable_distance_type;\r
+\r
+ static inline bool apply(Indexable const& b, Linestring const& path, comparable_distance_type & comparable_distance)\r
+ {\r
+ typedef typename ::boost::range_value<Linestring>::type point_type;\r
+ typedef typename ::boost::range_const_iterator<Linestring>::type const_iterator; \r
+ typedef typename ::boost::range_size<Linestring>::type size_type;\r
+ \r
+ const size_type count = ::boost::size(path);\r
+\r
+ if ( count == 2 )\r
+ {\r
+ return index::detail::segment_intersection(b, *::boost::begin(path), *(::boost::begin(path)+1), comparable_distance);\r
+ }\r
+ else if ( 2 < count )\r
+ {\r
+ const_iterator it0 = ::boost::begin(path);\r
+ const_iterator it1 = ::boost::begin(path) + 1;\r
+ const_iterator last = ::boost::end(path);\r
+\r
+ comparable_distance = 0;\r
+\r
+ for ( ; it1 != last ; ++it0, ++it1 )\r
+ {\r
+ typename default_distance_result<point_type, point_type>::type\r
+ dist = geometry::distance(*it0, *it1);\r
+\r
+ comparable_distance_type rel_dist;\r
+ if ( index::detail::segment_intersection(b, *it0, *it1, rel_dist) )\r
+ {\r
+ comparable_distance += dist * rel_dist;\r
+ return true;\r
+ }\r
+ else\r
+ comparable_distance += dist;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Indexable, typename SegmentOrLinestring>\r
+struct default_path_intersection_distance_type\r
+{\r
+ typedef typename dispatch::path_intersection<\r
+ Indexable, SegmentOrLinestring,\r
+ typename tag<Indexable>::type,\r
+ typename tag<SegmentOrLinestring>::type\r
+ >::comparable_distance_type type;\r
+};\r
+\r
+template <typename Indexable, typename SegmentOrLinestring> inline\r
+bool path_intersection(Indexable const& b,\r
+ SegmentOrLinestring const& path,\r
+ typename default_path_intersection_distance_type<Indexable, SegmentOrLinestring>::type & comparable_distance)\r
+{\r
+ // TODO check Indexable and Linestring concepts\r
+\r
+ return dispatch::path_intersection<\r
+ Indexable, SegmentOrLinestring,\r
+ typename tag<Indexable>::type,\r
+ typename tag<SegmentOrLinestring>::type\r
+ >::apply(b, path, comparable_distance);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// n-dimensional box-segment intersection\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+//template <typename Indexable, typename Point>\r
+//struct default_relative_distance_type\r
+//{\r
+// typedef typename select_most_precise<\r
+// typename select_most_precise<\r
+// typename coordinate_type<Indexable>::type,\r
+// typename coordinate_type<Point>::type\r
+// >::type,\r
+// float // TODO - use bigger type, calculated from the size of coordinate types\r
+// >::type type;\r
+//\r
+//\r
+// BOOST_MPL_ASSERT_MSG((!::boost::is_unsigned<type>::value),\r
+// THIS_TYPE_SHOULDNT_BE_UNSIGNED, (type));\r
+//};\r
+\r
+namespace dispatch {\r
+\r
+template <typename Box, typename Point, size_t I>\r
+struct box_segment_intersection_dim\r
+{\r
+ BOOST_STATIC_ASSERT(0 <= dimension<Box>::value);\r
+ BOOST_STATIC_ASSERT(0 <= dimension<Point>::value);\r
+ BOOST_STATIC_ASSERT(I < size_t(dimension<Box>::value));\r
+ BOOST_STATIC_ASSERT(I < size_t(dimension<Point>::value));\r
+ BOOST_STATIC_ASSERT(dimension<Point>::value == dimension<Box>::value);\r
+\r
+ // WARNING! - RelativeDistance must be IEEE float for this to work\r
+\r
+ template <typename RelativeDistance>\r
+ static inline bool apply(Box const& b, Point const& p0, Point const& p1,\r
+ RelativeDistance & t_near, RelativeDistance & t_far)\r
+ {\r
+ RelativeDistance ray_d = geometry::get<I>(p1) - geometry::get<I>(p0);\r
+ RelativeDistance tn = ( geometry::get<min_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;\r
+ RelativeDistance tf = ( geometry::get<max_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;\r
+ if ( tf < tn )\r
+ ::std::swap(tn, tf);\r
+\r
+ if ( t_near < tn )\r
+ t_near = tn;\r
+ if ( tf < t_far )\r
+ t_far = tf;\r
+\r
+ return 0 <= t_far && t_near <= t_far;\r
+ }\r
+};\r
+\r
+template <typename Box, typename Point, size_t CurrentDimension>\r
+struct box_segment_intersection\r
+{\r
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);\r
+\r
+ typedef box_segment_intersection_dim<Box, Point, CurrentDimension - 1> for_dim;\r
+\r
+ template <typename RelativeDistance>\r
+ static inline bool apply(Box const& b, Point const& p0, Point const& p1,\r
+ RelativeDistance & t_near, RelativeDistance & t_far)\r
+ {\r
+ return box_segment_intersection<Box, Point, CurrentDimension - 1>::apply(b, p0, p1, t_near, t_far)\r
+ && for_dim::apply(b, p0, p1, t_near, t_far);\r
+ }\r
+};\r
+\r
+template <typename Box, typename Point>\r
+struct box_segment_intersection<Box, Point, 1>\r
+{\r
+ typedef box_segment_intersection_dim<Box, Point, 0> for_dim;\r
+\r
+ template <typename RelativeDistance>\r
+ static inline bool apply(Box const& b, Point const& p0, Point const& p1,\r
+ RelativeDistance & t_near, RelativeDistance & t_far)\r
+ {\r
+ return for_dim::apply(b, p0, p1, t_near, t_far);\r
+ }\r
+};\r
+\r
+template <typename Indexable, typename Point, typename Tag>\r
+struct segment_intersection\r
+{\r
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (segment_intersection));\r
+};\r
+\r
+template <typename Indexable, typename Point>\r
+struct segment_intersection<Indexable, Point, point_tag>\r
+{\r
+ BOOST_MPL_ASSERT_MSG((false), SEGMENT_POINT_INTERSECTION_UNAVAILABLE, (segment_intersection));\r
+};\r
+\r
+template <typename Indexable, typename Point>\r
+struct segment_intersection<Indexable, Point, box_tag>\r
+{\r
+ typedef dispatch::box_segment_intersection<Indexable, Point, dimension<Indexable>::value> impl;\r
+\r
+ template <typename RelativeDistance>\r
+ static inline bool apply(Indexable const& b, Point const& p0, Point const& p1, RelativeDistance & relative_distance)\r
+ {\r
+\r
+// TODO: this ASSERT CHECK is wrong for user-defined CoordinateTypes!\r
+\r
+ static const bool check = !::boost::is_integral<RelativeDistance>::value;\r
+ BOOST_MPL_ASSERT_MSG(check, RELATIVE_DISTANCE_MUST_BE_FLOATING_POINT_TYPE, (RelativeDistance));\r
+\r
+ RelativeDistance t_near = -(::std::numeric_limits<RelativeDistance>::max)();\r
+ RelativeDistance t_far = (::std::numeric_limits<RelativeDistance>::max)();\r
+\r
+ return impl::apply(b, p0, p1, t_near, t_far) &&\r
+ (t_near <= 1) &&\r
+ ( relative_distance = 0 < t_near ? t_near : 0, true );\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Indexable, typename Point, typename RelativeDistance> inline\r
+bool segment_intersection(Indexable const& b,\r
+ Point const& p0,\r
+ Point const& p1,\r
+ RelativeDistance & relative_distance)\r
+{\r
+ // TODO check Indexable and Point concepts\r
+\r
+ return dispatch::segment_intersection<\r
+ Indexable, Point,\r
+ typename tag<Indexable>::type\r
+ >::apply(b, p0, p1, relative_distance);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Get smallest value calculated for indexable's dimensions, used in R-tree k nearest neighbors query\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <\r
+ typename Geometry,\r
+ typename Indexable,\r
+ typename IndexableTag,\r
+ typename AlgoTag,\r
+ size_t DimensionIndex>\r
+struct smallest_for_indexable_dimension\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,\r
+ (smallest_for_indexable_dimension));\r
+};\r
+\r
+template <\r
+ typename Geometry,\r
+ typename Indexable,\r
+ typename IndexableTag,\r
+ typename AlgoTag,\r
+ size_t N>\r
+struct smallest_for_indexable\r
+{\r
+ typedef typename smallest_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1\r
+ >::result_type result_type;\r
+\r
+ template <typename Data>\r
+ inline static result_type apply(Geometry const& g, Indexable const& i, Data const& data)\r
+ {\r
+ result_type r1 = smallest_for_indexable<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1\r
+ >::apply(g, i, data);\r
+\r
+ result_type r2 = smallest_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1\r
+ >::apply(g, i, data);\r
+\r
+ return r1 < r2 ? r1 : r2;\r
+ }\r
+};\r
+\r
+template <\r
+ typename Geometry,\r
+ typename Indexable,\r
+ typename IndexableTag,\r
+ typename AlgoTag>\r
+struct smallest_for_indexable<Geometry, Indexable, IndexableTag, AlgoTag, 1>\r
+{\r
+ typedef typename smallest_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, 0\r
+ >::result_type result_type;\r
+\r
+ template <typename Data>\r
+ inline static result_type apply(Geometry const& g, Indexable const& i, Data const& data)\r
+ {\r
+ return\r
+ smallest_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, 0\r
+ >::apply(g, i, data);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Sum values calculated for indexable's dimensions, used e.g. in R-tree k nearest neighbors query\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <\r
+ typename Geometry,\r
+ typename Indexable,\r
+ typename IndexableTag,\r
+ typename AlgoTag,\r
+ size_t DimensionIndex>\r
+struct sum_for_indexable_dimension\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,\r
+ (sum_for_indexable_dimension));\r
+};\r
+\r
+template <\r
+ typename Geometry,\r
+ typename Indexable,\r
+ typename IndexableTag,\r
+ typename AlgoTag,\r
+ size_t N>\r
+struct sum_for_indexable\r
+{\r
+ typedef typename sum_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1\r
+ >::result_type result_type;\r
+\r
+ inline static result_type apply(Geometry const& g, Indexable const& i)\r
+ {\r
+ return\r
+ sum_for_indexable<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1\r
+ >::apply(g, i) +\r
+ sum_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1\r
+ >::apply(g, i);\r
+ }\r
+};\r
+\r
+template <\r
+ typename Geometry,\r
+ typename Indexable,\r
+ typename IndexableTag,\r
+ typename AlgoTag>\r
+struct sum_for_indexable<Geometry, Indexable, IndexableTag, AlgoTag, 1>\r
+{\r
+ typedef typename sum_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, 0\r
+ >::result_type result_type;\r
+\r
+ inline static result_type apply(Geometry const& g, Indexable const& i)\r
+ {\r
+ return\r
+ sum_for_indexable_dimension<\r
+ Geometry, Indexable, IndexableTag, AlgoTag, 0\r
+ >::apply(g, i);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// boxes union/sum area/volume\r
+//\r
+// Copyright (c) 2008 Federico J. Fernandez.\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP\r
+\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+/**\r
+ * \brief Compute the area of the union of b1 and b2\r
+ */\r
+template <typename Box, typename Geometry>\r
+inline typename default_content_result<Box>::type union_content(Box const& b, Geometry const& g)\r
+{\r
+ Box expanded_box(b);\r
+ geometry::expand(expanded_box, g);\r
+ return detail::content(expanded_box);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+#undef BOOST_GEOMETRY_INDEX_ASSERT\r
+\r
+#define BOOST_GEOMETRY_INDEX_ASSERT(CONDITION, TEXT_MSG) \\r
+ BOOST_GEOMETRY_ASSERT_MSG(CONDITION, TEXT_MSG)\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// This view makes possible to treat some simple primitives as its bounding geometry\r
+// e.g. box, nsphere, etc.\r
+//\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP\r
+\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+namespace index { namespace detail {\r
+\r
+template <typename Geometry,\r
+ typename BoundingGeometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type,\r
+ typename BoundingTag = typename geometry::tag<BoundingGeometry>::type,\r
+ typename CSystem = typename geometry::coordinate_system<Geometry>::type>\r
+struct bounded_view\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THOSE_GEOMETRIES,\r
+ (BoundingTag, Tag));\r
+};\r
+\r
+\r
+// Segment -> Box\r
+\r
+template <typename Segment, typename Box>\r
+struct bounded_view<Segment, Box, segment_tag, box_tag, cs::cartesian>\r
+{\r
+public:\r
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;\r
+\r
+ explicit bounded_view(Segment const& segment)\r
+ : m_segment(segment)\r
+ {}\r
+ \r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_min() const\r
+ {\r
+ return boost::numeric_cast<coordinate_type>(\r
+ (std::min)( geometry::get<0, Dimension>(m_segment),\r
+ geometry::get<1, Dimension>(m_segment) ) );\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_max() const\r
+ {\r
+ return boost::numeric_cast<coordinate_type>(\r
+ (std::max)( geometry::get<0, Dimension>(m_segment),\r
+ geometry::get<1, Dimension>(m_segment) ) );\r
+ }\r
+\r
+private:\r
+ Segment const& m_segment;\r
+};\r
+\r
+template <typename Segment, typename Box, typename CSystem>\r
+struct bounded_view<Segment, Box, segment_tag, box_tag, CSystem>\r
+{\r
+public:\r
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;\r
+\r
+ explicit bounded_view(Segment const& segment)\r
+ {\r
+ geometry::envelope(segment, m_box);\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_min() const\r
+ {\r
+ return geometry::get<min_corner, Dimension>(m_box);\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_max() const\r
+ {\r
+ return geometry::get<max_corner, Dimension>(m_box);\r
+ }\r
+\r
+private:\r
+ Box m_box;\r
+};\r
+\r
+// Box -> Box\r
+\r
+template <typename BoxIn, typename Box, typename CSystem>\r
+struct bounded_view<BoxIn, Box, box_tag, box_tag, CSystem>\r
+{\r
+public:\r
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;\r
+\r
+ explicit bounded_view(BoxIn const& box)\r
+ : m_box(box)\r
+ {}\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_min() const\r
+ {\r
+ return boost::numeric_cast<coordinate_type>(\r
+ geometry::get<min_corner, Dimension>(m_box) );\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_max() const\r
+ {\r
+ return boost::numeric_cast<coordinate_type>(\r
+ geometry::get<max_corner, Dimension>(m_box) );\r
+ }\r
+\r
+private:\r
+ BoxIn const& m_box;\r
+};\r
+\r
+// Point -> Box\r
+\r
+template <typename Point, typename Box, typename CSystem>\r
+struct bounded_view<Point, Box, point_tag, box_tag, CSystem>\r
+{\r
+public:\r
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;\r
+\r
+ explicit bounded_view(Point const& point)\r
+ : m_point(point)\r
+ {}\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_min() const\r
+ {\r
+ return boost::numeric_cast<coordinate_type>(\r
+ geometry::get<Dimension>(m_point) );\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get_max() const\r
+ {\r
+ return boost::numeric_cast<coordinate_type>(\r
+ geometry::get<Dimension>(m_point) );\r
+ }\r
+\r
+private:\r
+ Point const& m_point;\r
+};\r
+\r
+}} // namespace index::detail\r
+\r
+// XXX -> Box\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename Geometry, typename Box, typename Tag, typename CSystem>\r
+struct tag< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >\r
+{\r
+ typedef box_tag type;\r
+};\r
+\r
+template <typename Geometry, typename Box, typename Tag, typename CSystem>\r
+struct point_type< index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> >\r
+{\r
+ typedef typename point_type<Box>::type type;\r
+};\r
+\r
+template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>\r
+struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,\r
+ min_corner, Dimension>\r
+{\r
+ typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;\r
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(box_type const& b)\r
+ {\r
+ return b.template get_min<Dimension>();\r
+ }\r
+\r
+ //static inline void set(box_type & b, coordinate_type const& value)\r
+ //{\r
+ // BOOST_GEOMETRY_INDEX_ASSERT(false, "unable to modify a box through view");\r
+ //}\r
+};\r
+\r
+template <typename Geometry, typename Box, typename Tag, typename CSystem, std::size_t Dimension>\r
+struct indexed_access<index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem>,\r
+ max_corner, Dimension>\r
+{\r
+ typedef index::detail::bounded_view<Geometry, Box, Tag, box_tag, CSystem> box_type;\r
+ typedef typename geometry::coordinate_type<Box>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(box_type const& b)\r
+ {\r
+ return b.template get_max<Dimension>();\r
+ }\r
+\r
+ //static inline void set(box_type & b, coordinate_type const& value)\r
+ //{\r
+ // BOOST_GEOMETRY_INDEX_ASSERT(false, "unable to modify a box through view");\r
+ //}\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_BOUNDED_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#include <boost/config.hpp>\r
+\r
+#ifdef BOOST_MSVC\r
+\r
+ #pragma warning (push)\r
+ #pragma warning (disable : 4512) // assignment operator could not be generated\r
+ #pragma warning (disable : 4127) // conditional expression is constant\r
+\r
+ // temporary?\r
+ #pragma warning (disable : 4180) // qualifier applied to function type has no meaning\r
+\r
+#endif //BOOST_MSVC\r
+\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#if defined BOOST_MSVC\r
+ #pragma warning (pop)\r
+#endif\r
+\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Spatial index distance predicates, calculators and checkers\r
+// used in nearest query - specialized for envelopes\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_DISTANCE_PREDICATES_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_DISTANCE_PREDICATES_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/comparable_distance_near.hpp>\r
+#include <boost/geometry/index/detail/algorithms/comparable_distance_far.hpp>\r
+#include <boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp>\r
+#include <boost/geometry/index/detail/algorithms/path_intersection.hpp>\r
+\r
+#include <boost/geometry/index/detail/tags.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+// ------------------------------------------------------------------ //\r
+// relations\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename T>\r
+struct to_nearest\r
+{\r
+ to_nearest(T const& v) : value(v) {}\r
+ T value;\r
+};\r
+\r
+template <typename T>\r
+struct to_centroid\r
+{\r
+ to_centroid(T const& v) : value(v) {}\r
+ T value;\r
+};\r
+\r
+template <typename T>\r
+struct to_furthest\r
+{\r
+ to_furthest(T const& v) : value(v) {}\r
+ T value;\r
+};\r
+\r
+// tags\r
+\r
+struct to_nearest_tag {};\r
+struct to_centroid_tag {};\r
+struct to_furthest_tag {};\r
+\r
+// ------------------------------------------------------------------ //\r
+// relation traits and access\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename T>\r
+struct relation\r
+{\r
+ typedef T value_type;\r
+ typedef to_nearest_tag tag;\r
+ static inline T const& value(T const& v) { return v; }\r
+ static inline T & value(T & v) { return v; }\r
+};\r
+\r
+template <typename T>\r
+struct relation< to_nearest<T> >\r
+{\r
+ typedef T value_type;\r
+ typedef to_nearest_tag tag;\r
+ static inline T const& value(to_nearest<T> const& r) { return r.value; }\r
+ static inline T & value(to_nearest<T> & r) { return r.value; }\r
+};\r
+\r
+template <typename T>\r
+struct relation< to_centroid<T> >\r
+{\r
+ typedef T value_type;\r
+ typedef to_centroid_tag tag;\r
+ static inline T const& value(to_centroid<T> const& r) { return r.value; }\r
+ static inline T & value(to_centroid<T> & r) { return r.value; }\r
+};\r
+\r
+template <typename T>\r
+struct relation< to_furthest<T> >\r
+{\r
+ typedef T value_type;\r
+ typedef to_furthest_tag tag;\r
+ static inline T const& value(to_furthest<T> const& r) { return r.value; }\r
+ static inline T & value(to_furthest<T> & r) { return r.value; }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+// calculate_distance\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename Predicate, typename Indexable, typename Tag>\r
+struct calculate_distance\r
+{\r
+ BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance));\r
+};\r
+\r
+// this handles nearest() with default Point parameter, to_nearest() and bounds\r
+template <typename PointRelation, typename Indexable, typename Tag>\r
+struct calculate_distance< predicates::nearest<PointRelation>, Indexable, Tag >\r
+{\r
+ typedef detail::relation<PointRelation> relation;\r
+ typedef typename relation::value_type point_type;\r
+ typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;\r
+\r
+ static inline bool apply(predicates::nearest<PointRelation> const& p, Indexable const& i, result_type & result)\r
+ {\r
+ result = geometry::comparable_distance(relation::value(p.point_or_relation), i);\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+struct calculate_distance< predicates::nearest< to_centroid<Point> >, Indexable, value_tag>\r
+{\r
+ typedef Point point_type;\r
+ typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;\r
+\r
+ static inline bool apply(predicates::nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)\r
+ {\r
+ result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i);\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Indexable>\r
+struct calculate_distance< predicates::nearest< to_furthest<Point> >, Indexable, value_tag>\r
+{\r
+ typedef Point point_type;\r
+ typedef typename geometry::default_comparable_distance_result<point_type, Indexable>::type result_type;\r
+\r
+ static inline bool apply(predicates::nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)\r
+ {\r
+ result = index::detail::comparable_distance_far(p.point_or_relation.value, i);\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename SegmentOrLinestring, typename Indexable, typename Tag>\r
+struct calculate_distance< predicates::path<SegmentOrLinestring>, Indexable, Tag>\r
+{\r
+ typedef typename index::detail::default_path_intersection_distance_type<\r
+ Indexable, SegmentOrLinestring\r
+ >::type result_type;\r
+\r
+ static inline bool apply(predicates::path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)\r
+ {\r
+ return index::detail::path_intersection(i, p.geometry, result);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_RTREE_DISTANCE_PREDICATES_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP\r
+\r
+#include <boost/core/no_exceptions_support.hpp>\r
+\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+#include <stdexcept>\r
+#include <boost/throw_exception.hpp>\r
+#else\r
+#include <cstdlib>\r
+#include <boost/geometry/index/detail/assert.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+#ifndef BOOST_NO_EXCEPTIONS\r
+\r
+inline void throw_runtime_error(const char * str)\r
+{\r
+ BOOST_THROW_EXCEPTION(std::runtime_error(str));\r
+}\r
+\r
+inline void throw_logic_error(const char * str)\r
+{\r
+ BOOST_THROW_EXCEPTION(std::logic_error(str));\r
+}\r
+\r
+inline void throw_invalid_argument(const char * str)\r
+{\r
+ BOOST_THROW_EXCEPTION(std::invalid_argument(str));\r
+}\r
+\r
+inline void throw_length_error(const char * str)\r
+{\r
+ BOOST_THROW_EXCEPTION(std::length_error(str));\r
+}\r
+\r
+inline void throw_out_of_range(const char * str)\r
+{\r
+ BOOST_THROW_EXCEPTION(std::out_of_range(str));\r
+}\r
+\r
+#else\r
+\r
+inline void throw_runtime_error(const char * str)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!"runtime_error thrown", str);\r
+ std::abort();\r
+}\r
+\r
+inline void throw_logic_error(const char * str)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!"logic_error thrown", str);\r
+ std::abort();\r
+}\r
+\r
+inline void throw_invalid_argument(const char * str)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!"invalid_argument thrown", str);\r
+ std::abort();\r
+}\r
+\r
+inline void throw_length_error(const char * str)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!"length_error thrown", str);\r
+ std::abort();\r
+}\r
+\r
+inline void throw_out_of_range(const char * str)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!"out_of_range thrown", str);\r
+ std::abort();\r
+}\r
+\r
+#endif\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type\r
+>\r
+struct is_bounding_geometry\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+template <typename Box>\r
+struct is_bounding_geometry<Box, box_tag>\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+}}}} // namespave boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_IS_BOUNDING_GEOMETRY_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type\r
+>\r
+struct is_indexable\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+template <typename Point>\r
+struct is_indexable<Point, geometry::point_tag>\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+template <typename Box>\r
+struct is_indexable<Box, geometry::box_tag>\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+template <typename Segment>\r
+struct is_indexable<Segment, geometry::segment_tag>\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+}}}} // namespave boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_IS_INDEXABLE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/mpl/aux_/has_type.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/and.hpp>\r
+//#include <boost/type_traits/is_convertible.hpp>\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_META_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_META_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename T>\r
+struct is_range\r
+ : ::boost::mpl::aux::has_type< ::boost::range_iterator<T> >\r
+{};\r
+\r
+//template <typename T, typename V, bool IsRange>\r
+//struct is_range_of_convertible_values_impl\r
+// : ::boost::is_convertible<typename ::boost::range_value<T>::type, V>\r
+//{};\r
+//\r
+//template <typename T, typename V>\r
+//struct is_range_of_convertible_values_impl<T, V, false>\r
+// : ::boost::mpl::bool_<false>\r
+//{};\r
+//\r
+//template <typename T, typename V>\r
+//struct is_range_of_convertible_values\r
+// : is_range_of_convertible_values_impl<T, V, is_range<T>::value>\r
+//{};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_META_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Spatial query predicates definition and checks.\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP\r
+\r
+#include <boost/geometry/index/predicates.hpp>\r
+#include <boost/geometry/index/detail/tags.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+namespace predicates {\r
+\r
+// ------------------------------------------------------------------ //\r
+// predicates\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename Fun, bool IsFunction>\r
+struct satisfies_impl\r
+{\r
+ satisfies_impl() : fun(NULL) {}\r
+ satisfies_impl(Fun f) : fun(f) {}\r
+ Fun * fun;\r
+};\r
+\r
+template <typename Fun>\r
+struct satisfies_impl<Fun, false>\r
+{\r
+ satisfies_impl() {}\r
+ satisfies_impl(Fun const& f) : fun(f) {}\r
+ Fun fun;\r
+};\r
+\r
+template <typename Fun, bool Negated>\r
+struct satisfies\r
+ : satisfies_impl<Fun, ::boost::is_function<Fun>::value>\r
+{\r
+ typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;\r
+\r
+ satisfies() {}\r
+ satisfies(Fun const& f) : base(f) {}\r
+ satisfies(base const& b) : base(b) {}\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+struct contains_tag {};\r
+struct covered_by_tag {};\r
+struct covers_tag {};\r
+struct disjoint_tag {};\r
+struct intersects_tag {};\r
+struct overlaps_tag {};\r
+struct touches_tag {};\r
+struct within_tag {};\r
+\r
+template <typename Geometry, typename Tag, bool Negated>\r
+struct spatial_predicate\r
+{\r
+ spatial_predicate() {}\r
+ spatial_predicate(Geometry const& g) : geometry(g) {}\r
+ Geometry geometry;\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+// CONSIDER: separated nearest<> and path<> may be replaced by\r
+// nearest_predicate<Geometry, Tag>\r
+// where Tag = point_tag | path_tag\r
+// IMPROVEMENT: user-defined nearest predicate allowing to define\r
+// all or only geometrical aspects of the search\r
+\r
+template <typename PointOrRelation>\r
+struct nearest\r
+{\r
+ nearest()\r
+// : count(0)\r
+ {}\r
+ nearest(PointOrRelation const& por, unsigned k)\r
+ : point_or_relation(por)\r
+ , count(k)\r
+ {}\r
+ PointOrRelation point_or_relation;\r
+ unsigned count;\r
+};\r
+\r
+template <typename SegmentOrLinestring>\r
+struct path\r
+{\r
+ path()\r
+// : count(0)\r
+ {}\r
+ path(SegmentOrLinestring const& g, unsigned k)\r
+ : geometry(g)\r
+ , count(k)\r
+ {}\r
+ SegmentOrLinestring geometry;\r
+ unsigned count;\r
+};\r
+\r
+} // namespace predicates\r
+\r
+// ------------------------------------------------------------------ //\r
+// predicate_check\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename Predicate, typename Tag>\r
+struct predicate_check\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_PREDICATE_OR_TAG,\r
+ (predicate_check));\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename Fun>\r
+struct predicate_check<predicates::satisfies<Fun, false>, value_tag>\r
+{\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const&)\r
+ {\r
+ return p.fun(v);\r
+ }\r
+};\r
+\r
+template <typename Fun>\r
+struct predicate_check<predicates::satisfies<Fun, true>, value_tag>\r
+{\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const&)\r
+ {\r
+ return !p.fun(v);\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename Tag>\r
+struct spatial_predicate_call\r
+{\r
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::contains_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::within(g2, g1);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::covered_by_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::covered_by(g1, g2);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::covers_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::covered_by(g2, g1);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::disjoint_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::disjoint(g1, g2);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::intersects_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::intersects(g1, g2);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::overlaps_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::overlaps(g1, g2);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::touches_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::touches(g1, g2);\r
+ }\r
+};\r
+\r
+template <>\r
+struct spatial_predicate_call<predicates::within_tag>\r
+{\r
+ template <typename G1, typename G2>\r
+ static inline bool apply(G1 const& g1, G2 const& g2)\r
+ {\r
+ return geometry::within(g1, g2);\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+// spatial predicate\r
+template <typename Geometry, typename Tag>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return spatial_predicate_call<Tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// negated spatial predicate\r
+template <typename Geometry, typename Tag>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return !spatial_predicate_call<Tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename DistancePredicates>\r
+struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>\r
+{\r
+ template <typename Value, typename Box>\r
+ static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Linestring>\r
+struct predicate_check<predicates::path<Linestring>, value_tag>\r
+{\r
+ template <typename Value, typename Box>\r
+ static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+// predicates_check for bounds\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename Fun, bool Negated>\r
+struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>\r
+{\r
+ template <typename Value, typename Box>\r
+ static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+// NOT NEGATED\r
+// value_tag bounds_tag\r
+// ---------------------------\r
+// contains(I,G) covers(I,G)\r
+// covered_by(I,G) intersects(I,G)\r
+// covers(I,G) covers(I,G)\r
+// disjoint(I,G) !covered_by(I,G)\r
+// intersects(I,G) intersects(I,G)\r
+// overlaps(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false\r
+// touches(I,G) intersects(I,G)\r
+// within(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false\r
+\r
+// spatial predicate - default\r
+template <typename Geometry, typename Tag>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// spatial predicate - contains\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// spatial predicate - covers\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// spatial predicate - disjoint\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// NEGATED\r
+// value_tag bounds_tag\r
+// ---------------------------\r
+// !contains(I,G) TRUE\r
+// !covered_by(I,G) !covered_by(I,G)\r
+// !covers(I,G) TRUE\r
+// !disjoint(I,G) !disjoint(I,G)\r
+// !intersects(I,G) !covered_by(I,G)\r
+// !overlaps(I,G) TRUE\r
+// !touches(I,G) !intersects(I,G)\r
+// !within(I,G) !within(I,G)\r
+\r
+// negated spatial predicate - default\r
+template <typename Geometry, typename Tag>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return !spatial_predicate_call<Tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// negated spatial predicate - contains\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& , Value const&, Indexable const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// negated spatial predicate - covers\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& , Value const&, Indexable const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// negated spatial predicate - intersects\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// negated spatial predicate - overlaps\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& , Value const&, Indexable const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// negated spatial predicate - touches\r
+template <typename Geometry>\r
+struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>\r
+{\r
+ typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)\r
+ {\r
+ return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename DistancePredicates>\r
+struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>\r
+{\r
+ template <typename Value, typename Box>\r
+ static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Linestring>\r
+struct predicate_check<predicates::path<Linestring>, bounds_tag>\r
+{\r
+ template <typename Value, typename Box>\r
+ static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+// predicates_length\r
+// ------------------------------------------------------------------ //\r
+\r
+template <typename T>\r
+struct predicates_length\r
+{\r
+ static const unsigned value = 1;\r
+};\r
+\r
+//template <typename F, typename S>\r
+//struct predicates_length< std::pair<F, S> >\r
+//{\r
+// static const unsigned value = 2;\r
+//};\r
+\r
+//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct predicates_length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >\r
+//{\r
+// static const unsigned value = boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value;\r
+//};\r
+\r
+template <typename Head, typename Tail>\r
+struct predicates_length< boost::tuples::cons<Head, Tail> >\r
+{\r
+ static const unsigned value = boost::tuples::length< boost::tuples::cons<Head, Tail> >::value;\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+// predicates_element\r
+// ------------------------------------------------------------------ //\r
+\r
+template <unsigned I, typename T>\r
+struct predicates_element\r
+{\r
+ BOOST_MPL_ASSERT_MSG((I < 1), INVALID_INDEX, (predicates_element));\r
+ typedef T type;\r
+ static type const& get(T const& p) { return p; }\r
+};\r
+\r
+//template <unsigned I, typename F, typename S>\r
+//struct predicates_element< I, std::pair<F, S> >\r
+//{\r
+// BOOST_MPL_ASSERT_MSG((I < 2), INVALID_INDEX, (predicates_element));\r
+//\r
+// typedef F type;\r
+// static type const& get(std::pair<F, S> const& p) { return p.first; }\r
+//};\r
+//\r
+//template <typename F, typename S>\r
+//struct predicates_element< 1, std::pair<F, S> >\r
+//{\r
+// typedef S type;\r
+// static type const& get(std::pair<F, S> const& p) { return p.second; }\r
+//};\r
+//\r
+//template <unsigned I, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct predicates_element< I, boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >\r
+//{\r
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicate_type;\r
+//\r
+// typedef typename boost::tuples::element<I, predicate_type>::type type;\r
+// static type const& get(predicate_type const& p) { return boost::get<I>(p); }\r
+//};\r
+\r
+template <unsigned I, typename Head, typename Tail>\r
+struct predicates_element< I, boost::tuples::cons<Head, Tail> >\r
+{\r
+ typedef boost::tuples::cons<Head, Tail> predicate_type;\r
+\r
+ typedef typename boost::tuples::element<I, predicate_type>::type type;\r
+ static type const& get(predicate_type const& p) { return boost::get<I>(p); }\r
+};\r
+\r
+// ------------------------------------------------------------------ //\r
+// predicates_check\r
+// ------------------------------------------------------------------ //\r
+\r
+//template <typename PairPredicates, typename Tag, unsigned First, unsigned Last>\r
+//struct predicates_check_pair {};\r
+//\r
+//template <typename PairPredicates, typename Tag, unsigned I>\r
+//struct predicates_check_pair<PairPredicates, Tag, I, I>\r
+//{\r
+// template <typename Value, typename Indexable>\r
+// static inline bool apply(PairPredicates const& , Value const& , Indexable const& )\r
+// {\r
+// return true;\r
+// }\r
+//};\r
+//\r
+//template <typename PairPredicates, typename Tag>\r
+//struct predicates_check_pair<PairPredicates, Tag, 0, 1>\r
+//{\r
+// template <typename Value, typename Indexable>\r
+// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)\r
+// {\r
+// return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i);\r
+// }\r
+//};\r
+//\r
+//template <typename PairPredicates, typename Tag>\r
+//struct predicates_check_pair<PairPredicates, Tag, 1, 2>\r
+//{\r
+// template <typename Value, typename Indexable>\r
+// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)\r
+// {\r
+// return predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);\r
+// }\r
+//};\r
+//\r
+//template <typename PairPredicates, typename Tag>\r
+//struct predicates_check_pair<PairPredicates, Tag, 0, 2>\r
+//{\r
+// template <typename Value, typename Indexable>\r
+// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)\r
+// {\r
+// return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i)\r
+// && predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);\r
+// }\r
+//};\r
+\r
+template <typename TuplePredicates, typename Tag, unsigned First, unsigned Last>\r
+struct predicates_check_tuple\r
+{\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i)\r
+ {\r
+ return\r
+ predicate_check<\r
+ typename boost::tuples::element<First, TuplePredicates>::type,\r
+ Tag\r
+ >::apply(boost::get<First>(p), v, i) &&\r
+ predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i);\r
+ }\r
+};\r
+\r
+template <typename TuplePredicates, typename Tag, unsigned First>\r
+struct predicates_check_tuple<TuplePredicates, Tag, First, First>\r
+{\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(TuplePredicates const& , Value const& , Indexable const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Predicate, typename Tag, unsigned First, unsigned Last>\r
+struct predicates_check_impl\r
+{\r
+ static const bool check = First < 1 && Last <= 1 && First <= Last;\r
+ BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(Predicate const& p, Value const& v, Indexable const& i)\r
+ {\r
+ return predicate_check<Predicate, Tag>::apply(p, v, i);\r
+ }\r
+};\r
+\r
+//template <typename Predicate1, typename Predicate2, typename Tag, size_t First, size_t Last>\r
+//struct predicates_check_impl<std::pair<Predicate1, Predicate2>, Tag, First, Last>\r
+//{\r
+// BOOST_MPL_ASSERT_MSG((First < 2 && Last <= 2 && First <= Last), INVALID_INDEXES, (predicates_check_impl));\r
+//\r
+// template <typename Value, typename Indexable>\r
+// static inline bool apply(std::pair<Predicate1, Predicate2> const& p, Value const& v, Indexable const& i)\r
+// {\r
+// return predicate_check<Predicate1, Tag>::apply(p.first, v, i)\r
+// && predicate_check<Predicate2, Tag>::apply(p.second, v, i);\r
+// }\r
+//};\r
+//\r
+//template <\r
+// typename T0, typename T1, typename T2, typename T3, typename T4,\r
+// typename T5, typename T6, typename T7, typename T8, typename T9,\r
+// typename Tag, unsigned First, unsigned Last\r
+//>\r
+//struct predicates_check_impl<\r
+// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,\r
+// Tag, First, Last\r
+//>\r
+//{\r
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicates_type;\r
+//\r
+// static const unsigned pred_len = boost::tuples::length<predicates_type>::value;\r
+// BOOST_MPL_ASSERT_MSG((First < pred_len && Last <= pred_len && First <= Last), INVALID_INDEXES, (predicates_check_impl));\r
+//\r
+// template <typename Value, typename Indexable>\r
+// static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)\r
+// {\r
+// return predicates_check_tuple<\r
+// predicates_type,\r
+// Tag, First, Last\r
+// >::apply(p, v, i);\r
+// }\r
+//};\r
+\r
+template <typename Head, typename Tail, typename Tag, unsigned First, unsigned Last>\r
+struct predicates_check_impl<\r
+ boost::tuples::cons<Head, Tail>,\r
+ Tag, First, Last\r
+>\r
+{\r
+ typedef boost::tuples::cons<Head, Tail> predicates_type;\r
+\r
+ static const unsigned pred_len = boost::tuples::length<predicates_type>::value;\r
+ static const bool check = First < pred_len && Last <= pred_len && First <= Last;\r
+ BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));\r
+\r
+ template <typename Value, typename Indexable>\r
+ static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)\r
+ {\r
+ return predicates_check_tuple<\r
+ predicates_type,\r
+ Tag, First, Last\r
+ >::apply(p, v, i);\r
+ }\r
+};\r
+\r
+template <typename Tag, unsigned First, unsigned Last, typename Predicates, typename Value, typename Indexable>\r
+inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i)\r
+{\r
+ return detail::predicates_check_impl<Predicates, Tag, First, Last>\r
+ ::apply(p, v, i);\r
+}\r
+\r
+// ------------------------------------------------------------------ //\r
+// nearest predicate helpers\r
+// ------------------------------------------------------------------ //\r
+\r
+// predicates_is_nearest\r
+\r
+template <typename P>\r
+struct predicates_is_distance\r
+{\r
+ static const unsigned value = 0;\r
+};\r
+\r
+template <typename DistancePredicates>\r
+struct predicates_is_distance< predicates::nearest<DistancePredicates> >\r
+{\r
+ static const unsigned value = 1;\r
+};\r
+\r
+template <typename Linestring>\r
+struct predicates_is_distance< predicates::path<Linestring> >\r
+{\r
+ static const unsigned value = 1;\r
+};\r
+\r
+// predicates_count_nearest\r
+\r
+template <typename T>\r
+struct predicates_count_distance\r
+{\r
+ static const unsigned value = predicates_is_distance<T>::value;\r
+};\r
+\r
+//template <typename F, typename S>\r
+//struct predicates_count_distance< std::pair<F, S> >\r
+//{\r
+// static const unsigned value = predicates_is_distance<F>::value\r
+// + predicates_is_distance<S>::value;\r
+//};\r
+\r
+template <typename Tuple, unsigned N>\r
+struct predicates_count_distance_tuple\r
+{\r
+ static const unsigned value =\r
+ predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value\r
+ + predicates_count_distance_tuple<Tuple, N-1>::value;\r
+};\r
+\r
+template <typename Tuple>\r
+struct predicates_count_distance_tuple<Tuple, 1>\r
+{\r
+ static const unsigned value =\r
+ predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;\r
+};\r
+\r
+//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct predicates_count_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >\r
+//{\r
+// static const unsigned value = predicates_count_distance_tuple<\r
+// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,\r
+// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value\r
+// >::value;\r
+//};\r
+\r
+template <typename Head, typename Tail>\r
+struct predicates_count_distance< boost::tuples::cons<Head, Tail> >\r
+{\r
+ static const unsigned value = predicates_count_distance_tuple<\r
+ boost::tuples::cons<Head, Tail>,\r
+ boost::tuples::length< boost::tuples::cons<Head, Tail> >::value\r
+ >::value;\r
+};\r
+\r
+// predicates_find_nearest\r
+\r
+template <typename T>\r
+struct predicates_find_distance\r
+{\r
+ static const unsigned value = predicates_is_distance<T>::value ? 0 : 1;\r
+};\r
+\r
+//template <typename F, typename S>\r
+//struct predicates_find_distance< std::pair<F, S> >\r
+//{\r
+// static const unsigned value = predicates_is_distance<F>::value ? 0 :\r
+// (predicates_is_distance<S>::value ? 1 : 2);\r
+//};\r
+\r
+template <typename Tuple, unsigned N>\r
+struct predicates_find_distance_tuple\r
+{\r
+ static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found\r
+ || predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value;\r
+\r
+ static const unsigned value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?\r
+ predicates_find_distance_tuple<Tuple, N-1>::value :\r
+ (predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value ?\r
+ N-1 : boost::tuples::length<Tuple>::value);\r
+};\r
+\r
+template <typename Tuple>\r
+struct predicates_find_distance_tuple<Tuple, 1>\r
+{\r
+ static const bool is_found = predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;\r
+ static const unsigned value = is_found ? 0 : boost::tuples::length<Tuple>::value;\r
+};\r
+\r
+//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>\r
+//struct predicates_find_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >\r
+//{\r
+// static const unsigned value = predicates_find_distance_tuple<\r
+// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,\r
+// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value\r
+// >::value;\r
+//};\r
+\r
+template <typename Head, typename Tail>\r
+struct predicates_find_distance< boost::tuples::cons<Head, Tail> >\r
+{\r
+ static const unsigned value = predicates_find_distance_tuple<\r
+ boost::tuples::cons<Head, Tail>,\r
+ boost::tuples::length< boost::tuples::cons<Head, Tail> >::value\r
+ >::value;\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree queries range adaptors\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP\r
+\r
+#include <deque>\r
+#include <boost/static_assert.hpp>\r
+\r
+#include <boost/geometry/index/adaptors/query.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+class rtree;\r
+\r
+namespace adaptors { namespace detail {\r
+\r
+template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+class query_range< index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator> >\r
+{\r
+public:\r
+ typedef std::vector<Value> result_type;\r
+ typedef typename result_type::iterator iterator;\r
+ typedef typename result_type::const_iterator const_iterator;\r
+\r
+ template <typename Predicates> inline\r
+ query_range(index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator> const& rtree,\r
+ Predicates const& pred)\r
+ {\r
+ rtree.query(pred, std::back_inserter(m_result));\r
+ }\r
+\r
+ inline iterator begin() { return m_result.begin(); }\r
+ inline iterator end() { return m_result.end(); }\r
+ inline const_iterator begin() const { return m_result.begin(); }\r
+ inline const_iterator end() const { return m_result.end(); }\r
+\r
+private:\r
+ result_type m_result;\r
+};\r
+\r
+}} // namespace adaptors::detail\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree iterators\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {\r
+\r
+template <typename Value, typename Allocators>\r
+struct end_iterator\r
+{\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ reference operator*() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");\r
+ pointer p(0);\r
+ return *p;\r
+ }\r
+\r
+ const value_type * operator->() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");\r
+ const value_type * p = 0;\r
+ return p;\r
+ }\r
+\r
+ end_iterator & operator++()\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");\r
+ return *this;\r
+ }\r
+\r
+ end_iterator operator++(int)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");\r
+ return *this;\r
+ }\r
+\r
+ friend bool operator==(end_iterator const& /*l*/, end_iterator const& /*r*/)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class iterator\r
+{\r
+ typedef visitors::iterator<Value, Options, Translator, Box, Allocators> visitor_type;\r
+ typedef typename visitor_type::node_pointer node_pointer;\r
+\r
+public:\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ inline iterator()\r
+ {}\r
+\r
+ inline iterator(node_pointer root)\r
+ {\r
+ m_visitor.initialize(root);\r
+ }\r
+\r
+ reference operator*() const\r
+ {\r
+ return m_visitor.dereference();\r
+ }\r
+\r
+ const value_type * operator->() const\r
+ {\r
+ return boost::addressof(m_visitor.dereference());\r
+ }\r
+\r
+ iterator & operator++()\r
+ {\r
+ m_visitor.increment();\r
+ return *this;\r
+ }\r
+\r
+ iterator operator++(int)\r
+ {\r
+ iterator temp = *this;\r
+ this->operator++();\r
+ return temp;\r
+ }\r
+\r
+ friend bool operator==(iterator const& l, iterator const& r)\r
+ {\r
+ return l.m_visitor == r.m_visitor;\r
+ }\r
+\r
+ friend bool operator==(iterator const& l, end_iterator<Value, Allocators> const& /*r*/)\r
+ {\r
+ return l.m_visitor.is_end();\r
+ }\r
+\r
+ friend bool operator==(end_iterator<Value, Allocators> const& /*l*/, iterator const& r)\r
+ {\r
+ return r.m_visitor.is_end();\r
+ }\r
+ \r
+private:\r
+ visitor_type m_visitor;\r
+};\r
+\r
+}}}}}} // namespace boost::geometry::index::detail::rtree::iterators\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree kmeans algorithm implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP\r
+\r
+#include <boost/geometry/index/rtree/kmeans/split.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree kmeans split algorithm implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP\r
+\r
+#include <boost/geometry/index/rtree/node/node.hpp>\r
+#include <boost/geometry/index/rtree/visitors/insert.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+namespace kmeans {\r
+\r
+// some details\r
+\r
+} // namespace kmeans\r
+\r
+// split_kmeans_tag\r
+// OR\r
+// split_clusters_tag and redistribute_kmeans_tag - then redistribute will probably slightly different interface\r
+// or some other than "redistribute"\r
+\r
+// 1. for this algorithm one probably MUST USE NON-STATIC NODES with node_default_tag\r
+// or the algorithm must be changed somehow - to not store additional nodes in the current node\r
+// but return excessive element/elements container instead (possibly pushable_array<1> or std::vector)\r
+// this would also cause building of smaller trees since +1 element in nodes wouldn't be needed in different redistributing algorithms\r
+// 2. it is probably possible to add e.g. 2 levels of tree in one insert\r
+\r
+// Edge case is that every node split generates M + 1 children, in parent containing M nodes\r
+// result is 2M + 1 nodes in parent on this level\r
+// On next level the same, next the same and so on.\r
+// We have Depth*M+1 nodes in the root\r
+// The tree may then gain some > 1 levels in one insert\r
+// split::apply() manages this but special attention is required\r
+\r
+// which algorithm should be used to choose current node in traversing while inserting?\r
+// some of the currently used ones or some using mean values as well?\r
+\r
+// TODO\r
+// 1. Zmienic troche algorytm zeby przekazywal nadmiarowe elementy do split\r
+// i pobieral ze split nadmiarowe elementy rodzica\r
+// W zaleznosci od algorytmu w rozny sposob - l/q/r* powinny zwracac np pushable_array<1>\r
+// wtedy tez is_overerflow (z R* insert?) bedzie nieportrzebne\r
+// Dla kmeans zapewne std::vector, jednak w wezlach nadal moglaby byc pushable_array\r
+// 2. Fajnie byloby tez uproscic te wszystkie parametry root,parent,index itd. Mozliwe ze okazalyby sie zbedne\r
+// 3. Sprawdzyc czasy wykonywania i zajetosc pamieci\r
+// 4. Pamietac o parametryzacji kontenera z nadmiarowymi elementami\r
+// PS. Z R* reinsertami moze byc masakra\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class split<Value, Options, Translator, Box, Allocators, split_kmeans_tag>\r
+{\r
+protected:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+public:\r
+ template <typename Node>\r
+ static inline void apply(node* & root_node,\r
+ size_t & leafs_level,\r
+ Node & n,\r
+ internal_node *parent_node,\r
+ size_t current_child_index,\r
+ Translator const& tr,\r
+ Allocators & allocators)\r
+ {\r
+\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree linear algorithm implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree linear split algorithm implementation\r
+//\r
+// Copyright (c) 2008 Federico J. Fernandez.\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP\r
+\r
+#include <boost/type_traits/is_unsigned.hpp>\r
+\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+#include <boost/geometry/index/detail/bounded_view.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+namespace linear {\r
+\r
+template <typename R, typename T>\r
+inline R difference_dispatch(T const& from, T const& to, ::boost::mpl::bool_<false> const& /*is_unsigned*/)\r
+{\r
+ return to - from;\r
+}\r
+\r
+template <typename R, typename T>\r
+inline R difference_dispatch(T const& from, T const& to, ::boost::mpl::bool_<true> const& /*is_unsigned*/)\r
+{\r
+ return from <= to ? R(to - from) : -R(from - to);\r
+}\r
+\r
+template <typename R, typename T>\r
+inline R difference(T const& from, T const& to)\r
+{\r
+ BOOST_MPL_ASSERT_MSG(!boost::is_unsigned<R>::value, RESULT_CANT_BE_UNSIGNED, (R));\r
+\r
+ typedef ::boost::mpl::bool_<\r
+ boost::is_unsigned<T>::value\r
+ > is_unsigned;\r
+\r
+ return difference_dispatch<R>(from, to, is_unsigned());\r
+}\r
+\r
+// TODO: awulkiew\r
+// In general, all aerial Indexables in the tree with box-like nodes will be analyzed as boxes\r
+// because they must fit into larger box. Therefore the algorithm could be the same for Bounds type.\r
+// E.g. if Bounds type is sphere, Indexables probably should be analyzed as spheres.\r
+// 1. View could be provided to 'see' all Indexables as Bounds type.\r
+// Not ok in the case of big types like Ring, however it's possible that Rings won't be supported,\r
+// only simple types. Even then if we consider storing Box inside the Sphere we must calculate\r
+// the bounding sphere 2x for each box because there are 2 loops. For each calculation this means\r
+// 4-2d or 8-3d expansions or -, / and sqrt().\r
+// 2. Additional container could be used and reused if the Indexable type is other than the Bounds type.\r
+\r
+// IMPORTANT!\r
+// Still probably the best way would be providing specialized algorithms for each Indexable-Bounds pair!\r
+// Probably on pick_seeds algorithm level - For Bounds=Sphere seeds would be choosen differently\r
+\r
+// TODO: awulkiew\r
+// there are loops inside find_greatest_normalized_separation::apply()\r
+// iteration is done for each DimensionIndex.\r
+// Separations and seeds for all DimensionIndex(es) could be calculated at once, stored, then the greatest would be choosen.\r
+\r
+// The following struct/method was adapted for the preliminary version of the R-tree. Then it was called:\r
+// void find_normalized_separations(std::vector<Box> const& boxes, T& separation, unsigned int& first, unsigned int& second) const\r
+\r
+template <typename Elements, typename Parameters, typename Translator, typename Tag, size_t DimensionIndex>\r
+struct find_greatest_normalized_separation\r
+{\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;\r
+\r
+ typedef typename boost::mpl::if_c<\r
+ boost::is_integral<coordinate_type>::value,\r
+ double,\r
+ coordinate_type\r
+ >::type separation_type;\r
+\r
+ typedef typename geometry::point_type<indexable_type>::type point_type;\r
+ typedef geometry::model::box<point_type> bounds_type;\r
+ typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;\r
+\r
+ static inline void apply(Elements const& elements,\r
+ Parameters const& parameters,\r
+ Translator const& translator,\r
+ separation_type & separation,\r
+ size_t & seed1,\r
+ size_t & seed2)\r
+ {\r
+ const size_t elements_count = parameters.get_max_elements() + 1;\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");\r
+\r
+ // find the lowest low, highest high\r
+ bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator));\r
+ coordinate_type lowest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_0);\r
+ coordinate_type highest_high = geometry::get<max_corner, DimensionIndex>(bounded_indexable_0);\r
+\r
+ // and the lowest high\r
+ coordinate_type lowest_high = highest_high;\r
+ size_t lowest_high_index = 0;\r
+ for ( size_t i = 1 ; i < elements_count ; ++i )\r
+ {\r
+ bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator));\r
+ coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);\r
+ coordinate_type max_coord = geometry::get<max_corner, DimensionIndex>(bounded_indexable);\r
+\r
+ if ( max_coord < lowest_high )\r
+ {\r
+ lowest_high = max_coord;\r
+ lowest_high_index = i;\r
+ }\r
+\r
+ if ( min_coord < lowest_low )\r
+ lowest_low = min_coord;\r
+\r
+ if ( highest_high < max_coord )\r
+ highest_high = max_coord;\r
+ }\r
+\r
+ // find the highest low\r
+ size_t highest_low_index = lowest_high_index == 0 ? 1 : 0;\r
+ bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator));\r
+ coordinate_type highest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_hl);\r
+ for ( size_t i = highest_low_index ; i < elements_count ; ++i )\r
+ {\r
+ bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator));\r
+ coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);\r
+ if ( highest_low < min_coord &&\r
+ i != lowest_high_index )\r
+ {\r
+ highest_low = min_coord;\r
+ highest_low_index = i;\r
+ }\r
+ }\r
+\r
+ coordinate_type const width = highest_high - lowest_low;\r
+ \r
+ // highest_low - lowest_high\r
+ separation = difference<separation_type>(lowest_high, highest_low);\r
+ // BOOST_GEOMETRY_INDEX_ASSERT(0 <= width);\r
+ if ( std::numeric_limits<coordinate_type>::epsilon() < width )\r
+ separation /= width;\r
+\r
+ seed1 = highest_low_index;\r
+ seed2 = lowest_high_index;\r
+\r
+ ::boost::ignore_unused_variable_warning(parameters);\r
+ }\r
+};\r
+\r
+// Version for points doesn't calculate normalized separation since it would always be equal to 1\r
+// It returns two seeds most distant to each other, separation is equal to distance\r
+template <typename Elements, typename Parameters, typename Translator, size_t DimensionIndex>\r
+struct find_greatest_normalized_separation<Elements, Parameters, Translator, point_tag, DimensionIndex>\r
+{\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;\r
+\r
+ typedef coordinate_type separation_type;\r
+\r
+ static inline void apply(Elements const& elements,\r
+ Parameters const& parameters,\r
+ Translator const& translator,\r
+ separation_type & separation,\r
+ size_t & seed1,\r
+ size_t & seed2)\r
+ {\r
+ const size_t elements_count = parameters.get_max_elements() + 1;\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");\r
+\r
+ // find the lowest low, highest high\r
+ coordinate_type lowest = geometry::get<DimensionIndex>(rtree::element_indexable(elements[0], translator));\r
+ coordinate_type highest = geometry::get<DimensionIndex>(rtree::element_indexable(elements[0], translator));\r
+ size_t lowest_index = 0;\r
+ size_t highest_index = 0;\r
+ for ( size_t i = 1 ; i < elements_count ; ++i )\r
+ {\r
+ coordinate_type coord = geometry::get<DimensionIndex>(rtree::element_indexable(elements[i], translator));\r
+\r
+ if ( coord < lowest )\r
+ {\r
+ lowest = coord;\r
+ lowest_index = i;\r
+ }\r
+\r
+ if ( highest < coord )\r
+ {\r
+ highest = coord;\r
+ highest_index = i;\r
+ }\r
+ }\r
+\r
+ separation = highest - lowest;\r
+ seed1 = lowest_index;\r
+ seed2 = highest_index;\r
+\r
+ if ( lowest_index == highest_index )\r
+ seed2 = (lowest_index + 1) % elements_count; // % is just in case since if this is true lowest_index is 0\r
+\r
+ ::boost::ignore_unused_variable_warning(parameters);\r
+ }\r
+};\r
+\r
+template <typename Elements, typename Parameters, typename Translator, size_t Dimension>\r
+struct pick_seeds_impl\r
+{\r
+ BOOST_STATIC_ASSERT(0 < Dimension);\r
+\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+\r
+ typedef find_greatest_normalized_separation<\r
+ Elements, Parameters, Translator,\r
+ typename tag<indexable_type>::type, Dimension - 1\r
+ > find_norm_sep;\r
+\r
+ typedef typename find_norm_sep::separation_type separation_type;\r
+\r
+ static inline void apply(Elements const& elements,\r
+ Parameters const& parameters,\r
+ Translator const& tr,\r
+ separation_type & separation,\r
+ size_t & seed1,\r
+ size_t & seed2)\r
+ {\r
+ pick_seeds_impl<Elements, Parameters, Translator, Dimension - 1>::apply(elements, parameters, tr, separation, seed1, seed2);\r
+\r
+ separation_type current_separation;\r
+ size_t s1, s2;\r
+ find_norm_sep::apply(elements, parameters, tr, current_separation, s1, s2);\r
+\r
+ // in the old implementation different operator was used: <= (y axis prefered)\r
+ if ( separation < current_separation )\r
+ {\r
+ separation = current_separation;\r
+ seed1 = s1;\r
+ seed2 = s2;\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Elements, typename Parameters, typename Translator>\r
+struct pick_seeds_impl<Elements, Parameters, Translator, 1>\r
+{\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;\r
+\r
+ typedef find_greatest_normalized_separation<\r
+ Elements, Parameters, Translator,\r
+ typename tag<indexable_type>::type, 0\r
+ > find_norm_sep;\r
+\r
+ typedef typename find_norm_sep::separation_type separation_type;\r
+\r
+ static inline void apply(Elements const& elements,\r
+ Parameters const& parameters,\r
+ Translator const& tr,\r
+ separation_type & separation,\r
+ size_t & seed1,\r
+ size_t & seed2)\r
+ {\r
+ find_norm_sep::apply(elements, parameters, tr, separation, seed1, seed2);\r
+ }\r
+};\r
+\r
+// from void linear_pick_seeds(node_pointer const& n, unsigned int &seed1, unsigned int &seed2) const\r
+\r
+template <typename Elements, typename Parameters, typename Translator>\r
+inline void pick_seeds(Elements const& elements,\r
+ Parameters const& parameters,\r
+ Translator const& tr,\r
+ size_t & seed1,\r
+ size_t & seed2)\r
+{\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+\r
+ typedef pick_seeds_impl\r
+ <\r
+ Elements, Parameters, Translator,\r
+ geometry::dimension<indexable_type>::value\r
+ > impl;\r
+ typedef typename impl::separation_type separation_type;\r
+\r
+ separation_type separation = 0;\r
+ impl::apply(elements, parameters, tr, separation, seed1, seed2);\r
+}\r
+\r
+} // namespace linear\r
+\r
+// from void split_node(node_pointer const& n, node_pointer& n1, node_pointer& n2) const\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear_tag>\r
+{\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ template <typename Node>\r
+ static inline void apply(Node & n,\r
+ Node & second_node,\r
+ Box & box1,\r
+ Box & box2,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators)\r
+ {\r
+ typedef typename rtree::elements_type<Node>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ elements_type & elements1 = rtree::elements(n);\r
+ elements_type & elements2 = rtree::elements(second_node);\r
+ const size_t elements1_count = parameters.get_max_elements() + 1;\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == elements1_count, "unexpected number of elements");\r
+\r
+ // copy original elements - use in-memory storage (std::allocator)\r
+ // TODO: move if noexcept\r
+ typedef typename rtree::container_from_elements_type<elements_type, element_type>::type\r
+ container_type;\r
+ container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)\r
+\r
+ // calculate initial seeds\r
+ size_t seed1 = 0;\r
+ size_t seed2 = 0;\r
+ linear::pick_seeds(elements_copy, parameters, translator, seed1, seed2);\r
+\r
+ // prepare nodes' elements containers\r
+ elements1.clear();\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "unexpected container state");\r
+\r
+ BOOST_TRY\r
+ {\r
+ // add seeds\r
+ elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)\r
+ elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)\r
+\r
+ // calculate boxes\r
+ detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);\r
+ detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);\r
+\r
+ // initialize areas\r
+ content_type content1 = index::detail::content(box1);\r
+ content_type content2 = index::detail::content(box2);\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements1_count, "unexpected elements number");\r
+ size_t remaining = elements1_count - 2;\r
+\r
+ // redistribute the rest of the elements\r
+ for ( size_t i = 0 ; i < elements1_count ; ++i )\r
+ {\r
+ if (i != seed1 && i != seed2)\r
+ {\r
+ element_type const& elem = elements_copy[i];\r
+ indexable_type const& indexable = rtree::element_indexable(elem, translator);\r
+\r
+ // if there is small number of elements left and the number of elements in node is lesser than min_elems\r
+ // just insert them to this node\r
+ if ( elements1.size() + remaining <= parameters.get_min_elements() )\r
+ {\r
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)\r
+ geometry::expand(box1, indexable);\r
+ content1 = index::detail::content(box1);\r
+ }\r
+ else if ( elements2.size() + remaining <= parameters.get_min_elements() )\r
+ {\r
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)\r
+ geometry::expand(box2, indexable);\r
+ content2 = index::detail::content(box2);\r
+ }\r
+ // choose better node and insert element\r
+ else\r
+ {\r
+ // calculate enlarged boxes and areas\r
+ Box enlarged_box1(box1);\r
+ Box enlarged_box2(box2);\r
+ geometry::expand(enlarged_box1, indexable);\r
+ geometry::expand(enlarged_box2, indexable);\r
+ content_type enlarged_content1 = index::detail::content(enlarged_box1);\r
+ content_type enlarged_content2 = index::detail::content(enlarged_box2);\r
+\r
+ content_type content_increase1 = enlarged_content1 - content1;\r
+ content_type content_increase2 = enlarged_content2 - content2;\r
+\r
+ // choose group which box content have to be enlarged least or has smaller content or has fewer elements\r
+ if ( content_increase1 < content_increase2 ||\r
+ ( content_increase1 == content_increase2 &&\r
+ ( content1 < content2 ||\r
+ ( content1 == content2 && elements1.size() <= elements2.size() ) ) ) )\r
+ {\r
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)\r
+ box1 = enlarged_box1;\r
+ content1 = enlarged_content1;\r
+ }\r
+ else\r
+ {\r
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)\r
+ box2 = enlarged_box2;\r
+ content2 = enlarged_content2;\r
+ }\r
+ }\r
+ \r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "unexpected value");\r
+ --remaining;\r
+ }\r
+ }\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ elements1.clear();\r
+ elements2.clear();\r
+\r
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_copy, allocators);\r
+ //elements_copy.clear();\r
+\r
+ BOOST_RETHROW // RETHROW, BASIC\r
+ }\r
+ BOOST_CATCH_END\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree node concept\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct node\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,\r
+ (node));\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct internal_node\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,\r
+ (internal_node));\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct leaf\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,\r
+ (leaf));\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>\r
+struct visitor\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,\r
+ (visitor));\r
+};\r
+\r
+template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>\r
+class allocators\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,\r
+ (allocators));\r
+};\r
+\r
+template <typename Allocators, typename Node>\r
+struct create_node\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_NODE_TYPE,\r
+ (create_node));\r
+};\r
+\r
+template <typename Allocators, typename Node>\r
+struct destroy_node\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_NODE_TYPE,\r
+ (destroy_node));\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP\r
+\r
+#include <boost/container/vector.hpp>\r
+#include <boost/geometry/index/detail/varray.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/pairs.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp>\r
+\r
+//#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>\r
+//#include <boost/geometry/index/detail/rtree/node/weak_dynamic.hpp>\r
+//#include <boost/geometry/index/detail/rtree/node/weak_static.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/variant_dynamic.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/variant_static.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>\r
+\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>\r
+\r
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>\r
+#include <boost/geometry/index/detail/is_bounding_geometry.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// elements box\r
+\r
+template <typename Box, typename FwdIter, typename Translator>\r
+inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)\r
+{\r
+ Box result;\r
+ \r
+ // Only here to suppress 'uninitialized local variable used' warning\r
+ // until the suggestion below is not implemented\r
+ geometry::assign_inverse(result);\r
+\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(first != last, "non-empty range required");\r
+ // NOTE: this is not elegant temporary solution,\r
+ // reference to box could be passed as parameter and bool returned\r
+ if ( first == last )\r
+ return result;\r
+\r
+ detail::bounds(element_indexable(*first, tr), result);\r
+ ++first;\r
+\r
+ for ( ; first != last ; ++first )\r
+ geometry::expand(result, element_indexable(*first, tr));\r
+\r
+ return result;\r
+}\r
+\r
+// Enlarge bounds of a leaf node WRT epsilon if needed.\r
+// It's because Points and Segments are compared WRT machine epsilon.\r
+// This ensures that leafs bounds correspond to the stored elements.\r
+// NOTE: this is done only if the Indexable is not a Box\r
+// in the future don't do it also for NSphere\r
+template <typename Box, typename FwdIter, typename Translator>\r
+inline Box values_box(FwdIter first, FwdIter last, Translator const& tr)\r
+{\r
+ typedef typename std::iterator_traits<FwdIter>::value_type element_type;\r
+ BOOST_MPL_ASSERT_MSG((is_leaf_element<element_type>::value),\r
+ SHOULD_BE_CALLED_ONLY_FOR_LEAF_ELEMENTS,\r
+ (element_type));\r
+\r
+ Box result = elements_box<Box>(first, last, tr);\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON\r
+ if (BOOST_GEOMETRY_CONDITION((\r
+ ! is_bounding_geometry\r
+ <\r
+ typename indexable_type<Translator>::type\r
+ >::value)))\r
+ {\r
+ geometry::detail::expand_by_epsilon(result);\r
+ }\r
+#endif\r
+\r
+ return result;\r
+}\r
+\r
+// destroys subtree if the element is internal node's element\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct destroy_element\r
+{\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+\r
+ inline static void apply(typename internal_node::elements_type::value_type & element, Allocators & allocators)\r
+ {\r
+ subtree_destroyer dummy(element.second, allocators);\r
+ element.second = 0;\r
+ }\r
+\r
+ inline static void apply(typename leaf::elements_type::value_type &, Allocators &) {}\r
+};\r
+\r
+// destroys stored subtrees if internal node's elements are passed\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct destroy_elements\r
+{\r
+ template <typename Range>\r
+ inline static void apply(Range & elements, Allocators & allocators)\r
+ {\r
+ apply(boost::begin(elements), boost::end(elements), allocators);\r
+ }\r
+\r
+ template <typename It>\r
+ inline static void apply(It first, It last, Allocators & allocators)\r
+ {\r
+ typedef boost::mpl::bool_<\r
+ boost::is_same<\r
+ Value, typename std::iterator_traits<It>::value_type\r
+ >::value\r
+ > is_range_of_values;\r
+\r
+ apply_dispatch(first, last, allocators, is_range_of_values());\r
+ }\r
+\r
+private:\r
+ template <typename It>\r
+ inline static void apply_dispatch(It first, It last, Allocators & allocators,\r
+ boost::mpl::bool_<false> const& /*is_range_of_values*/)\r
+ {\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+\r
+ for ( ; first != last ; ++first )\r
+ {\r
+ subtree_destroyer dummy(first->second, allocators);\r
+ first->second = 0;\r
+ }\r
+ }\r
+\r
+ template <typename It>\r
+ inline static void apply_dispatch(It /*first*/, It /*last*/, Allocators & /*allocators*/,\r
+ boost::mpl::bool_<true> const& /*is_range_of_values*/)\r
+ {}\r
+};\r
+\r
+// clears node, deletes all subtrees stored in node\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct clear_node\r
+{\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ inline static void apply(node & node, Allocators & allocators)\r
+ {\r
+ rtree::visitors::is_leaf<Value, Options, Box, Allocators> ilv;\r
+ rtree::apply_visitor(ilv, node);\r
+ if ( ilv.result )\r
+ {\r
+ apply(rtree::get<leaf>(node), allocators);\r
+ }\r
+ else\r
+ {\r
+ apply(rtree::get<internal_node>(node), allocators);\r
+ }\r
+ }\r
+\r
+ inline static void apply(internal_node & internal_node, Allocators & allocators)\r
+ {\r
+ destroy_elements<Value, Options, Translator, Box, Allocators>::apply(rtree::elements(internal_node), allocators);\r
+ rtree::elements(internal_node).clear();\r
+ }\r
+\r
+ inline static void apply(leaf & leaf, Allocators &)\r
+ {\r
+ rtree::elements(leaf).clear();\r
+ }\r
+};\r
+\r
+template <typename Container, typename Iterator>\r
+void move_from_back(Container & container, Iterator it)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!container.empty(), "cannot copy from empty container");\r
+ Iterator back_it = container.end();\r
+ --back_it;\r
+ if ( it != back_it )\r
+ {\r
+ *it = boost::move(*back_it); // MAY THROW (copy)\r
+ }\r
+}\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree node elements access\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP\r
+\r
+#include <boost/container/vector.hpp>\r
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>\r
+#include <boost/geometry/index/detail/varray.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/pairs.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// element's indexable type\r
+\r
+template <typename Element, typename Translator>\r
+struct element_indexable_type\r
+{\r
+ typedef typename indexable_type<Translator>::type type;\r
+};\r
+\r
+template <typename First, typename Pointer, typename Translator>\r
+struct element_indexable_type<\r
+ rtree::ptr_pair<First, Pointer>,\r
+ Translator\r
+>\r
+{\r
+ typedef First type;\r
+};\r
+\r
+// is leaf element\r
+\r
+template <typename Element>\r
+struct is_leaf_element\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+template <typename First, typename Pointer>\r
+struct is_leaf_element< rtree::ptr_pair<First, Pointer> >\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+// element's indexable getter\r
+\r
+template <typename Element, typename Translator>\r
+typename result_type<Translator>::type\r
+element_indexable(Element const& el, Translator const& tr)\r
+{\r
+ return tr(el);\r
+}\r
+\r
+template <typename First, typename Pointer, typename Translator>\r
+First const&\r
+element_indexable(rtree::ptr_pair<First, Pointer> const& el, Translator const& /*tr*/)\r
+{\r
+ return el.first;\r
+}\r
+\r
+// nodes elements\r
+\r
+template <typename Node>\r
+struct elements_type\r
+{\r
+ typedef typename Node::elements_type type;\r
+};\r
+\r
+template <typename Node>\r
+inline typename elements_type<Node>::type &\r
+elements(Node & n)\r
+{\r
+ return n.elements;\r
+}\r
+\r
+template <typename Node>\r
+inline typename elements_type<Node>::type const&\r
+elements(Node const& n)\r
+{\r
+ return n.elements;\r
+}\r
+\r
+// elements derived type\r
+\r
+template <typename Elements, typename NewValue>\r
+struct container_from_elements_type\r
+{\r
+ typedef boost::container::vector<NewValue> type;\r
+};\r
+\r
+template <typename OldValue, size_t N, typename NewValue>\r
+struct container_from_elements_type<detail::varray<OldValue, N>, NewValue>\r
+{\r
+ typedef detail::varray<NewValue, N> type;\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_ELEMENTS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Pairs intended to be used internally in nodes.\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP\r
+\r
+#include <boost/move/move.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename First, typename Pointer>\r
+class ptr_pair\r
+{\r
+public:\r
+ typedef First first_type;\r
+ typedef Pointer second_type;\r
+ ptr_pair(First const& f, Pointer s) : first(f), second(s) {}\r
+ //ptr_pair(ptr_pair const& p) : first(p.first), second(p.second) {}\r
+ //ptr_pair & operator=(ptr_pair const& p) { first = p.first; second = p.second; return *this; }\r
+\r
+ first_type first;\r
+ second_type second;\r
+};\r
+\r
+template <typename First, typename Pointer> inline\r
+ptr_pair<First, Pointer>\r
+make_ptr_pair(First const& f, Pointer s)\r
+{\r
+ return ptr_pair<First, Pointer>(f, s);\r
+}\r
+\r
+// TODO: It this will be used, rename it to unique_ptr_pair and possibly use unique_ptr.\r
+\r
+template <typename First, typename Pointer>\r
+class exclusive_ptr_pair\r
+{\r
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(exclusive_ptr_pair)\r
+public:\r
+ typedef First first_type;\r
+ typedef Pointer second_type;\r
+ exclusive_ptr_pair(First const& f, Pointer s) : first(f), second(s) {}\r
+\r
+ // INFO - members aren't really moved!\r
+ exclusive_ptr_pair(BOOST_RV_REF(exclusive_ptr_pair) p) : first(p.first), second(p.second) { p.second = 0; }\r
+ exclusive_ptr_pair & operator=(BOOST_RV_REF(exclusive_ptr_pair) p) { first = p.first; second = p.second; p.second = 0; return *this; }\r
+\r
+ first_type first;\r
+ second_type second;\r
+};\r
+\r
+template <typename First, typename Pointer> inline\r
+exclusive_ptr_pair<First, Pointer>\r
+make_exclusive_ptr_pair(First const& f, Pointer s)\r
+{\r
+ return exclusive_ptr_pair<First, Pointer>(f, s);\r
+}\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree scoped deallocator\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename Alloc>\r
+class scoped_deallocator\r
+{\r
+ scoped_deallocator(scoped_deallocator const&);\r
+ scoped_deallocator & operator=(scoped_deallocator const&);\r
+public:\r
+ typedef typename Alloc::pointer pointer;\r
+ inline scoped_deallocator(pointer p, Alloc & a)\r
+ : m_ptr(p), m_alloc(a)\r
+ {}\r
+ inline ~scoped_deallocator()\r
+ {\r
+ if ( m_ptr )\r
+ {\r
+ boost::container::allocator_traits<Alloc>::deallocate(m_alloc, m_ptr, 1);\r
+ }\r
+ }\r
+ inline void release()\r
+ {\r
+ m_ptr = 0;\r
+ }\r
+private:\r
+ pointer m_ptr;\r
+ Alloc & m_alloc;\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree subtree scoped destroyer\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class subtree_destroyer\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename Allocators::node_pointer pointer;\r
+\r
+ subtree_destroyer(subtree_destroyer const&);\r
+ subtree_destroyer & operator=(subtree_destroyer const&);\r
+\r
+public:\r
+ subtree_destroyer(pointer ptr, Allocators & allocators)\r
+ : m_ptr(ptr)\r
+ , m_allocators(allocators)\r
+ {}\r
+\r
+ ~subtree_destroyer()\r
+ {\r
+ reset();\r
+ }\r
+\r
+ void reset(pointer ptr = 0)\r
+ {\r
+ if ( m_ptr && m_ptr != ptr )\r
+ {\r
+ detail::rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(m_ptr, m_allocators);\r
+ detail::rtree::apply_visitor(del_v, *m_ptr);\r
+ }\r
+ m_ptr = ptr;\r
+ }\r
+\r
+ void release()\r
+ {\r
+ m_ptr = 0;\r
+ }\r
+\r
+ pointer get() const\r
+ {\r
+ return m_ptr;\r
+ }\r
+\r
+ node & operator*() const\r
+ {\r
+ return *m_ptr;\r
+ }\r
+\r
+ pointer operator->() const\r
+ {\r
+ return m_ptr;\r
+ }\r
+\r
+private:\r
+ pointer m_ptr;\r
+ Allocators & m_allocators;\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SUBTREE_DESTROYED_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes based on Boost.Variant, storing dynamic-size containers\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// nodes default types\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct variant_internal_node\r
+{\r
+ typedef boost::container::vector\r
+ <\r
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,\r
+ typename Allocators::node_allocator_type::template rebind\r
+ <\r
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>\r
+ >::other\r
+ > elements_type;\r
+\r
+ template <typename Al>\r
+ inline variant_internal_node(Al const& al)\r
+ : elements(al)\r
+ {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct variant_leaf\r
+{\r
+ typedef boost::container::vector\r
+ <\r
+ Value,\r
+ typename Allocators::node_allocator_type::template rebind\r
+ <\r
+ Value\r
+ >::other\r
+ > elements_type;\r
+\r
+ template <typename Al>\r
+ inline variant_leaf(Al const& al)\r
+ : elements(al)\r
+ {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+// nodes traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>\r
+{\r
+ typedef boost::variant<\r
+ variant_leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>\r
+ > type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>\r
+{\r
+ typedef variant_internal_node<Value, Parameters, Box, Allocators, node_variant_dynamic_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag>\r
+{\r
+ typedef variant_leaf<Value, Parameters, Box, Allocators, node_variant_dynamic_tag> type;\r
+};\r
+\r
+// visitor traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>\r
+struct visitor<Value, Parameters, Box, Allocators, node_variant_dynamic_tag, IsVisitableConst>\r
+{\r
+ typedef static_visitor<> type;\r
+};\r
+\r
+// allocators\r
+\r
+template <typename Allocator, typename Value, typename Parameters, typename Box>\r
+class allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>\r
+ : public Allocator::template rebind<\r
+ typename node<\r
+ Value, Parameters, Box,\r
+ allocators<Allocator, Value, Parameters, Box, node_variant_dynamic_tag>,\r
+ node_variant_dynamic_tag\r
+ >::type\r
+ >::other\r
+{\r
+ typedef typename Allocator::template rebind<\r
+ Value\r
+ >::other value_allocator_type;\r
+\r
+public:\r
+ typedef Allocator allocator_type;\r
+\r
+ typedef Value value_type;\r
+ typedef typename value_allocator_type::reference reference;\r
+ typedef typename value_allocator_type::const_reference const_reference;\r
+ typedef typename value_allocator_type::size_type size_type;\r
+ typedef typename value_allocator_type::difference_type difference_type;\r
+ typedef typename value_allocator_type::pointer pointer;\r
+ typedef typename value_allocator_type::const_pointer const_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename node<Value, Parameters, Box, allocators, node_variant_dynamic_tag>::type\r
+ >::other::pointer node_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename node<Value, Parameters, Box, allocators, node_variant_dynamic_tag>::type\r
+ >::other node_allocator_type;\r
+\r
+ inline allocators()\r
+ : node_allocator_type()\r
+ {}\r
+\r
+ template <typename Alloc>\r
+ inline explicit allocators(Alloc const& alloc)\r
+ : node_allocator_type(alloc)\r
+ {}\r
+\r
+ inline allocators(BOOST_FWD_REF(allocators) a)\r
+ : node_allocator_type(boost::move(a.node_allocator()))\r
+ {}\r
+\r
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)\r
+ {\r
+ node_allocator() = boost::move(a.node_allocator());\r
+ return *this;\r
+ }\r
+\r
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+ inline allocators & operator=(allocators const& a)\r
+ {\r
+ node_allocator() = a.node_allocator();\r
+ return *this;\r
+ }\r
+#endif\r
+\r
+ void swap(allocators & a)\r
+ {\r
+ boost::swap(node_allocator(), a.node_allocator());\r
+ }\r
+\r
+ bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }\r
+ template <typename Alloc>\r
+ bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }\r
+\r
+ Allocator allocator() const { return Allocator(node_allocator()); }\r
+\r
+ node_allocator_type & node_allocator() { return *this; }\r
+ node_allocator_type const& node_allocator() const { return *this; }\r
+};\r
+\r
+// create_node_variant\r
+\r
+template <typename VariantPtr, typename Node>\r
+struct create_variant_node\r
+{\r
+ template <typename AllocNode>\r
+ static inline VariantPtr apply(AllocNode & alloc_node)\r
+ {\r
+ typedef boost::container::allocator_traits<AllocNode> Al;\r
+ typedef typename Al::pointer P;\r
+\r
+ P p = Al::allocate(alloc_node, 1);\r
+\r
+ if ( 0 == p )\r
+ throw_runtime_error("boost::geometry::index::rtree node creation failed");\r
+\r
+ scoped_deallocator<AllocNode> deallocator(p, alloc_node);\r
+\r
+ Al::construct(alloc_node, boost::addressof(*p), Node(alloc_node)); // implicit cast to Variant\r
+\r
+ deallocator.release();\r
+ return p;\r
+ }\r
+};\r
+\r
+// destroy_node_variant\r
+\r
+template <typename Node>\r
+struct destroy_variant_node\r
+{\r
+ template <typename AllocNode, typename VariantPtr>\r
+ static inline void apply(AllocNode & alloc_node, VariantPtr n)\r
+ {\r
+ typedef boost::container::allocator_traits<AllocNode> Al;\r
+\r
+ Al::destroy(alloc_node, boost::addressof(*n));\r
+ Al::deallocate(alloc_node, n, 1);\r
+ }\r
+};\r
+\r
+// create_node\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct create_node<\r
+ Allocators,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline typename Allocators::node_pointer\r
+ apply(Allocators & allocators)\r
+ {\r
+ return create_variant_node<\r
+ typename Allocators::node_pointer,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.node_allocator());\r
+ }\r
+};\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct create_node<\r
+ Allocators,\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline typename Allocators::node_pointer\r
+ apply(Allocators & allocators)\r
+ {\r
+ return create_variant_node<\r
+ typename Allocators::node_pointer,\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.node_allocator());\r
+ }\r
+};\r
+\r
+// destroy_node\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct destroy_node<\r
+ Allocators,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)\r
+ {\r
+ destroy_variant_node<\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.node_allocator(), n);\r
+ }\r
+};\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct destroy_node<\r
+ Allocators,\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)\r
+ {\r
+ destroy_variant_node<\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.node_allocator(), n);\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes based on Boost.Variant, storing static-size containers\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// nodes default types\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>\r
+{\r
+ typedef detail::varray<\r
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,\r
+ Parameters::max_elements + 1\r
+ > elements_type;\r
+\r
+ template <typename Alloc>\r
+ inline variant_internal_node(Alloc const&) {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>\r
+{\r
+ typedef detail::varray<\r
+ Value,\r
+ Parameters::max_elements + 1\r
+ > elements_type;\r
+\r
+ template <typename Alloc>\r
+ inline variant_leaf(Alloc const&) {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+// nodes traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct node<Value, Parameters, Box, Allocators, node_variant_static_tag>\r
+{\r
+ typedef boost::variant<\r
+ variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>\r
+ > type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag>\r
+{\r
+ typedef variant_internal_node<Value, Parameters, Box, Allocators, node_variant_static_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct leaf<Value, Parameters, Box, Allocators, node_variant_static_tag>\r
+{\r
+ typedef variant_leaf<Value, Parameters, Box, Allocators, node_variant_static_tag> type;\r
+};\r
+\r
+// visitor traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>\r
+struct visitor<Value, Parameters, Box, Allocators, node_variant_static_tag, IsVisitableConst>\r
+{\r
+ typedef static_visitor<> type;\r
+};\r
+\r
+// allocators\r
+\r
+template <typename Allocator, typename Value, typename Parameters, typename Box>\r
+class allocators<Allocator, Value, Parameters, Box, node_variant_static_tag>\r
+ : public Allocator::template rebind<\r
+ typename node<\r
+ Value, Parameters, Box,\r
+ allocators<Allocator, Value, Parameters, Box, node_variant_static_tag>,\r
+ node_variant_static_tag\r
+ >::type\r
+ >::other\r
+{\r
+ typedef typename Allocator::template rebind<\r
+ Value\r
+ >::other value_allocator_type;\r
+\r
+public:\r
+ typedef Allocator allocator_type;\r
+\r
+ typedef Value value_type;\r
+ typedef value_type & reference;\r
+ typedef const value_type & const_reference;\r
+ typedef typename value_allocator_type::size_type size_type;\r
+ typedef typename value_allocator_type::difference_type difference_type;\r
+ typedef typename value_allocator_type::pointer pointer;\r
+ typedef typename value_allocator_type::const_pointer const_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename node<Value, Parameters, Box, allocators, node_variant_static_tag>::type\r
+ >::other::pointer node_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename node<Value, Parameters, Box, allocators, node_variant_static_tag>::type\r
+ >::other node_allocator_type;\r
+\r
+ inline allocators()\r
+ : node_allocator_type()\r
+ {}\r
+\r
+ template <typename Alloc>\r
+ inline explicit allocators(Alloc const& alloc)\r
+ : node_allocator_type(alloc)\r
+ {}\r
+\r
+ inline allocators(BOOST_FWD_REF(allocators) a)\r
+ : node_allocator_type(boost::move(a.node_allocator()))\r
+ {}\r
+\r
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)\r
+ {\r
+ node_allocator() = boost::move(a.node_allocator());\r
+ return *this;\r
+ }\r
+\r
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+ inline allocators & operator=(allocators const& a)\r
+ {\r
+ node_allocator() = a.node_allocator();\r
+ return *this;\r
+ }\r
+#endif\r
+\r
+ void swap(allocators & a)\r
+ {\r
+ boost::swap(node_allocator(), a.node_allocator());\r
+ }\r
+\r
+ bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }\r
+ template <typename Alloc>\r
+ bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }\r
+\r
+ Allocator allocator() const { return Allocator(node_allocator()); }\r
+\r
+ node_allocator_type & node_allocator() { return *this; }\r
+ node_allocator_type const& node_allocator() const { return *this; }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes static visitor related code\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_VISITOR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_VISITOR_HPP\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/get.hpp>\r
+#include <boost/variant/variant.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// nodes variants forward declarations\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct variant_internal_node;\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct variant_leaf;\r
+\r
+// nodes conversion\r
+\r
+template <typename V, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+inline V & get(\r
+ boost::variant<\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ > & v)\r
+{\r
+ return boost::get<V>(v);\r
+}\r
+\r
+// apply visitor\r
+\r
+template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+inline void apply_visitor(Visitor & v,\r
+ boost::variant<\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ > & n)\r
+{\r
+ boost::apply_visitor(v, n);\r
+}\r
+\r
+template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+inline void apply_visitor(Visitor & v,\r
+ boost::variant<\r
+ variant_leaf<Value, Parameters, Box, Allocators, Tag>,\r
+ variant_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ > const& n)\r
+{\r
+ boost::apply_visitor(v, n);\r
+}\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_VISITOR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes based on static conversion, storing dynamic-size containers\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct weak_internal_node\r
+ : public weak_node<Value, Parameters, Box, Allocators, Tag>\r
+{\r
+ typedef boost::container::vector\r
+ <\r
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,\r
+ typename Allocators::internal_node_allocator_type::template rebind\r
+ <\r
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>\r
+ >::other\r
+ > elements_type;\r
+\r
+ template <typename Al>\r
+ inline weak_internal_node(Al const& al)\r
+ : elements(al)\r
+ {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct weak_leaf\r
+ : public weak_node<Value, Parameters, Box, Allocators, Tag>\r
+{\r
+ typedef boost::container::vector\r
+ <\r
+ Value,\r
+ typename Allocators::leaf_allocator_type::template rebind\r
+ <\r
+ Value\r
+ >::other\r
+ > elements_type;\r
+\r
+ template <typename Al>\r
+ inline weak_leaf(Al const& al)\r
+ : elements(al)\r
+ {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+// nodes traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>\r
+{\r
+ typedef weak_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct internal_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>\r
+{\r
+ typedef weak_internal_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct leaf<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>\r
+{\r
+ typedef weak_leaf<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;\r
+};\r
+\r
+// visitor traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>\r
+struct visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisitableConst>\r
+{\r
+ typedef weak_visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisitableConst> type;\r
+};\r
+\r
+// allocators\r
+\r
+template <typename Allocator, typename Value, typename Parameters, typename Box>\r
+class allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>\r
+ : public Allocator::template rebind<\r
+ typename internal_node<\r
+ Value, Parameters, Box,\r
+ allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>,\r
+ node_weak_dynamic_tag\r
+ >::type\r
+ >::other\r
+ , public Allocator::template rebind<\r
+ typename leaf<\r
+ Value, Parameters, Box,\r
+ allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>,\r
+ node_weak_dynamic_tag\r
+ >::type\r
+ >::other\r
+{\r
+ typedef typename Allocator::template rebind<\r
+ Value\r
+ >::other value_allocator_type;\r
+\r
+public:\r
+ typedef Allocator allocator_type;\r
+ \r
+ typedef Value value_type;\r
+ typedef typename value_allocator_type::reference reference;\r
+ typedef typename value_allocator_type::const_reference const_reference;\r
+ typedef typename value_allocator_type::size_type size_type;\r
+ typedef typename value_allocator_type::difference_type difference_type;\r
+ typedef typename value_allocator_type::pointer pointer;\r
+ typedef typename value_allocator_type::const_pointer const_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename node<Value, Parameters, Box, allocators, node_weak_dynamic_tag>::type\r
+ >::other::pointer node_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename internal_node<Value, Parameters, Box, allocators, node_weak_dynamic_tag>::type\r
+ >::other internal_node_allocator_type;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename leaf<Value, Parameters, Box, allocators, node_weak_dynamic_tag>::type\r
+ >::other leaf_allocator_type;\r
+\r
+ inline allocators()\r
+ : internal_node_allocator_type()\r
+ , leaf_allocator_type()\r
+ {}\r
+\r
+ template <typename Alloc>\r
+ inline explicit allocators(Alloc const& alloc)\r
+ : internal_node_allocator_type(alloc)\r
+ , leaf_allocator_type(alloc)\r
+ {}\r
+\r
+ inline allocators(BOOST_FWD_REF(allocators) a)\r
+ : internal_node_allocator_type(boost::move(a.internal_node_allocator()))\r
+ , leaf_allocator_type(boost::move(a.leaf_allocator()))\r
+ {}\r
+\r
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)\r
+ {\r
+ internal_node_allocator() = ::boost::move(a.internal_node_allocator());\r
+ leaf_allocator() = ::boost::move(a.leaf_allocator());\r
+ return *this;\r
+ }\r
+\r
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+ inline allocators & operator=(allocators const& a)\r
+ {\r
+ internal_node_allocator() = a.internal_node_allocator();\r
+ leaf_allocator() = a.leaf_allocator();\r
+ return *this;\r
+ }\r
+#endif\r
+\r
+ void swap(allocators & a)\r
+ {\r
+ boost::swap(internal_node_allocator(), a.internal_node_allocator());\r
+ boost::swap(leaf_allocator(), a.leaf_allocator());\r
+ }\r
+\r
+ bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }\r
+ template <typename Alloc>\r
+ bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }\r
+\r
+ Allocator allocator() const { return Allocator(leaf_allocator()); }\r
+\r
+ internal_node_allocator_type & internal_node_allocator() { return *this; }\r
+ internal_node_allocator_type const& internal_node_allocator() const { return *this; }\r
+ leaf_allocator_type & leaf_allocator() { return *this; }\r
+ leaf_allocator_type const& leaf_allocator() const { return *this; }\r
+};\r
+\r
+// create_node_impl\r
+\r
+template <typename BaseNodePtr, typename Node>\r
+struct create_weak_node\r
+{\r
+ template <typename AllocNode>\r
+ static inline BaseNodePtr apply(AllocNode & alloc_node)\r
+ {\r
+ typedef boost::container::allocator_traits<AllocNode> Al;\r
+ typedef typename Al::pointer P;\r
+\r
+ P p = Al::allocate(alloc_node, 1);\r
+\r
+ if ( 0 == p )\r
+ throw_runtime_error("boost::geometry::index::rtree node creation failed");\r
+\r
+ scoped_deallocator<AllocNode> deallocator(p, alloc_node);\r
+\r
+ Al::construct(alloc_node, boost::addressof(*p), alloc_node);\r
+\r
+ deallocator.release();\r
+ return p;\r
+ }\r
+};\r
+\r
+// destroy_node_impl\r
+\r
+template <typename Node>\r
+struct destroy_weak_node\r
+{\r
+ template <typename AllocNode, typename BaseNodePtr>\r
+ static inline void apply(AllocNode & alloc_node, BaseNodePtr n)\r
+ {\r
+ typedef boost::container::allocator_traits<AllocNode> Al;\r
+ typedef typename Al::pointer P;\r
+\r
+ P p(&static_cast<Node&>(rtree::get<Node>(*n)));\r
+ Al::destroy(alloc_node, boost::addressof(*p));\r
+ Al::deallocate(alloc_node, p, 1);\r
+ }\r
+};\r
+\r
+// create_node\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct create_node<\r
+ Allocators,\r
+ weak_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline typename Allocators::node_pointer\r
+ apply(Allocators & allocators)\r
+ {\r
+ return create_weak_node<\r
+ typename Allocators::node_pointer,\r
+ weak_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.internal_node_allocator());\r
+ }\r
+};\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct create_node<\r
+ Allocators,\r
+ weak_leaf<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline typename Allocators::node_pointer\r
+ apply(Allocators & allocators)\r
+ {\r
+ return create_weak_node<\r
+ typename Allocators::node_pointer,\r
+ weak_leaf<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.leaf_allocator());\r
+ }\r
+};\r
+\r
+// destroy_node\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct destroy_node<\r
+ Allocators,\r
+ weak_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)\r
+ {\r
+ destroy_weak_node<\r
+ weak_internal_node<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.internal_node_allocator(), n);\r
+ }\r
+};\r
+\r
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>\r
+struct destroy_node<\r
+ Allocators,\r
+ weak_leaf<Value, Parameters, Box, Allocators, Tag>\r
+>\r
+{\r
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)\r
+ {\r
+ destroy_weak_node<\r
+ weak_leaf<Value, Parameters, Box, Allocators, Tag>\r
+ >::apply(allocators.leaf_allocator(), n);\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes based on static conversion, storing static-size containers\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct weak_internal_node<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+ : public weak_node<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+{\r
+ typedef detail::varray<\r
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,\r
+ Parameters::max_elements + 1\r
+ > elements_type;\r
+\r
+ template <typename Alloc>\r
+ inline weak_internal_node(Alloc const&) {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct weak_leaf<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+ : public weak_node<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+{\r
+ typedef detail::varray<\r
+ Value,\r
+ Parameters::max_elements + 1\r
+ > elements_type;\r
+\r
+ template <typename Alloc>\r
+ inline weak_leaf(Alloc const&) {}\r
+\r
+ elements_type elements;\r
+};\r
+\r
+// nodes traits\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct node<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+{\r
+ typedef weak_node<Value, Parameters, Box, Allocators, node_weak_static_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct internal_node<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+{\r
+ typedef weak_internal_node<Value, Parameters, Box, Allocators, node_weak_static_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators>\r
+struct leaf<Value, Parameters, Box, Allocators, node_weak_static_tag>\r
+{\r
+ typedef weak_leaf<Value, Parameters, Box, Allocators, node_weak_static_tag> type;\r
+};\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>\r
+struct visitor<Value, Parameters, Box, Allocators, node_weak_static_tag, IsVisitableConst>\r
+{\r
+ typedef weak_visitor<Value, Parameters, Box, Allocators, node_weak_static_tag, IsVisitableConst> type;\r
+};\r
+\r
+// allocators\r
+\r
+template <typename Allocator, typename Value, typename Parameters, typename Box>\r
+class allocators<Allocator, Value, Parameters, Box, node_weak_static_tag>\r
+ : public Allocator::template rebind<\r
+ typename internal_node<\r
+ Value, Parameters, Box,\r
+ allocators<Allocator, Value, Parameters, Box, node_weak_static_tag>,\r
+ node_weak_static_tag\r
+ >::type\r
+ >::other\r
+ , public Allocator::template rebind<\r
+ typename leaf<\r
+ Value, Parameters, Box,\r
+ allocators<Allocator, Value, Parameters, Box, node_weak_static_tag>,\r
+ node_weak_static_tag\r
+ >::type\r
+ >::other\r
+{\r
+ typedef typename Allocator::template rebind<\r
+ Value\r
+ >::other value_allocator_type;\r
+\r
+public:\r
+ typedef Allocator allocator_type;\r
+\r
+ typedef Value value_type;\r
+ typedef value_type & reference;\r
+ typedef const value_type & const_reference;\r
+ typedef typename value_allocator_type::size_type size_type;\r
+ typedef typename value_allocator_type::difference_type difference_type;\r
+ typedef typename value_allocator_type::pointer pointer;\r
+ typedef typename value_allocator_type::const_pointer const_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename node<Value, Parameters, Box, allocators, node_weak_static_tag>::type\r
+ >::other::pointer node_pointer;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename internal_node<Value, Parameters, Box, allocators, node_weak_static_tag>::type\r
+ >::other internal_node_allocator_type;\r
+\r
+ typedef typename Allocator::template rebind<\r
+ typename leaf<Value, Parameters, Box, allocators, node_weak_static_tag>::type\r
+ >::other leaf_allocator_type;\r
+\r
+ inline allocators()\r
+ : internal_node_allocator_type()\r
+ , leaf_allocator_type()\r
+ {}\r
+\r
+ template <typename Alloc>\r
+ inline explicit allocators(Alloc const& alloc)\r
+ : internal_node_allocator_type(alloc)\r
+ , leaf_allocator_type(alloc)\r
+ {}\r
+\r
+ inline allocators(BOOST_FWD_REF(allocators) a)\r
+ : internal_node_allocator_type(boost::move(a.internal_node_allocator()))\r
+ , leaf_allocator_type(boost::move(a.leaf_allocator()))\r
+ {}\r
+\r
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)\r
+ {\r
+ internal_node_allocator() = ::boost::move(a.internal_node_allocator());\r
+ leaf_allocator() = ::boost::move(a.leaf_allocator());\r
+ return *this;\r
+ }\r
+\r
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+ inline allocators & operator=(allocators const& a)\r
+ {\r
+ internal_node_allocator() = a.internal_node_allocator();\r
+ leaf_allocator() = a.leaf_allocator();\r
+ return *this;\r
+ }\r
+#endif\r
+\r
+ void swap(allocators & a)\r
+ {\r
+ boost::swap(internal_node_allocator(), a.internal_node_allocator());\r
+ boost::swap(leaf_allocator(), a.leaf_allocator());\r
+ }\r
+\r
+ bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }\r
+ template <typename Alloc>\r
+ bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }\r
+\r
+ Allocator allocator() const { return Allocator(leaf_allocator()); }\r
+\r
+ internal_node_allocator_type & internal_node_allocator() { return *this; }\r
+ internal_node_allocator_type const& internal_node_allocator() const { return *this; }\r
+ leaf_allocator_type & leaf_allocator() { return *this; }\r
+ leaf_allocator_type const& leaf_allocator() const{ return *this; }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes weak visitor and nodes base type\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// empty visitor\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>\r
+struct weak_visitor {};\r
+\r
+// node\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct weak_node {};\r
+\r
+// nodes variants forward declarations\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct weak_internal_node;\r
+\r
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+struct weak_leaf;\r
+\r
+// nodes conversion\r
+\r
+template <typename Derived, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+inline Derived & get(weak_node<Value, Parameters, Box, Allocators, Tag> & n)\r
+{\r
+ return static_cast<Derived&>(n);\r
+}\r
+\r
+// apply visitor\r
+\r
+template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>\r
+inline void apply_visitor(Visitor & v,\r
+ weak_node<Value, Parameters, Box, Allocators, Tag> & n,\r
+ bool is_internal_node)\r
+{\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n, "null ptr");\r
+ if ( is_internal_node )\r
+ {\r
+ typedef weak_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;\r
+ v(get<internal_node>(n));\r
+ }\r
+ else\r
+ {\r
+ typedef weak_leaf<Value, Parameters, Box, Allocators, Tag> leaf;\r
+ v(get<leaf>(n));\r
+ }\r
+}\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree options, algorithms, parameters\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP\r
+\r
+#include <boost/geometry/index/parameters.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// InsertTag\r
+struct insert_default_tag {};\r
+struct insert_reinsert_tag {};\r
+\r
+// ChooseNextNodeTag\r
+struct choose_by_content_diff_tag {};\r
+struct choose_by_overlap_diff_tag {};\r
+\r
+// SplitTag\r
+struct split_default_tag {};\r
+//struct split_kmeans_tag {};\r
+\r
+// RedistributeTag\r
+struct linear_tag {};\r
+struct quadratic_tag {};\r
+struct rstar_tag {};\r
+\r
+// NodeTag\r
+struct node_variant_dynamic_tag {};\r
+struct node_variant_static_tag {};\r
+//struct node_weak_dynamic_tag {};\r
+//struct node_weak_static_tag {};\r
+\r
+template <typename Parameters, typename InsertTag, typename ChooseNextNodeTag, typename SplitTag, typename RedistributeTag, typename NodeTag>\r
+struct options\r
+{\r
+ typedef Parameters parameters_type;\r
+ typedef InsertTag insert_tag;\r
+ typedef ChooseNextNodeTag choose_next_node_tag;\r
+ typedef SplitTag split_tag;\r
+ typedef RedistributeTag redistribute_tag;\r
+ typedef NodeTag node_tag;\r
+};\r
+\r
+template <typename Parameters>\r
+struct options_type\r
+{\r
+ // TODO: awulkiew - use static assert\r
+};\r
+\r
+template <size_t MaxElements, size_t MinElements>\r
+struct options_type< index::linear<MaxElements, MinElements> >\r
+{\r
+ typedef options<\r
+ index::linear<MaxElements, MinElements>,\r
+ insert_default_tag,\r
+ choose_by_content_diff_tag,\r
+ split_default_tag,\r
+ linear_tag,\r
+ node_variant_static_tag\r
+ > type;\r
+};\r
+\r
+template <size_t MaxElements, size_t MinElements>\r
+struct options_type< index::quadratic<MaxElements, MinElements> >\r
+{\r
+ typedef options<\r
+ index::quadratic<MaxElements, MinElements>,\r
+ insert_default_tag,\r
+ choose_by_content_diff_tag,\r
+ split_default_tag,\r
+ quadratic_tag,\r
+ node_variant_static_tag\r
+ > type;\r
+};\r
+\r
+template <size_t MaxElements, size_t MinElements, size_t OverlapCostThreshold, size_t ReinsertedElements>\r
+struct options_type< index::rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements> >\r
+{\r
+ typedef options<\r
+ index::rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements>,\r
+ insert_reinsert_tag,\r
+ choose_by_overlap_diff_tag,\r
+ split_default_tag,\r
+ rstar_tag,\r
+ node_variant_static_tag\r
+ > type;\r
+};\r
+\r
+//template <size_t MaxElements, size_t MinElements>\r
+//struct options_type< kmeans<MaxElements, MinElements> >\r
+//{\r
+// typedef options<\r
+// kmeans<MaxElements, MinElements>,\r
+// insert_default_tag,\r
+// choose_by_content_diff_tag, // change it?\r
+// split_kmeans_tag,\r
+// int, // dummy tag - not used for now\r
+// node_variant_static_tag\r
+// > type;\r
+//};\r
+\r
+template <>\r
+struct options_type< index::dynamic_linear >\r
+{\r
+ typedef options<\r
+ index::dynamic_linear,\r
+ insert_default_tag,\r
+ choose_by_content_diff_tag,\r
+ split_default_tag,\r
+ linear_tag,\r
+ node_variant_dynamic_tag\r
+ > type;\r
+};\r
+\r
+template <>\r
+struct options_type< index::dynamic_quadratic >\r
+{\r
+ typedef options<\r
+ index::dynamic_quadratic,\r
+ insert_default_tag,\r
+ choose_by_content_diff_tag,\r
+ split_default_tag,\r
+ quadratic_tag,\r
+ node_variant_dynamic_tag\r
+ > type;\r
+};\r
+\r
+template <>\r
+struct options_type< index::dynamic_rstar >\r
+{\r
+ typedef options<\r
+ index::dynamic_rstar,\r
+ insert_reinsert_tag,\r
+ choose_by_overlap_diff_tag,\r
+ split_default_tag,\r
+ rstar_tag,\r
+ node_variant_dynamic_tag\r
+ > type;\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree initial packing\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP\r
+\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {\r
+\r
+namespace pack_utils {\r
+\r
+template <std::size_t Dimension>\r
+struct biggest_edge\r
+{\r
+ BOOST_STATIC_ASSERT(0 < Dimension);\r
+ template <typename Box>\r
+ static inline void apply(Box const& box, typename coordinate_type<Box>::type & length, std::size_t & dim_index)\r
+ {\r
+ biggest_edge<Dimension-1>::apply(box, length, dim_index);\r
+ typename coordinate_type<Box>::type curr\r
+ = geometry::get<max_corner, Dimension-1>(box) - geometry::get<min_corner, Dimension-1>(box);\r
+ if ( length < curr )\r
+ {\r
+ dim_index = Dimension - 1;\r
+ length = curr;\r
+ }\r
+ }\r
+};\r
+\r
+template <>\r
+struct biggest_edge<1>\r
+{\r
+ template <typename Box>\r
+ static inline void apply(Box const& box, typename coordinate_type<Box>::type & length, std::size_t & dim_index)\r
+ {\r
+ dim_index = 0;\r
+ length = geometry::get<max_corner, 0>(box) - geometry::get<min_corner, 0>(box);\r
+ }\r
+};\r
+\r
+template <std::size_t I>\r
+struct point_entries_comparer\r
+{\r
+ template <typename PointEntry>\r
+ bool operator()(PointEntry const& e1, PointEntry const& e2) const\r
+ {\r
+ return geometry::get<I>(e1.first) < geometry::get<I>(e2.first);\r
+ }\r
+};\r
+\r
+template <std::size_t I, std::size_t Dimension>\r
+struct nth_element_and_half_boxes\r
+{\r
+ template <typename EIt, typename Box>\r
+ static inline void apply(EIt first, EIt median, EIt last, Box const& box, Box & left, Box & right, std::size_t dim_index)\r
+ {\r
+ if ( I == dim_index )\r
+ {\r
+ std::nth_element(first, median, last, point_entries_comparer<I>());\r
+\r
+ geometry::convert(box, left);\r
+ geometry::convert(box, right);\r
+ typename coordinate_type<Box>::type edge_len\r
+ = geometry::get<max_corner, I>(box) - geometry::get<min_corner, I>(box);\r
+ typename coordinate_type<Box>::type median\r
+ = geometry::get<min_corner, I>(box) + edge_len / 2;\r
+ geometry::set<max_corner, I>(left, median);\r
+ geometry::set<min_corner, I>(right, median);\r
+ }\r
+ else\r
+ nth_element_and_half_boxes<I+1, Dimension>::apply(first, median, last, box, left, right, dim_index);\r
+ }\r
+};\r
+\r
+template <std::size_t Dimension>\r
+struct nth_element_and_half_boxes<Dimension, Dimension>\r
+{\r
+ template <typename EIt, typename Box>\r
+ static inline void apply(EIt , EIt , EIt , Box const& , Box & , Box & , std::size_t ) {}\r
+};\r
+\r
+} // namespace pack_utils\r
+\r
+// STR leafs number are calculated as rcount/max\r
+// and the number of splitting planes for each dimension as (count/max)^(1/dimension)\r
+// <-> for dimension==2 -> sqrt(count/max)\r
+//\r
+// The main flaw of this algorithm is that the resulting tree will have bad structure for:\r
+// 1. non-uniformly distributed elements\r
+// Statistic check could be performed, e.g. based on variance of lengths of elements edges for each dimension\r
+// 2. elements distributed mainly along one axis\r
+// Calculate bounding box of all elements and then number of dividing planes for a dimension\r
+// from the length of BB edge for this dimension (more or less assuming that elements are uniformly-distributed squares)\r
+//\r
+// Another thing is that the last node may have less elements than Max or even Min.\r
+// The number of splitting planes must be chosen more carefully than count/max\r
+//\r
+// This algorithm is something between STR and TGS\r
+// it is more similar to the top-down recursive kd-tree creation algorithm\r
+// using object median split and split axis of greatest BB edge\r
+// BB is only used as a hint (assuming objects are distributed uniformly)\r
+//\r
+// Implemented algorithm guarantees that the number of elements in nodes will be between Min and Max\r
+// and that nodes are packed as tightly as possible\r
+// e.g. for 177 values Max = 5 and Min = 2 it will construct the following tree:\r
+// ROOT 177\r
+// L1 125 52\r
+// L2 25 25 25 25 25 25 17 10\r
+// L3 5x5 5x5 5x5 5x5 5x5 5x5 3x5+2 2x5\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class pack\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ typedef typename geometry::point_type<Box>::type point_type;\r
+ typedef typename geometry::coordinate_type<point_type>::type coordinate_type;\r
+ typedef typename detail::default_content_result<Box>::type content_type;\r
+ typedef typename Options::parameters_type parameters_type;\r
+ static const std::size_t dimension = geometry::dimension<point_type>::value;\r
+\r
+ typedef typename rtree::container_from_elements_type<\r
+ typename rtree::elements_type<leaf>::type,\r
+ std::size_t\r
+ >::type values_counts_container;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type internal_elements;\r
+ typedef typename internal_elements::value_type internal_element;\r
+\r
+public:\r
+ // Arbitrary iterators\r
+ template <typename InIt> inline static\r
+ node_pointer apply(InIt first, InIt last, size_type & values_count, size_type & leafs_level,\r
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)\r
+ {\r
+ typedef typename std::iterator_traits<InIt>::difference_type diff_type;\r
+ \r
+ diff_type diff = std::distance(first, last);\r
+ if ( diff <= 0 )\r
+ return node_pointer(0);\r
+\r
+ typedef std::pair<point_type, InIt> entry_type;\r
+ std::vector<entry_type> entries;\r
+\r
+ values_count = static_cast<size_type>(diff);\r
+ entries.reserve(values_count);\r
+ \r
+ expandable_box<Box> hint_box;\r
+ for ( ; first != last ; ++first )\r
+ {\r
+ // NOTE: support for iterators not returning true references adapted\r
+ // to Geometry concept and default translator returning true reference\r
+ // An alternative would be to dereference the iterator and translate\r
+ // in one expression each time the indexable was needed.\r
+ typename std::iterator_traits<InIt>::reference in_ref = *first;\r
+ typename Translator::result_type indexable = translator(in_ref);\r
+\r
+ // NOTE: added for consistency with insert()\r
+ // CONSIDER: alternative - ignore invalid indexable or throw an exception\r
+ BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(indexable), "Indexable is invalid");\r
+\r
+ hint_box.expand(indexable);\r
+\r
+ point_type pt;\r
+ geometry::centroid(indexable, pt);\r
+ entries.push_back(std::make_pair(pt, first));\r
+ }\r
+\r
+ subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level);\r
+ internal_element el = per_level(entries.begin(), entries.end(), hint_box.get(), values_count, subtree_counts,\r
+ parameters, translator, allocators);\r
+\r
+ return el.second;\r
+ }\r
+\r
+private:\r
+ template <typename BoxType>\r
+ class expandable_box\r
+ {\r
+ public:\r
+ expandable_box()\r
+ : m_initialized(false)\r
+ {}\r
+\r
+ template <typename Indexable>\r
+ explicit expandable_box(Indexable const& indexable)\r
+ : m_initialized(true)\r
+ {\r
+ detail::bounds(indexable, m_box);\r
+ }\r
+\r
+ template <typename Indexable>\r
+ void expand(Indexable const& indexable)\r
+ {\r
+ if ( !m_initialized )\r
+ {\r
+ // it's guaranteed that the Box will be initialized\r
+ // only for Points, Boxes and Segments but that's ok\r
+ // since only those Geometries can be stored\r
+ detail::bounds(indexable, m_box);\r
+ m_initialized = true;\r
+ }\r
+ else\r
+ {\r
+ geometry::expand(m_box, indexable);\r
+ }\r
+ }\r
+\r
+ void expand_by_epsilon()\r
+ {\r
+ geometry::detail::expand_by_epsilon(m_box);\r
+ }\r
+\r
+ BoxType const& get() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_initialized, "uninitialized envelope accessed");\r
+ return m_box;\r
+ }\r
+\r
+ private:\r
+ bool m_initialized;\r
+ BoxType m_box;\r
+ };\r
+\r
+ struct subtree_elements_counts\r
+ {\r
+ subtree_elements_counts(std::size_t ma, std::size_t mi) : maxc(ma), minc(mi) {}\r
+ std::size_t maxc;\r
+ std::size_t minc;\r
+ };\r
+\r
+ template <typename EIt> inline static\r
+ internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts,\r
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,\r
+ "unexpected parameters");\r
+\r
+ if ( subtree_counts.maxc <= 1 )\r
+ {\r
+ // ROOT or LEAF\r
+ BOOST_GEOMETRY_INDEX_ASSERT(values_count <= parameters.get_max_elements(),\r
+ "too big number of elements");\r
+ // if !root check m_parameters.get_min_elements() <= count\r
+\r
+ // create new leaf node\r
+ node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)\r
+ subtree_destroyer auto_remover(n, allocators);\r
+ leaf & l = rtree::get<leaf>(*n);\r
+\r
+ // reserve space for values\r
+ rtree::elements(l).reserve(values_count); // MAY THROW (A)\r
+\r
+ // calculate values box and copy values\r
+ // initialize the box explicitly to avoid GCC-4.4 uninitialized variable warnings with O2\r
+ expandable_box<Box> elements_box(translator(*(first->second)));\r
+ rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)\r
+ for ( ++first ; first != last ; ++first )\r
+ {\r
+ // NOTE: push_back() must be called at the end in order to support move_iterator.\r
+ // The iterator is dereferenced 2x (no temporary reference) to support\r
+ // non-true reference types and move_iterator without boost::forward<>.\r
+ elements_box.expand(translator(*(first->second)));\r
+ rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON\r
+ // Enlarge bounds of a leaf node.\r
+ // It's because Points and Segments are compared WRT machine epsilon\r
+ // This ensures that leafs bounds correspond to the stored elements\r
+ // NOTE: this is done only if the Indexable is a different kind of Geometry\r
+ // than the bounds (only Box for now). Spatial predicates are checked\r
+ // the same way for Geometry of the same kind.\r
+ if ( BOOST_GEOMETRY_CONDITION((\r
+ ! index::detail::is_bounding_geometry\r
+ <\r
+ typename indexable_type<Translator>::type\r
+ >::value )) )\r
+ {\r
+ elements_box.expand_by_epsilon();\r
+ }\r
+#endif\r
+\r
+ auto_remover.release();\r
+ return internal_element(elements_box.get(), n);\r
+ }\r
+\r
+ // calculate next max and min subtree counts\r
+ subtree_elements_counts next_subtree_counts = subtree_counts;\r
+ next_subtree_counts.maxc /= parameters.get_max_elements();\r
+ next_subtree_counts.minc /= parameters.get_max_elements();\r
+\r
+ // create new internal node\r
+ node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)\r
+ subtree_destroyer auto_remover(n, allocators);\r
+ internal_node & in = rtree::get<internal_node>(*n);\r
+\r
+ // reserve space for values\r
+ std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts);\r
+ rtree::elements(in).reserve(nodes_count); // MAY THROW (A)\r
+ // calculate values box and copy values\r
+ expandable_box<Box> elements_box;\r
+ \r
+ per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,\r
+ rtree::elements(in), elements_box,\r
+ parameters, translator, allocators);\r
+\r
+ auto_remover.release();\r
+ return internal_element(elements_box.get(), n);\r
+ }\r
+\r
+ template <typename EIt, typename ExpandableBox> inline static\r
+ void per_level_packets(EIt first, EIt last, Box const& hint_box,\r
+ std::size_t values_count,\r
+ subtree_elements_counts const& subtree_counts,\r
+ subtree_elements_counts const& next_subtree_counts,\r
+ internal_elements & elements, ExpandableBox & elements_box,\r
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count,\r
+ "unexpected parameters");\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(subtree_counts.minc <= values_count,\r
+ "too small number of elements");\r
+\r
+ // only one packet\r
+ if ( values_count <= subtree_counts.maxc )\r
+ {\r
+ // the end, move to the next level\r
+ internal_element el = per_level(first, last, hint_box, values_count, next_subtree_counts,\r
+ parameters, translator, allocators);\r
+\r
+ // in case if push_back() do throw here\r
+ // and even if this is not probable (previously reserved memory, nonthrowing pairs copy)\r
+ // this case is also tested by exceptions test.\r
+ subtree_destroyer auto_remover(el.second, allocators);\r
+ // this container should have memory allocated, reserve() called outside\r
+ elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't\r
+ auto_remover.release();\r
+\r
+ elements_box.expand(el.first);\r
+ return;\r
+ }\r
+ \r
+ std::size_t median_count = calculate_median_count(values_count, subtree_counts);\r
+ EIt median = first + median_count;\r
+\r
+ coordinate_type greatest_length;\r
+ std::size_t greatest_dim_index = 0;\r
+ pack_utils::biggest_edge<dimension>::apply(hint_box, greatest_length, greatest_dim_index);\r
+ Box left, right;\r
+ pack_utils::nth_element_and_half_boxes<0, dimension>\r
+ ::apply(first, median, last, hint_box, left, right, greatest_dim_index);\r
+ \r
+ per_level_packets(first, median, left,\r
+ median_count, subtree_counts, next_subtree_counts,\r
+ elements, elements_box,\r
+ parameters, translator, allocators);\r
+ per_level_packets(median, last, right,\r
+ values_count - median_count, subtree_counts, next_subtree_counts,\r
+ elements, elements_box,\r
+ parameters, translator, allocators);\r
+ }\r
+\r
+ inline static\r
+ subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters, size_type & leafs_level)\r
+ {\r
+ boost::ignore_unused_variable_warning(parameters);\r
+\r
+ subtree_elements_counts res(1, 1);\r
+ leafs_level = 0;\r
+\r
+ std::size_t smax = parameters.get_max_elements();\r
+ for ( ; smax < elements_count ; smax *= parameters.get_max_elements(), ++leafs_level )\r
+ res.maxc = smax;\r
+\r
+ res.minc = parameters.get_min_elements() * (res.maxc / parameters.get_max_elements());\r
+\r
+ return res;\r
+ }\r
+\r
+ inline static\r
+ std::size_t calculate_nodes_count(std::size_t count,\r
+ subtree_elements_counts const& subtree_counts)\r
+ {\r
+ std::size_t n = count / subtree_counts.maxc;\r
+ std::size_t r = count % subtree_counts.maxc;\r
+\r
+ if ( 0 < r && r < subtree_counts.minc )\r
+ {\r
+ std::size_t count_minus_min = count - subtree_counts.minc;\r
+ n = count_minus_min / subtree_counts.maxc;\r
+ r = count_minus_min % subtree_counts.maxc;\r
+ ++n;\r
+ }\r
+\r
+ if ( 0 < r )\r
+ ++n;\r
+\r
+ return n;\r
+ }\r
+\r
+ inline static\r
+ std::size_t calculate_median_count(std::size_t count,\r
+ subtree_elements_counts const& subtree_counts)\r
+ {\r
+ // e.g. for max = 5, min = 2, count = 52, subtree_max = 25, subtree_min = 10\r
+\r
+ std::size_t n = count / subtree_counts.maxc; // e.g. 52 / 25 = 2\r
+ std::size_t r = count % subtree_counts.maxc; // e.g. 52 % 25 = 2\r
+ std::size_t median_count = (n / 2) * subtree_counts.maxc; // e.g. 2 / 2 * 25 = 25\r
+\r
+ if ( 0 != r ) // e.g. 0 != 2\r
+ {\r
+ if ( subtree_counts.minc <= r ) // e.g. 10 <= 2 == false\r
+ {\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value");\r
+ median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((2+1)/2) * 25 which would be ok, but not in all cases\r
+ }\r
+ else // r < subtree_counts.second // e.g. 2 < 10 == true\r
+ {\r
+ std::size_t count_minus_min = count - subtree_counts.minc; // e.g. 52 - 10 = 42\r
+ n = count_minus_min / subtree_counts.maxc; // e.g. 42 / 25 = 1\r
+ r = count_minus_min % subtree_counts.maxc; // e.g. 42 % 25 = 17\r
+ if ( r == 0 ) // e.g. false\r
+ {\r
+ // n can't be equal to 0 because then there wouldn't be any element in the other node\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value");\r
+ median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((1+1)/2) * 25 which would be ok, but not in all cases\r
+ }\r
+ else\r
+ {\r
+ if ( n == 0 ) // e.g. false\r
+ median_count = r; // if calculated -> 17 which is wrong!\r
+ else\r
+ median_count = ((n+2)/2) * subtree_counts.maxc; // e.g. ((1+2)/2) * 25 = 25\r
+ }\r
+ }\r
+ }\r
+\r
+ return median_count;\r
+ }\r
+};\r
+\r
+}}}}} // namespace boost::geometry::index::detail::rtree\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree quadratic algorithm implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree quadratic split algorithm implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>\r
+\r
+#include <boost/geometry/index/detail/bounded_view.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+namespace quadratic {\r
+\r
+template <typename Box, typename Elements, typename Parameters, typename Translator>\r
+inline void pick_seeds(Elements const& elements,\r
+ Parameters const& parameters,\r
+ Translator const& tr,\r
+ size_t & seed1,\r
+ size_t & seed2)\r
+{\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef Box box_type;\r
+ typedef typename index::detail::default_content_result<box_type>::type content_type;\r
+ typedef index::detail::bounded_view<indexable_type, box_type> bounded_indexable_view;\r
+\r
+ const size_t elements_count = parameters.get_max_elements() + 1;\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "wrong number of elements");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");\r
+\r
+ content_type greatest_free_content = 0;\r
+ seed1 = 0;\r
+ seed2 = 1;\r
+\r
+ for ( size_t i = 0 ; i < elements_count - 1 ; ++i )\r
+ {\r
+ for ( size_t j = i + 1 ; j < elements_count ; ++j )\r
+ {\r
+ indexable_type const& ind1 = rtree::element_indexable(elements[i], tr);\r
+ indexable_type const& ind2 = rtree::element_indexable(elements[j], tr);\r
+\r
+ box_type enlarged_box;\r
+ detail::bounds(ind1, enlarged_box);\r
+ geometry::expand(enlarged_box, ind2);\r
+\r
+ bounded_indexable_view bounded_ind1(ind1);\r
+ bounded_indexable_view bounded_ind2(ind2);\r
+ content_type free_content = ( index::detail::content(enlarged_box)\r
+ - index::detail::content(bounded_ind1) )\r
+ - index::detail::content(bounded_ind2);\r
+ \r
+ if ( greatest_free_content < free_content )\r
+ {\r
+ greatest_free_content = free_content;\r
+ seed1 = i;\r
+ seed2 = j;\r
+ }\r
+ }\r
+ }\r
+\r
+ ::boost::ignore_unused_variable_warning(parameters);\r
+}\r
+\r
+} // namespace quadratic\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadratic_tag>\r
+{\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Node>\r
+ static inline void apply(Node & n,\r
+ Node & second_node,\r
+ Box & box1,\r
+ Box & box2,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators)\r
+ {\r
+ typedef typename rtree::elements_type<Node>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+\r
+ elements_type & elements1 = rtree::elements(n);\r
+ elements_type & elements2 = rtree::elements(second_node);\r
+ \r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == parameters.get_max_elements() + 1, "unexpected elements number");\r
+\r
+ // copy original elements - use in-memory storage (std::allocator)\r
+ // TODO: move if noexcept\r
+ typedef typename rtree::container_from_elements_type<elements_type, element_type>::type\r
+ container_type;\r
+ container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)\r
+ container_type elements_backup(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)\r
+ \r
+ // calculate initial seeds\r
+ size_t seed1 = 0;\r
+ size_t seed2 = 0;\r
+ quadratic::pick_seeds<Box>(elements_copy, parameters, translator, seed1, seed2);\r
+\r
+ // prepare nodes' elements containers\r
+ elements1.clear();\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "second node's elements container should be empty");\r
+\r
+ BOOST_TRY\r
+ {\r
+ // add seeds\r
+ elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)\r
+ elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)\r
+\r
+ // calculate boxes\r
+ detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);\r
+ detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);\r
+\r
+ // remove seeds\r
+ if (seed1 < seed2)\r
+ {\r
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed2); // MAY THROW, STRONG (copy)\r
+ elements_copy.pop_back();\r
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed1); // MAY THROW, STRONG (copy)\r
+ elements_copy.pop_back();\r
+ }\r
+ else\r
+ {\r
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed1); // MAY THROW, STRONG (copy)\r
+ elements_copy.pop_back();\r
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed2); // MAY THROW, STRONG (copy)\r
+ elements_copy.pop_back();\r
+ }\r
+\r
+ // initialize areas\r
+ content_type content1 = index::detail::content(box1);\r
+ content_type content2 = index::detail::content(box2);\r
+\r
+ size_t remaining = elements_copy.size();\r
+\r
+ // redistribute the rest of the elements\r
+ while ( !elements_copy.empty() )\r
+ {\r
+ typename container_type::reverse_iterator el_it = elements_copy.rbegin();\r
+ bool insert_into_group1 = false;\r
+\r
+ size_t elements1_count = elements1.size();\r
+ size_t elements2_count = elements2.size();\r
+\r
+ // if there is small number of elements left and the number of elements in node is lesser than min_elems\r
+ // just insert them to this node\r
+ if ( elements1_count + remaining <= parameters.get_min_elements() )\r
+ {\r
+ insert_into_group1 = true;\r
+ }\r
+ else if ( elements2_count + remaining <= parameters.get_min_elements() )\r
+ {\r
+ insert_into_group1 = false;\r
+ }\r
+ // insert the best element\r
+ else\r
+ {\r
+ // find element with minimum groups areas increses differences\r
+ content_type content_increase1 = 0;\r
+ content_type content_increase2 = 0;\r
+ el_it = pick_next(elements_copy.rbegin(), elements_copy.rend(),\r
+ box1, box2, content1, content2, translator,\r
+ content_increase1, content_increase2);\r
+\r
+ if ( content_increase1 < content_increase2 ||\r
+ ( content_increase1 == content_increase2 && ( content1 < content2 ||\r
+ ( content1 == content2 && elements1_count <= elements2_count ) )\r
+ ) )\r
+ {\r
+ insert_into_group1 = true;\r
+ }\r
+ else\r
+ {\r
+ insert_into_group1 = false;\r
+ }\r
+ }\r
+\r
+ // move element to the choosen group\r
+ element_type const& elem = *el_it;\r
+ indexable_type const& indexable = rtree::element_indexable(elem, translator);\r
+\r
+ if ( insert_into_group1 )\r
+ {\r
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)\r
+ geometry::expand(box1, indexable);\r
+ content1 = index::detail::content(box1);\r
+ }\r
+ else\r
+ {\r
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)\r
+ geometry::expand(box2, indexable);\r
+ content2 = index::detail::content(box2);\r
+ }\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!elements_copy.empty(), "expected more elements");\r
+ typename container_type::iterator el_it_base = el_it.base();\r
+ rtree::move_from_back(elements_copy, --el_it_base); // MAY THROW, STRONG (copy)\r
+ elements_copy.pop_back();\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "expected more remaining elements");\r
+ --remaining;\r
+ }\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ //elements_copy.clear();\r
+ elements1.clear();\r
+ elements2.clear();\r
+\r
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);\r
+ //elements_backup.clear();\r
+\r
+ BOOST_RETHROW // RETHROW, BASIC\r
+ }\r
+ BOOST_CATCH_END\r
+ }\r
+\r
+ // TODO: awulkiew - change following function to static member of the pick_next class?\r
+\r
+ template <typename It>\r
+ static inline It pick_next(It first, It last,\r
+ Box const& box1, Box const& box2,\r
+ content_type const& content1, content_type const& content2,\r
+ Translator const& translator,\r
+ content_type & out_content_increase1, content_type & out_content_increase2)\r
+ {\r
+ typedef typename boost::iterator_value<It>::type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+\r
+ content_type greatest_content_incrase_diff = 0;\r
+ It out_it = first;\r
+ out_content_increase1 = 0;\r
+ out_content_increase2 = 0;\r
+ \r
+ // find element with greatest difference between increased group's boxes areas\r
+ for ( It el_it = first ; el_it != last ; ++el_it )\r
+ {\r
+ indexable_type const& indexable = rtree::element_indexable(*el_it, translator);\r
+\r
+ // calculate enlarged boxes and areas\r
+ Box enlarged_box1(box1);\r
+ Box enlarged_box2(box2);\r
+ geometry::expand(enlarged_box1, indexable);\r
+ geometry::expand(enlarged_box2, indexable);\r
+ content_type enlarged_content1 = index::detail::content(enlarged_box1);\r
+ content_type enlarged_content2 = index::detail::content(enlarged_box2);\r
+\r
+ content_type content_incrase1 = (enlarged_content1 - content1);\r
+ content_type content_incrase2 = (enlarged_content2 - content2);\r
+\r
+ content_type content_incrase_diff = content_incrase1 < content_incrase2 ?\r
+ content_incrase2 - content_incrase1 : content_incrase1 - content_incrase2;\r
+\r
+ if ( greatest_content_incrase_diff < content_incrase_diff )\r
+ {\r
+ greatest_content_incrase_diff = content_incrase_diff;\r
+ out_it = el_it;\r
+ out_content_increase1 = content_incrase1;\r
+ out_content_increase2 = content_incrase2;\r
+ }\r
+ }\r
+\r
+ return out_it;\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree query iterators\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP\r
+\r
+#include <boost/scoped_ptr.hpp>\r
+\r
+//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {\r
+\r
+template <typename Value, typename Allocators>\r
+struct end_query_iterator\r
+{\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ reference operator*() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");\r
+ pointer p(0);\r
+ return *p;\r
+ }\r
+\r
+ const value_type * operator->() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not dereferencable");\r
+ const value_type * p = 0;\r
+ return p;\r
+ }\r
+\r
+ end_query_iterator & operator++()\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");\r
+ return *this;\r
+ }\r
+\r
+ end_query_iterator operator++(int)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "iterator not incrementable");\r
+ return *this;\r
+ }\r
+\r
+ friend bool operator==(end_query_iterator const& /*l*/, end_query_iterator const& /*r*/)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>\r
+class spatial_query_iterator\r
+{\r
+ typedef visitors::spatial_query_incremental<Value, Options, Translator, Box, Allocators, Predicates> visitor_type;\r
+ typedef typename visitor_type::node_pointer node_pointer;\r
+\r
+public:\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ inline spatial_query_iterator()\r
+ {}\r
+\r
+ inline spatial_query_iterator(Translator const& t, Predicates const& p)\r
+ : m_visitor(t, p)\r
+ {}\r
+\r
+ inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p)\r
+ : m_visitor(t, p)\r
+ {\r
+ m_visitor.initialize(root);\r
+ }\r
+\r
+ reference operator*() const\r
+ {\r
+ return m_visitor.dereference();\r
+ }\r
+\r
+ const value_type * operator->() const\r
+ {\r
+ return boost::addressof(m_visitor.dereference());\r
+ }\r
+\r
+ spatial_query_iterator & operator++()\r
+ {\r
+ m_visitor.increment();\r
+ return *this;\r
+ }\r
+\r
+ spatial_query_iterator operator++(int)\r
+ {\r
+ spatial_query_iterator temp = *this;\r
+ this->operator++();\r
+ return temp;\r
+ }\r
+\r
+ friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)\r
+ {\r
+ return l.m_visitor == r.m_visitor;\r
+ }\r
+\r
+ friend bool operator==(spatial_query_iterator const& l, end_query_iterator<Value, Allocators> const& /*r*/)\r
+ {\r
+ return l.m_visitor.is_end();\r
+ }\r
+\r
+ friend bool operator==(end_query_iterator<Value, Allocators> const& /*l*/, spatial_query_iterator const& r)\r
+ {\r
+ return r.m_visitor.is_end();\r
+ }\r
+ \r
+private:\r
+ visitor_type m_visitor;\r
+};\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, unsigned NearestPredicateIndex>\r
+class distance_query_iterator\r
+{\r
+ typedef visitors::distance_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> visitor_type;\r
+ typedef typename visitor_type::node_pointer node_pointer;\r
+\r
+public:\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ inline distance_query_iterator()\r
+ {}\r
+\r
+ inline distance_query_iterator(Translator const& t, Predicates const& p)\r
+ : m_visitor(t, p)\r
+ {}\r
+\r
+ inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p)\r
+ : m_visitor(t, p)\r
+ {\r
+ m_visitor.initialize(root);\r
+ }\r
+\r
+ reference operator*() const\r
+ {\r
+ return m_visitor.dereference();\r
+ }\r
+\r
+ const value_type * operator->() const\r
+ {\r
+ return boost::addressof(m_visitor.dereference());\r
+ }\r
+\r
+ distance_query_iterator & operator++()\r
+ {\r
+ m_visitor.increment();\r
+ return *this;\r
+ }\r
+\r
+ distance_query_iterator operator++(int)\r
+ {\r
+ distance_query_iterator temp = *this;\r
+ this->operator++();\r
+ return temp;\r
+ }\r
+\r
+ friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r)\r
+ {\r
+ return l.m_visitor == r.m_visitor;\r
+ }\r
+\r
+ friend bool operator==(distance_query_iterator const& l, end_query_iterator<Value, Allocators> const& /*r*/)\r
+ {\r
+ return l.m_visitor.is_end();\r
+ }\r
+\r
+ friend bool operator==(end_query_iterator<Value, Allocators> const& /*l*/, distance_query_iterator const& r)\r
+ {\r
+ return r.m_visitor.is_end();\r
+ }\r
+\r
+private:\r
+ visitor_type m_visitor;\r
+};\r
+\r
+\r
+template <typename L, typename R>\r
+inline bool operator!=(L const& l, R const& r)\r
+{\r
+ return !(l == r);\r
+}\r
+\r
+\r
+template <typename Value, typename Allocators>\r
+class query_iterator_base\r
+{\r
+public:\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ virtual ~query_iterator_base() {}\r
+\r
+ virtual query_iterator_base * clone() const = 0;\r
+ \r
+ virtual bool is_end() const = 0;\r
+ virtual reference dereference() const = 0;\r
+ virtual void increment() = 0;\r
+ virtual bool equals(query_iterator_base const&) const = 0;\r
+};\r
+\r
+template <typename Value, typename Allocators, typename Iterator>\r
+class query_iterator_wrapper\r
+ : public query_iterator_base<Value, Allocators>\r
+{\r
+ typedef query_iterator_base<Value, Allocators> base_t;\r
+\r
+public:\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ query_iterator_wrapper() : m_iterator() {}\r
+ explicit query_iterator_wrapper(Iterator const& it) : m_iterator(it) {}\r
+\r
+ virtual base_t * clone() const { return new query_iterator_wrapper(m_iterator); }\r
+\r
+ virtual bool is_end() const { return m_iterator == end_query_iterator<Value, Allocators>(); }\r
+ virtual reference dereference() const { return *m_iterator; }\r
+ virtual void increment() { ++m_iterator; }\r
+ virtual bool equals(base_t const& r) const\r
+ {\r
+ const query_iterator_wrapper * p = dynamic_cast<const query_iterator_wrapper *>(boost::addressof(r));\r
+ BOOST_GEOMETRY_INDEX_ASSERT(p, "iterators can't be compared");\r
+ return m_iterator == p->m_iterator;\r
+ }\r
+\r
+private:\r
+ Iterator m_iterator;\r
+};\r
+\r
+\r
+template <typename Value, typename Allocators>\r
+class query_iterator\r
+{\r
+ typedef query_iterator_base<Value, Allocators> iterator_base;\r
+ typedef boost::scoped_ptr<iterator_base> iterator_ptr;\r
+\r
+public:\r
+ typedef std::forward_iterator_tag iterator_category;\r
+ typedef Value value_type;\r
+ typedef typename Allocators::const_reference reference;\r
+ typedef typename Allocators::difference_type difference_type;\r
+ typedef typename Allocators::const_pointer pointer;\r
+\r
+ query_iterator()\r
+ {}\r
+\r
+ template <typename It>\r
+ query_iterator(It const& it)\r
+ : m_ptr(static_cast<iterator_base*>(\r
+ new query_iterator_wrapper<Value, Allocators, It>(it) ))\r
+ {}\r
+\r
+ query_iterator(end_query_iterator<Value, Allocators> const& /*it*/)\r
+ {}\r
+\r
+ query_iterator(query_iterator const& o)\r
+ : m_ptr(o.m_ptr.get() ? o.m_ptr->clone() : 0)\r
+ {}\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE\r
+ query_iterator & operator=(query_iterator const& o)\r
+ {\r
+ if ( this != boost::addressof(o) )\r
+ {\r
+ m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);\r
+ }\r
+ return *this;\r
+ }\r
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+ query_iterator(query_iterator && o)\r
+ : m_ptr(0)\r
+ {\r
+ m_ptr.swap(o.m_ptr);\r
+ }\r
+ query_iterator & operator=(query_iterator && o)\r
+ {\r
+ if ( this != boost::addressof(o) )\r
+ {\r
+ m_ptr.swap(o.m_ptr);\r
+ o.m_ptr.reset();\r
+ }\r
+ return *this;\r
+ }\r
+#endif\r
+#else // !BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE\r
+private:\r
+ BOOST_COPYABLE_AND_MOVABLE(query_iterator)\r
+public:\r
+ query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)\r
+ {\r
+ if ( this != boost::addressof(o) )\r
+ {\r
+ m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);\r
+ }\r
+ return *this;\r
+ }\r
+ query_iterator(BOOST_RV_REF(query_iterator) o)\r
+ : m_ptr(0)\r
+ {\r
+ m_ptr.swap(o.m_ptr);\r
+ }\r
+ query_iterator & operator=(BOOST_RV_REF(query_iterator) o)\r
+ {\r
+ if ( this != boost::addressof(o) )\r
+ {\r
+ m_ptr.swap(o.m_ptr);\r
+ o.m_ptr.reset();\r
+ }\r
+ return *this;\r
+ }\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE\r
+\r
+ reference operator*() const\r
+ {\r
+ return m_ptr->dereference();\r
+ }\r
+\r
+ const value_type * operator->() const\r
+ {\r
+ return boost::addressof(m_ptr->dereference());\r
+ }\r
+\r
+ query_iterator & operator++()\r
+ {\r
+ m_ptr->increment();\r
+ return *this;\r
+ }\r
+\r
+ query_iterator operator++(int)\r
+ {\r
+ query_iterator temp = *this;\r
+ this->operator++();\r
+ return temp;\r
+ }\r
+\r
+ friend bool operator==(query_iterator const& l, query_iterator const& r)\r
+ {\r
+ if ( l.m_ptr.get() )\r
+ {\r
+ if ( r.m_ptr.get() )\r
+ return l.m_ptr->equals(*r.m_ptr);\r
+ else\r
+ return l.m_ptr->is_end();\r
+ }\r
+ else\r
+ {\r
+ if ( r.m_ptr.get() )\r
+ return r.m_ptr->is_end();\r
+ else\r
+ return true;\r
+ }\r
+ }\r
+\r
+private:\r
+ iterator_ptr m_ptr;\r
+};\r
+\r
+}}}}}} // namespace boost::geometry::index::detail::rtree::iterators\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree R*-tree next node choosing algorithm implementation\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>\r
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+class choose_next_node<Value, Options, Box, Allocators, choose_by_overlap_diff_tag>\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type children_type;\r
+ typedef typename children_type::value_type child_type;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+public:\r
+ template <typename Indexable>\r
+ static inline size_t apply(internal_node & n,\r
+ Indexable const& indexable,\r
+ parameters_type const& parameters,\r
+ size_t node_relative_level)\r
+ {\r
+ ::boost::ignore_unused_variable_warning(parameters);\r
+\r
+ children_type & children = rtree::elements(n);\r
+ \r
+ // children are leafs\r
+ if ( node_relative_level <= 1 )\r
+ {\r
+ return choose_by_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());\r
+ }\r
+ // children are internal nodes\r
+ else\r
+ return choose_by_minimum_content_cost(children, indexable);\r
+ }\r
+\r
+private:\r
+ template <typename Indexable>\r
+ static inline size_t choose_by_minimum_overlap_cost(children_type const& children,\r
+ Indexable const& indexable,\r
+ size_t overlap_cost_threshold)\r
+ {\r
+ const size_t children_count = children.size();\r
+\r
+ content_type min_content_diff = (std::numeric_limits<content_type>::max)();\r
+ content_type min_content = (std::numeric_limits<content_type>::max)();\r
+ size_t choosen_index = 0;\r
+\r
+ // create container of children sorted by content enlargement needed to include the new value\r
+ typedef boost::tuple<size_t, content_type, content_type> child_contents;\r
+\r
+ typename rtree::container_from_elements_type<children_type, child_contents>::type children_contents;\r
+ children_contents.resize(children_count);\r
+\r
+ for ( size_t i = 0 ; i < children_count ; ++i )\r
+ {\r
+ child_type const& ch_i = children[i];\r
+\r
+ // expanded child node's box\r
+ Box box_exp(ch_i.first);\r
+ geometry::expand(box_exp, indexable);\r
+\r
+ // areas difference\r
+ content_type content = index::detail::content(box_exp);\r
+ content_type content_diff = content - index::detail::content(ch_i.first);\r
+\r
+ children_contents[i] = boost::make_tuple(i, content_diff, content);\r
+\r
+ if ( content_diff < min_content_diff ||\r
+ (content_diff == min_content_diff && content < min_content) )\r
+ {\r
+ min_content_diff = content_diff;\r
+ min_content = content;\r
+ choosen_index = i;\r
+ }\r
+ }\r
+\r
+ // is this assumption ok? if min_content_diff == 0 there is no overlap increase?\r
+\r
+ if ( min_content_diff < -std::numeric_limits<double>::epsilon() || std::numeric_limits<double>::epsilon() < min_content_diff )\r
+ {\r
+ size_t first_n_children_count = children_count;\r
+ if ( 0 < overlap_cost_threshold && overlap_cost_threshold < children.size() )\r
+ {\r
+ first_n_children_count = overlap_cost_threshold;\r
+ // rearrange by content_diff\r
+ // in order to calculate nearly minimum overlap cost\r
+ std::nth_element(children_contents.begin(), children_contents.begin() + first_n_children_count, children_contents.end(), content_diff_less);\r
+ }\r
+\r
+ // calculate minimum or nearly minimum overlap cost\r
+ choosen_index = choose_by_minimum_overlap_cost_first_n(children, indexable, first_n_children_count, children_count, children_contents);\r
+ }\r
+\r
+ return choosen_index;\r
+ }\r
+\r
+ static inline bool content_diff_less(boost::tuple<size_t, content_type, content_type> const& p1, boost::tuple<size_t, content_type, content_type> const& p2)\r
+ {\r
+ return boost::get<1>(p1) < boost::get<1>(p2) ||\r
+ (boost::get<1>(p1) == boost::get<1>(p2) && boost::get<2>(p1) < boost::get<2>(p2));\r
+ }\r
+\r
+ template <typename Indexable, typename ChildrenContents>\r
+ static inline size_t choose_by_minimum_overlap_cost_first_n(children_type const& children,\r
+ Indexable const& indexable,\r
+ size_t const first_n_children_count,\r
+ size_t const children_count,\r
+ ChildrenContents const& children_contents)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(first_n_children_count <= children_count, "unexpected value");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(children_contents.size() == children_count, "unexpected number of elements");\r
+\r
+ // choose index with smallest overlap change value, or content change or smallest content\r
+ size_t choosen_index = 0;\r
+ content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();\r
+ content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();\r
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();\r
+\r
+ // for each child node\r
+ for (size_t i = 0 ; i < first_n_children_count ; ++i )\r
+ {\r
+ child_type const& ch_i = children[i];\r
+\r
+ Box box_exp(ch_i.first);\r
+ // calculate expanded box of child node ch_i\r
+ geometry::expand(box_exp, indexable);\r
+\r
+ content_type overlap_diff = 0;\r
+\r
+ // calculate overlap\r
+ for ( size_t j = 0 ; j < children_count ; ++j )\r
+ {\r
+ if ( i != j )\r
+ {\r
+ child_type const& ch_j = children[j];\r
+\r
+ content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);\r
+ if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )\r
+ {\r
+ overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);\r
+ }\r
+ }\r
+ }\r
+\r
+ content_type content = boost::get<2>(children_contents[i]);\r
+ content_type content_diff = boost::get<1>(children_contents[i]);\r
+\r
+ // update result\r
+ if ( overlap_diff < smallest_overlap_diff ||\r
+ ( overlap_diff == smallest_overlap_diff && ( content_diff < smallest_content_diff ||\r
+ ( content_diff == smallest_content_diff && content < smallest_content ) )\r
+ ) )\r
+ {\r
+ smallest_overlap_diff = overlap_diff;\r
+ smallest_content_diff = content_diff;\r
+ smallest_content = content;\r
+ choosen_index = i;\r
+ }\r
+ }\r
+\r
+ return choosen_index;\r
+ }\r
+\r
+ template <typename Indexable>\r
+ static inline size_t choose_by_minimum_content_cost(children_type const& children, Indexable const& indexable)\r
+ {\r
+ size_t children_count = children.size();\r
+\r
+ // choose index with smallest content change or smallest content\r
+ size_t choosen_index = 0;\r
+ content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();\r
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();\r
+\r
+ // choose the child which requires smallest box expansion to store the indexable\r
+ for ( size_t i = 0 ; i < children_count ; ++i )\r
+ {\r
+ child_type const& ch_i = children[i];\r
+\r
+ // expanded child node's box\r
+ Box box_exp(ch_i.first);\r
+ geometry::expand(box_exp, indexable);\r
+\r
+ // areas difference\r
+ content_type content = index::detail::content(box_exp);\r
+ content_type content_diff = content - index::detail::content(ch_i.first);\r
+\r
+ // update the result\r
+ if ( content_diff < smallest_content_diff ||\r
+ ( content_diff == smallest_content_diff && content < smallest_content ) )\r
+ {\r
+ smallest_content_diff = content_diff;\r
+ smallest_content = content;\r
+ choosen_index = i;\r
+ }\r
+ }\r
+\r
+ return choosen_index;\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree R*-tree insert algorithm implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+namespace rstar {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class remove_elements_to_reinsert\r
+{\r
+public:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ //typedef typename Allocators::internal_node_pointer internal_node_pointer;\r
+ typedef internal_node * internal_node_pointer;\r
+\r
+ template <typename ResultElements, typename Node>\r
+ static inline void apply(ResultElements & result_elements,\r
+ Node & n,\r
+ internal_node_pointer parent,\r
+ size_t current_child_index,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators)\r
+ {\r
+ typedef typename rtree::elements_type<Node>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ typedef typename geometry::point_type<Box>::type point_type;\r
+ // TODO: awulkiew - change second point_type to the point type of the Indexable?\r
+ typedef typename\r
+ geometry::default_comparable_distance_result<point_type>::type\r
+ comparable_distance_type;\r
+\r
+ elements_type & elements = rtree::elements(n);\r
+\r
+ const size_t elements_count = parameters.get_max_elements() + 1;\r
+ const size_t reinserted_elements_count = (::std::min)(parameters.get_reinserted_elements(), elements_count - parameters.get_min_elements());\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(parent, "node shouldn't be the root node");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");\r
+\r
+ // calculate current node's center\r
+ point_type node_center;\r
+ geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);\r
+\r
+ // fill the container of centers' distances of children from current node's center\r
+ typedef typename index::detail::rtree::container_from_elements_type<\r
+ elements_type,\r
+ std::pair<comparable_distance_type, element_type>\r
+ >::type sorted_elements_type;\r
+\r
+ sorted_elements_type sorted_elements;\r
+ // If constructor is used instead of resize() MS implementation leaks here\r
+ sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)\r
+ \r
+ for ( typename elements_type::const_iterator it = elements.begin() ;\r
+ it != elements.end() ; ++it )\r
+ {\r
+ point_type element_center;\r
+ geometry::centroid( rtree::element_indexable(*it, translator), element_center);\r
+ sorted_elements.push_back(std::make_pair(\r
+ geometry::comparable_distance(node_center, element_center),\r
+ *it)); // MAY THROW (V, E: copy)\r
+ }\r
+\r
+ // sort elements by distances from center\r
+ std::partial_sort(\r
+ sorted_elements.begin(),\r
+ sorted_elements.begin() + reinserted_elements_count,\r
+ sorted_elements.end(),\r
+ distances_dsc<comparable_distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)\r
+\r
+ // copy elements which will be reinserted\r
+ result_elements.clear();\r
+ result_elements.reserve(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)\r
+ for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ;\r
+ it != sorted_elements.begin() + reinserted_elements_count ; ++it )\r
+ {\r
+ result_elements.push_back(it->second); // MAY THROW (V, E: copy)\r
+ }\r
+\r
+ BOOST_TRY\r
+ {\r
+ // copy remaining elements to the current node\r
+ elements.clear();\r
+ elements.reserve(elements_count - reinserted_elements_count); // SHOULDN'T THROW (new_size <= old size)\r
+ for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count;\r
+ it != sorted_elements.end() ; ++it )\r
+ {\r
+ elements.push_back(it->second); // MAY THROW (V, E: copy)\r
+ }\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ elements.clear();\r
+\r
+ for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ;\r
+ it != sorted_elements.end() ; ++it )\r
+ {\r
+ destroy_element<Value, Options, Translator, Box, Allocators>::apply(it->second, allocators);\r
+ }\r
+\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ ::boost::ignore_unused_variable_warning(parameters);\r
+ }\r
+\r
+private:\r
+ template <typename Distance, typename El>\r
+ static inline bool distances_asc(\r
+ std::pair<Distance, El> const& d1,\r
+ std::pair<Distance, El> const& d2)\r
+ {\r
+ return d1.first < d2.first;\r
+ }\r
+ \r
+ template <typename Distance, typename El>\r
+ static inline bool distances_dsc(\r
+ std::pair<Distance, El> const& d1,\r
+ std::pair<Distance, El> const& d2)\r
+ {\r
+ return d1.first > d2.first;\r
+ }\r
+};\r
+\r
+template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Box, typename Allocators>\r
+struct level_insert_elements_type\r
+{\r
+ typedef typename rtree::elements_type<\r
+ typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type\r
+ >::type type;\r
+};\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+struct level_insert_elements_type<0, Value, Value, Options, Box, Allocators>\r
+{\r
+ typedef typename rtree::elements_type<\r
+ typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type\r
+ >::type type;\r
+};\r
+\r
+template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct level_insert_base\r
+ : public detail::insert<Element, Value, Options, Translator, Box, Allocators>\r
+{\r
+ typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;\r
+ typedef typename base::node node;\r
+ typedef typename base::internal_node internal_node;\r
+ typedef typename base::leaf leaf;\r
+\r
+ typedef typename level_insert_elements_type<InsertIndex, Element, Value, Options, Box, Allocators>::type elements_type;\r
+ typedef typename index::detail::rtree::container_from_elements_type<\r
+ elements_type,\r
+ typename elements_type::value_type\r
+ >::type result_elements_type;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ inline level_insert_base(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Element const& element,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level)\r
+ : base(root, leafs_level, element, parameters, translator, allocators, relative_level)\r
+ , result_relative_level(0)\r
+ {}\r
+\r
+ template <typename Node>\r
+ inline void handle_possible_reinsert_or_split_of_root(Node &n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(result_elements.empty(), "reinsert should be handled only once for level");\r
+\r
+ result_relative_level = base::m_leafs_level - base::m_traverse_data.current_level;\r
+\r
+ // overflow\r
+ if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )\r
+ {\r
+ // node isn't root node\r
+ if ( !base::m_traverse_data.current_is_root() )\r
+ {\r
+ // NOTE: exception-safety\r
+ // After an exception result_elements may contain garbage, don't use it\r
+ rstar::remove_elements_to_reinsert<Value, Options, Translator, Box, Allocators>::apply(\r
+ result_elements, n,\r
+ base::m_traverse_data.parent, base::m_traverse_data.current_child_index,\r
+ base::m_parameters, base::m_translator, base::m_allocators); // MAY THROW, BASIC (V, E: alloc, copy)\r
+ }\r
+ // node is root node\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*base::m_root_node), "node should be the root node");\r
+ base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+ }\r
+ }\r
+ }\r
+\r
+ template <typename Node>\r
+ inline void handle_possible_split(Node &n) const\r
+ {\r
+ // overflow\r
+ if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )\r
+ {\r
+ base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+ }\r
+ }\r
+\r
+ template <typename Node>\r
+ inline void recalculate_aabb_if_necessary(Node const& n) const\r
+ {\r
+ if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )\r
+ {\r
+ // calulate node's new box\r
+ recalculate_aabb(n);\r
+ }\r
+ }\r
+\r
+ template <typename Node>\r
+ inline void recalculate_aabb(Node const& n) const\r
+ {\r
+ base::m_traverse_data.current_element().first =\r
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);\r
+ }\r
+\r
+ inline void recalculate_aabb(leaf const& n) const\r
+ {\r
+ base::m_traverse_data.current_element().first =\r
+ values_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);\r
+ }\r
+\r
+ size_type result_relative_level;\r
+ result_elements_type result_elements;\r
+};\r
+\r
+template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct level_insert\r
+ : public level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators>\r
+{\r
+ typedef level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators> base;\r
+ typedef typename base::node node;\r
+ typedef typename base::internal_node internal_node;\r
+ typedef typename base::leaf leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ inline level_insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Element const& element,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level)\r
+ : base(root, leafs_level, element, parameters, translator, allocators, relative_level)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");\r
+\r
+ if ( base::m_traverse_data.current_level < base::m_level )\r
+ {\r
+ // next traversing step\r
+ base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)\r
+\r
+ // further insert\r
+ if ( 0 < InsertIndex )\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");\r
+\r
+ if ( base::m_traverse_data.current_level == base::m_level - 1 )\r
+ {\r
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");\r
+\r
+ BOOST_TRY\r
+ {\r
+ // push new child node\r
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ // NOTE: exception-safety\r
+ // if the insert fails above, the element won't be stored in the tree, so delete it\r
+\r
+ rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);\r
+ rtree::apply_visitor(del_v, *base::m_element.second);\r
+\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ // first insert\r
+ if ( 0 == InsertIndex )\r
+ {\r
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)\r
+ }\r
+ // not the first insert\r
+ else\r
+ {\r
+ base::handle_possible_split(n); // MAY THROW (E: alloc, N: alloc)\r
+ }\r
+ }\r
+\r
+ base::recalculate_aabb_if_necessary(n);\r
+ }\r
+\r
+ inline void operator()(leaf &)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");\r
+ }\r
+};\r
+\r
+template <size_t InsertIndex, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct level_insert<InsertIndex, Value, Value, Options, Translator, Box, Allocators>\r
+ : public level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators>\r
+{\r
+ typedef level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators> base;\r
+ typedef typename base::node node;\r
+ typedef typename base::internal_node internal_node;\r
+ typedef typename base::leaf leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ inline level_insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Value const& v,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level)\r
+ : base(root, leafs_level, v, parameters, translator, allocators, relative_level)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");\r
+\r
+ // next traversing step\r
+ base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");\r
+ \r
+ if ( base::m_traverse_data.current_level == base::m_level - 1 )\r
+ {\r
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)\r
+ }\r
+\r
+ base::recalculate_aabb_if_necessary(n);\r
+ }\r
+\r
+ inline void operator()(leaf & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,\r
+ "unexpected level");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||\r
+ base::m_level == (std::numeric_limits<size_t>::max)(),\r
+ "unexpected level");\r
+ \r
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)\r
+\r
+ base::handle_possible_split(n); // MAY THROW (V: alloc, copy, N: alloc)\r
+ }\r
+};\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct level_insert<0, Value, Value, Options, Translator, Box, Allocators>\r
+ : public level_insert_base<0, Value, Value, Options, Translator, Box, Allocators>\r
+{\r
+ typedef level_insert_base<0, Value, Value, Options, Translator, Box, Allocators> base;\r
+ typedef typename base::node node;\r
+ typedef typename base::internal_node internal_node;\r
+ typedef typename base::leaf leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ inline level_insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Value const& v,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level)\r
+ : base(root, leafs_level, v, parameters, translator, allocators, relative_level)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level,\r
+ "unexpected level");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level,\r
+ "unexpected level");\r
+\r
+ // next traversing step\r
+ base::traverse(*this, n); // MAY THROW (V: alloc, copy, N: alloc)\r
+\r
+ base::recalculate_aabb_if_necessary(n);\r
+ }\r
+\r
+ inline void operator()(leaf & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,\r
+ "unexpected level");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||\r
+ base::m_level == (std::numeric_limits<size_t>::max)(),\r
+ "unexpected level");\r
+\r
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)\r
+\r
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (V: alloc, copy, N: alloc)\r
+ \r
+ base::recalculate_aabb_if_necessary(n);\r
+ }\r
+};\r
+\r
+} // namespace rstar\r
+\r
+// R*-tree insert visitor\r
+// After passing the Element to insert visitor the Element is managed by the tree\r
+// I.e. one should not delete the node passed to the insert visitor after exception is thrown\r
+// because this visitor may delete it\r
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class insert<Element, Value, Options, Translator, Box, Allocators, insert_reinsert_tag>\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type\r
+{\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+public:\r
+ inline insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Element const& element,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level = 0)\r
+ : m_root(root), m_leafs_level(leafs_level), m_element(element)\r
+ , m_parameters(parameters), m_translator(translator)\r
+ , m_relative_level(relative_level), m_allocators(allocators)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ boost::ignore_unused(n);\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");\r
+\r
+ // Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one\r
+ if ( m_parameters.get_reinserted_elements() > 0 )\r
+ {\r
+ rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(\r
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);\r
+\r
+ rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ if ( !lins_v.result_elements.empty() )\r
+ {\r
+ recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+ }\r
+ }\r
+ else\r
+ {\r
+ visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(\r
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);\r
+\r
+ rtree::apply_visitor(ins_v, *m_root); \r
+ }\r
+ }\r
+\r
+ inline void operator()(leaf & n)\r
+ {\r
+ boost::ignore_unused(n);\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");\r
+\r
+ // Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one\r
+ if ( m_parameters.get_reinserted_elements() > 0 )\r
+ {\r
+ rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(\r
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);\r
+\r
+ rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ // we're in the root, so root should be split and there should be no elements to reinsert\r
+ BOOST_GEOMETRY_INDEX_ASSERT(lins_v.result_elements.empty(), "unexpected state");\r
+ }\r
+ else\r
+ {\r
+ visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(\r
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);\r
+\r
+ rtree::apply_visitor(ins_v, *m_root); \r
+ }\r
+ }\r
+\r
+private:\r
+ template <typename Elements>\r
+ inline void recursive_reinsert(Elements & elements, size_t relative_level)\r
+ {\r
+ typedef typename Elements::value_type element_type;\r
+\r
+ // reinsert children starting from the minimum distance\r
+ typename Elements::reverse_iterator it = elements.rbegin();\r
+ for ( ; it != elements.rend() ; ++it)\r
+ {\r
+ rstar::level_insert<1, element_type, Value, Options, Translator, Box, Allocators> lins_v(\r
+ m_root, m_leafs_level, *it, m_parameters, m_translator, m_allocators, relative_level);\r
+\r
+ BOOST_TRY\r
+ {\r
+ rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ ++it;\r
+ for ( ; it != elements.rend() ; ++it)\r
+ rtree::destroy_element<Value, Options, Translator, Box, Allocators>::apply(*it, m_allocators);\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(relative_level + 1 == lins_v.result_relative_level, "unexpected level");\r
+\r
+ // non-root relative level\r
+ if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())\r
+ {\r
+ recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+ }\r
+ }\r
+ }\r
+\r
+ node_pointer & m_root;\r
+ size_type & m_leafs_level;\r
+ Element const& m_element;\r
+\r
+ parameters_type const& m_parameters;\r
+ Translator const& m_translator;\r
+\r
+ size_type m_relative_level;\r
+\r
+ Allocators & m_allocators;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree R*-tree split algorithm implementation\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP\r
+\r
+#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>\r
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>\r
+#include <boost/geometry/index/detail/algorithms/margin.hpp>\r
+\r
+#include <boost/geometry/index/detail/bounded_view.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+namespace rstar {\r
+\r
+template <typename Element, typename Translator, typename Tag, size_t Corner, size_t AxisIndex>\r
+class element_axis_corner_less\r
+{\r
+ typedef typename rtree::element_indexable_type<Element, Translator>::type indexable_type;\r
+ typedef typename geometry::point_type<indexable_type>::type point_type;\r
+ typedef geometry::model::box<point_type> bounds_type;\r
+ typedef index::detail::bounded_view<indexable_type, bounds_type> bounded_view_type;\r
+\r
+public:\r
+ element_axis_corner_less(Translator const& tr)\r
+ : m_tr(tr)\r
+ {}\r
+\r
+ bool operator()(Element const& e1, Element const& e2) const\r
+ {\r
+ bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr));\r
+ bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr));\r
+\r
+ return geometry::get<Corner, AxisIndex>(bounded_ind1)\r
+ < geometry::get<Corner, AxisIndex>(bounded_ind2);\r
+ }\r
+\r
+private:\r
+ Translator const& m_tr;\r
+};\r
+\r
+template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>\r
+class element_axis_corner_less<Element, Translator, box_tag, Corner, AxisIndex>\r
+{\r
+public:\r
+ element_axis_corner_less(Translator const& tr)\r
+ : m_tr(tr)\r
+ {}\r
+\r
+ bool operator()(Element const& e1, Element const& e2) const\r
+ {\r
+ return geometry::get<Corner, AxisIndex>(rtree::element_indexable(e1, m_tr))\r
+ < geometry::get<Corner, AxisIndex>(rtree::element_indexable(e2, m_tr));\r
+ }\r
+\r
+private:\r
+ Translator const& m_tr;\r
+};\r
+\r
+template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>\r
+class element_axis_corner_less<Element, Translator, point_tag, Corner, AxisIndex>\r
+{\r
+public:\r
+ element_axis_corner_less(Translator const& tr)\r
+ : m_tr(tr)\r
+ {}\r
+\r
+ bool operator()(Element const& e1, Element const& e2) const\r
+ {\r
+ return geometry::get<AxisIndex>(rtree::element_indexable(e1, m_tr))\r
+ < geometry::get<AxisIndex>(rtree::element_indexable(e2, m_tr));\r
+ }\r
+\r
+private:\r
+ Translator const& m_tr;\r
+};\r
+\r
+template <typename Box, size_t Corner, size_t AxisIndex>\r
+struct choose_split_axis_and_index_for_corner\r
+{\r
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Elements, typename Parameters, typename Translator>\r
+ static inline void apply(Elements const& elements,\r
+ size_t & choosen_index,\r
+ margin_type & sum_of_margins,\r
+ content_type & smallest_overlap,\r
+ content_type & smallest_content,\r
+ Parameters const& parameters,\r
+ Translator const& translator)\r
+ {\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef typename tag<indexable_type>::type indexable_tag;\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements");\r
+\r
+ // copy elements\r
+ Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)\r
+ \r
+ size_t const index_first = parameters.get_min_elements();\r
+ size_t const index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;\r
+\r
+ // sort elements\r
+ element_axis_corner_less<element_type, Translator, indexable_tag, Corner, AxisIndex> elements_less(translator);\r
+ std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)\r
+// {\r
+// typename Elements::iterator f = elements_copy.begin() + index_first;\r
+// typename Elements::iterator l = elements_copy.begin() + index_last;\r
+// std::nth_element(elements_copy.begin(), f, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)\r
+// std::nth_element(f, l, elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)\r
+// std::sort(f, l, elements_less); // MAY THROW, BASIC (copy)\r
+// }\r
+\r
+ // init outputs\r
+ choosen_index = index_first;\r
+ sum_of_margins = 0;\r
+ smallest_overlap = (std::numeric_limits<content_type>::max)();\r
+ smallest_content = (std::numeric_limits<content_type>::max)();\r
+\r
+ // calculate sum of margins for all distributions\r
+ for ( size_t i = index_first ; i < index_last ; ++i )\r
+ {\r
+ // TODO - awulkiew: may be optimized - box of group 1 may be initialized with\r
+ // box of min_elems number of elements and expanded for each iteration by another element\r
+\r
+ Box box1 = rtree::elements_box<Box>(elements_copy.begin(), elements_copy.begin() + i, translator);\r
+ Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(), translator);\r
+ \r
+ sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2);\r
+\r
+ content_type ovl = index::detail::intersection_content(box1, box2);\r
+ content_type con = index::detail::content(box1) + index::detail::content(box2);\r
+\r
+ // TODO - shouldn't here be < instead of <= ?\r
+ if ( ovl < smallest_overlap || (ovl == smallest_overlap && con <= smallest_content) )\r
+ {\r
+ choosen_index = i;\r
+ smallest_overlap = ovl;\r
+ smallest_content = con;\r
+ }\r
+ }\r
+\r
+ ::boost::ignore_unused_variable_warning(parameters);\r
+ }\r
+};\r
+\r
+//template <typename Box, size_t AxisIndex, typename ElementIndexableTag>\r
+//struct choose_split_axis_and_index_for_axis\r
+//{\r
+// BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (ElementIndexableTag));\r
+//};\r
+\r
+template <typename Box, size_t AxisIndex, typename ElementIndexableTag>\r
+struct choose_split_axis_and_index_for_axis\r
+{\r
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Elements, typename Parameters, typename Translator>\r
+ static inline void apply(Elements const& elements,\r
+ size_t & choosen_corner,\r
+ size_t & choosen_index,\r
+ margin_type & sum_of_margins,\r
+ content_type & smallest_overlap,\r
+ content_type & smallest_content,\r
+ Parameters const& parameters,\r
+ Translator const& translator)\r
+ {\r
+ size_t index1 = 0;\r
+ margin_type som1 = 0;\r
+ content_type ovl1 = (std::numeric_limits<content_type>::max)();\r
+ content_type con1 = (std::numeric_limits<content_type>::max)();\r
+\r
+ choose_split_axis_and_index_for_corner<Box, min_corner, AxisIndex>\r
+ ::apply(elements, index1,\r
+ som1, ovl1, con1,\r
+ parameters, translator); // MAY THROW, STRONG\r
+\r
+ size_t index2 = 0;\r
+ margin_type som2 = 0;\r
+ content_type ovl2 = (std::numeric_limits<content_type>::max)();\r
+ content_type con2 = (std::numeric_limits<content_type>::max)();\r
+\r
+ choose_split_axis_and_index_for_corner<Box, max_corner, AxisIndex>\r
+ ::apply(elements, index2,\r
+ som2, ovl2, con2,\r
+ parameters, translator); // MAY THROW, STRONG\r
+\r
+ sum_of_margins = som1 + som2;\r
+\r
+ if ( ovl1 < ovl2 || (ovl1 == ovl2 && con1 <= con2) )\r
+ {\r
+ choosen_corner = min_corner;\r
+ choosen_index = index1;\r
+ smallest_overlap = ovl1;\r
+ smallest_content = con1;\r
+ }\r
+ else\r
+ {\r
+ choosen_corner = max_corner;\r
+ choosen_index = index2;\r
+ smallest_overlap = ovl2;\r
+ smallest_content = con2;\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Box, size_t AxisIndex>\r
+struct choose_split_axis_and_index_for_axis<Box, AxisIndex, point_tag>\r
+{\r
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Elements, typename Parameters, typename Translator>\r
+ static inline void apply(Elements const& elements,\r
+ size_t & choosen_corner,\r
+ size_t & choosen_index,\r
+ margin_type & sum_of_margins,\r
+ content_type & smallest_overlap,\r
+ content_type & smallest_content,\r
+ Parameters const& parameters,\r
+ Translator const& translator)\r
+ {\r
+ choose_split_axis_and_index_for_corner<Box, min_corner, AxisIndex>\r
+ ::apply(elements, choosen_index,\r
+ sum_of_margins, smallest_overlap, smallest_content,\r
+ parameters, translator); // MAY THROW, STRONG\r
+\r
+ choosen_corner = min_corner;\r
+ }\r
+};\r
+\r
+template <typename Box, size_t Dimension>\r
+struct choose_split_axis_and_index\r
+{\r
+ BOOST_STATIC_ASSERT(0 < Dimension);\r
+\r
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Elements, typename Parameters, typename Translator>\r
+ static inline void apply(Elements const& elements,\r
+ size_t & choosen_axis,\r
+ size_t & choosen_corner,\r
+ size_t & choosen_index,\r
+ margin_type & smallest_sum_of_margins,\r
+ content_type & smallest_overlap,\r
+ content_type & smallest_content,\r
+ Parameters const& parameters,\r
+ Translator const& translator)\r
+ {\r
+ typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;\r
+\r
+ choose_split_axis_and_index<Box, Dimension - 1>\r
+ ::apply(elements, choosen_axis, choosen_corner, choosen_index,\r
+ smallest_sum_of_margins, smallest_overlap, smallest_content,\r
+ parameters, translator); // MAY THROW, STRONG\r
+\r
+ margin_type sum_of_margins = 0;\r
+\r
+ size_t corner = min_corner;\r
+ size_t index = 0;\r
+\r
+ content_type overlap_val = (std::numeric_limits<content_type>::max)();\r
+ content_type content_val = (std::numeric_limits<content_type>::max)();\r
+\r
+ choose_split_axis_and_index_for_axis<\r
+ Box,\r
+ Dimension - 1,\r
+ typename tag<element_indexable_type>::type\r
+ >::apply(elements, corner, index, sum_of_margins, overlap_val, content_val, parameters, translator); // MAY THROW, STRONG\r
+\r
+ if ( sum_of_margins < smallest_sum_of_margins )\r
+ {\r
+ choosen_axis = Dimension - 1;\r
+ choosen_corner = corner;\r
+ choosen_index = index;\r
+ smallest_sum_of_margins = sum_of_margins;\r
+ smallest_overlap = overlap_val;\r
+ smallest_content = content_val;\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct choose_split_axis_and_index<Box, 1>\r
+{\r
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Elements, typename Parameters, typename Translator>\r
+ static inline void apply(Elements const& elements,\r
+ size_t & choosen_axis,\r
+ size_t & choosen_corner,\r
+ size_t & choosen_index,\r
+ margin_type & smallest_sum_of_margins,\r
+ content_type & smallest_overlap,\r
+ content_type & smallest_content,\r
+ Parameters const& parameters,\r
+ Translator const& translator)\r
+ {\r
+ typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;\r
+\r
+ choosen_axis = 0;\r
+\r
+ choose_split_axis_and_index_for_axis<\r
+ Box,\r
+ 0,\r
+ typename tag<element_indexable_type>::type\r
+ >::apply(elements, choosen_corner, choosen_index, smallest_sum_of_margins, smallest_overlap, smallest_content, parameters, translator); // MAY THROW\r
+ }\r
+};\r
+\r
+template <size_t Corner, size_t Dimension, size_t I = 0>\r
+struct nth_element\r
+{\r
+ BOOST_STATIC_ASSERT(0 < Dimension);\r
+ BOOST_STATIC_ASSERT(I < Dimension);\r
+\r
+ template <typename Elements, typename Translator>\r
+ static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr)\r
+ {\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(axis < Dimension, "unexpected axis value");\r
+\r
+ if ( axis != I )\r
+ {\r
+ nth_element<Corner, Dimension, I + 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)\r
+ }\r
+ else\r
+ {\r
+ typedef typename Elements::value_type element_type;\r
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;\r
+ typedef typename tag<indexable_type>::type indexable_tag;\r
+\r
+ element_axis_corner_less<element_type, Translator, indexable_tag, Corner, I> less(tr);\r
+ std::nth_element(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)\r
+ }\r
+ }\r
+};\r
+\r
+template <size_t Corner, size_t Dimension>\r
+struct nth_element<Corner, Dimension, Dimension>\r
+{\r
+ template <typename Elements, typename Translator>\r
+ static inline void apply(Elements & /*elements*/, const size_t /*axis*/, const size_t /*index*/, Translator const& /*tr*/)\r
+ {}\r
+};\r
+\r
+} // namespace rstar\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct redistribute_elements<Value, Options, Translator, Box, Allocators, rstar_tag>\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ static const size_t dimension = geometry::dimension<Box>::value;\r
+\r
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Node>\r
+ static inline void apply(\r
+ Node & n,\r
+ Node & second_node,\r
+ Box & box1,\r
+ Box & box2,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators)\r
+ {\r
+ typedef typename rtree::elements_type<Node>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ \r
+ elements_type & elements1 = rtree::elements(n);\r
+ elements_type & elements2 = rtree::elements(second_node);\r
+\r
+ // copy original elements - use in-memory storage (std::allocator)\r
+ // TODO: move if noexcept\r
+ typedef typename rtree::container_from_elements_type<elements_type, element_type>::type\r
+ container_type;\r
+ container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG\r
+ container_type elements_backup(elements1.begin(), elements1.end()); // MAY THROW, STRONG\r
+\r
+ size_t split_axis = 0;\r
+ size_t split_corner = 0;\r
+ size_t split_index = parameters.get_min_elements();\r
+ margin_type smallest_sum_of_margins = (std::numeric_limits<margin_type>::max)();\r
+ content_type smallest_overlap = (std::numeric_limits<content_type>::max)();\r
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();\r
+\r
+ // NOTE: this function internally copies passed elements\r
+ // why not pass mutable elements and use the same container for all axes/corners\r
+ // and again, the same below calling partial_sort/nth_element\r
+ // It would be even possible to not re-sort/find nth_element if the axis/corner\r
+ // was found for the last sorting - last combination of axis/corner\r
+ rstar::choose_split_axis_and_index<Box, dimension>\r
+ ::apply(elements_copy,\r
+ split_axis, split_corner, split_index,\r
+ smallest_sum_of_margins, smallest_overlap, smallest_content,\r
+ parameters, translator); // MAY THROW, STRONG\r
+\r
+ // TODO: awulkiew - get rid of following static_casts?\r
+ BOOST_GEOMETRY_INDEX_ASSERT(split_axis < dimension, "unexpected value");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(split_corner == static_cast<size_t>(min_corner) || split_corner == static_cast<size_t>(max_corner), "unexpected value");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= split_index && split_index <= parameters.get_max_elements() - parameters.get_min_elements() + 1, "unexpected value");\r
+\r
+ // TODO: consider using nth_element\r
+ if ( split_corner == static_cast<size_t>(min_corner) )\r
+ {\r
+ rstar::nth_element<min_corner, dimension>\r
+ ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)\r
+ }\r
+ else\r
+ {\r
+ rstar::nth_element<max_corner, dimension>\r
+ ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)\r
+ }\r
+\r
+ BOOST_TRY\r
+ {\r
+ // copy elements to nodes\r
+ elements1.assign(elements_copy.begin(), elements_copy.begin() + split_index); // MAY THROW, BASIC\r
+ elements2.assign(elements_copy.begin() + split_index, elements_copy.end()); // MAY THROW, BASIC\r
+\r
+ // calculate boxes\r
+ box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(), translator);\r
+ box2 = rtree::elements_box<Box>(elements2.begin(), elements2.end(), translator);\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ //elements_copy.clear();\r
+ elements1.clear();\r
+ elements2.clear();\r
+\r
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);\r
+ //elements_backup.clear();\r
+\r
+ BOOST_RETHROW // RETHROW, BASIC\r
+ }\r
+ BOOST_CATCH_END\r
+ }\r
+};\r
+\r
+}} // namespace detail::rtree\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree R*-tree algorithm implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/rstar/insert.hpp>\r
+#include <boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp>\r
+#include <boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree boxes validating visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {\r
+\r
+namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class are_boxes_ok\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+public:\r
+ are_boxes_ok(Translator const& tr, bool exact_match)\r
+ : result(false), m_tr(tr), m_is_root(true), m_exact_match(exact_match)\r
+ {}\r
+\r
+ void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ if (elements.empty())\r
+ {\r
+ result = false;\r
+ return;\r
+ }\r
+\r
+ Box box_bckup = m_box;\r
+ bool is_root_bckup = m_is_root;\r
+\r
+ m_is_root = false;\r
+\r
+ for ( typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end() ; ++it)\r
+ {\r
+ m_box = it->first;\r
+\r
+ rtree::apply_visitor(*this, *it->second);\r
+\r
+ if ( result == false )\r
+ return;\r
+ }\r
+\r
+ m_box = box_bckup;\r
+ m_is_root = is_root_bckup;\r
+\r
+ Box box_exp = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);\r
+ \r
+ if ( m_exact_match )\r
+ result = m_is_root || geometry::equals(box_exp, m_box);\r
+ else\r
+ result = m_is_root || geometry::covered_by(box_exp, m_box);\r
+ }\r
+\r
+ void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // non-root node\r
+ if (!m_is_root)\r
+ {\r
+ if ( elements.empty() )\r
+ {\r
+ result = false;\r
+ return;\r
+ }\r
+ \r
+ Box box_exp = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr);\r
+\r
+ if ( m_exact_match )\r
+ result = geometry::equals(box_exp, m_box);\r
+ else\r
+ result = geometry::covered_by(box_exp, m_box);\r
+ }\r
+ else\r
+ result = true;\r
+ }\r
+\r
+ bool result;\r
+\r
+private:\r
+ Translator const& m_tr;\r
+ Box m_box;\r
+ bool m_is_root;\r
+ bool m_exact_match;\r
+};\r
+\r
+} // namespace visitors\r
+\r
+template <typename Rtree> inline\r
+bool are_boxes_ok(Rtree const& tree, bool exact_match = true)\r
+{\r
+ typedef utilities::view<Rtree> RTV;\r
+ RTV rtv(tree);\r
+\r
+ visitors::are_boxes_ok<\r
+ typename RTV::value_type,\r
+ typename RTV::options_type,\r
+ typename RTV::translator_type,\r
+ typename RTV::box_type,\r
+ typename RTV::allocators_type\r
+ > v(rtv.translator(), exact_match);\r
+ \r
+ rtv.apply_visitor(v);\r
+\r
+ return v.result;\r
+}\r
+\r
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree nodes elements numbers validating visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {\r
+\r
+namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+class are_counts_ok\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+public:\r
+ inline are_counts_ok(parameters_type const& parameters)\r
+ : result(true), m_current_level(0), m_parameters(parameters)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // root internal node shouldn't contain 0 elements\r
+ if ( elements.empty()\r
+ || !check_count(elements) )\r
+ {\r
+ result = false;\r
+ return;\r
+ }\r
+\r
+ size_t current_level_backup = m_current_level;\r
+ ++m_current_level;\r
+\r
+ for ( typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end() && result == true ;\r
+ ++it)\r
+ {\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+\r
+ m_current_level = current_level_backup;\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // empty leaf in non-root node\r
+ if ( ( m_current_level > 0 && elements.empty() )\r
+ || !check_count(elements) )\r
+ {\r
+ result = false;\r
+ }\r
+ }\r
+\r
+ bool result;\r
+\r
+private:\r
+ template <typename Elements>\r
+ bool check_count(Elements const& elements)\r
+ {\r
+ // root may contain count < min but should never contain count > max\r
+ return elements.size() <= m_parameters.get_max_elements()\r
+ && ( elements.size() >= m_parameters.get_min_elements()\r
+ || m_current_level == 0 );\r
+ }\r
+\r
+ size_t m_current_level;\r
+ parameters_type const& m_parameters;\r
+};\r
+\r
+} // namespace visitors\r
+\r
+template <typename Rtree> inline\r
+bool are_counts_ok(Rtree const& tree)\r
+{\r
+ typedef utilities::view<Rtree> RTV;\r
+ RTV rtv(tree);\r
+\r
+ visitors::are_counts_ok<\r
+ typename RTV::value_type,\r
+ typename RTV::options_type,\r
+ typename RTV::box_type,\r
+ typename RTV::allocators_type\r
+ > v(tree.parameters());\r
+ \r
+ rtv.apply_visitor(v);\r
+\r
+ return v.result;\r
+}\r
+\r
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree levels validating visitor implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {\r
+\r
+namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+class are_levels_ok\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+public:\r
+ inline are_levels_ok()\r
+ : result(true), m_leafs_level((std::numeric_limits<size_t>::max)()), m_current_level(0)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ if (elements.empty())\r
+ {\r
+ result = false;\r
+ return;\r
+ }\r
+\r
+ size_t current_level_backup = m_current_level;\r
+ ++m_current_level;\r
+\r
+ for ( typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end() ; ++it)\r
+ {\r
+ rtree::apply_visitor(*this, *it->second);\r
+\r
+ if ( result == false )\r
+ return;\r
+ }\r
+\r
+ m_current_level = current_level_backup;\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // empty leaf in non-root node\r
+ if (0 < m_current_level && elements.empty())\r
+ {\r
+ result = false;\r
+ return;\r
+ }\r
+\r
+ if ( m_leafs_level == (std::numeric_limits<size_t>::max)() )\r
+ {\r
+ m_leafs_level = m_current_level;\r
+ }\r
+ else if ( m_leafs_level != m_current_level )\r
+ {\r
+ result = false;\r
+ }\r
+ }\r
+\r
+ bool result;\r
+\r
+private:\r
+ size_t m_leafs_level;\r
+ size_t m_current_level;\r
+};\r
+\r
+} // namespace visitors\r
+\r
+template <typename Rtree> inline\r
+bool are_levels_ok(Rtree const& tree)\r
+{\r
+ typedef utilities::view<Rtree> RTV;\r
+ RTV rtv(tree);\r
+\r
+ visitors::are_levels_ok<\r
+ typename RTV::value_type,\r
+ typename RTV::options_type,\r
+ typename RTV::box_type,\r
+ typename RTV::allocators_type\r
+ > v;\r
+ \r
+ rtv.apply_visitor(v);\r
+\r
+ return v.result;\r
+}\r
+\r
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree OpenGL drawing visitor implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+namespace utilities {\r
+\r
+namespace dispatch {\r
+\r
+template <typename Point, size_t Dimension>\r
+struct gl_draw_point\r
+{};\r
+\r
+template <typename Point>\r
+struct gl_draw_point<Point, 2>\r
+{\r
+ static inline void apply(Point const& p, typename coordinate_type<Point>::type z)\r
+ {\r
+ typename coordinate_type<Point>::type const& x = geometry::get<0>(p);\r
+ typename coordinate_type<Point>::type const& y = geometry::get<1>(p);\r
+ /*glBegin(GL_POINT);\r
+ glVertex3f(x, y, z);\r
+ glEnd();*/\r
+ glBegin(GL_QUADS);\r
+ glVertex3f(x+1, y, z);\r
+ glVertex3f(x, y+1, z);\r
+ glVertex3f(x-1, y, z);\r
+ glVertex3f(x, y-1, z);\r
+ glEnd();\r
+ }\r
+};\r
+\r
+template <typename Box, size_t Dimension>\r
+struct gl_draw_box\r
+{};\r
+\r
+template <typename Box>\r
+struct gl_draw_box<Box, 2>\r
+{\r
+ static inline void apply(Box const& b, typename coordinate_type<Box>::type z)\r
+ {\r
+ glBegin(GL_LINE_LOOP);\r
+ glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<min_corner, 1>(b), z);\r
+ glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<min_corner, 1>(b), z);\r
+ glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<max_corner, 1>(b), z);\r
+ glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<max_corner, 1>(b), z);\r
+ glEnd();\r
+ }\r
+};\r
+\r
+template <typename Segment, size_t Dimension>\r
+struct gl_draw_segment\r
+{};\r
+\r
+template <typename Segment>\r
+struct gl_draw_segment<Segment, 2>\r
+{\r
+ static inline void apply(Segment const& s, typename coordinate_type<Segment>::type z)\r
+ {\r
+ glBegin(GL_LINES);\r
+ glVertex3f(geometry::get<0, 0>(s), geometry::get<0, 1>(s), z);\r
+ glVertex3f(geometry::get<1, 0>(s), geometry::get<1, 1>(s), z);\r
+ glEnd();\r
+ }\r
+};\r
+\r
+template <typename Indexable, typename Tag>\r
+struct gl_draw_indexable\r
+{\r
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));\r
+};\r
+\r
+template <typename Box>\r
+struct gl_draw_indexable<Box, box_tag>\r
+ : gl_draw_box<Box, geometry::dimension<Box>::value>\r
+{};\r
+\r
+template <typename Point>\r
+struct gl_draw_indexable<Point, point_tag>\r
+ : gl_draw_point<Point, geometry::dimension<Point>::value>\r
+{};\r
+\r
+template <typename Segment>\r
+struct gl_draw_indexable<Segment, segment_tag>\r
+ : gl_draw_segment<Segment, geometry::dimension<Segment>::value>\r
+{};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Indexable> inline\r
+void gl_draw_indexable(Indexable const& i, typename coordinate_type<Indexable>::type z)\r
+{\r
+ dispatch::gl_draw_indexable<\r
+ Indexable,\r
+ typename tag<Indexable>::type\r
+ >::apply(i, z);\r
+}\r
+\r
+} // namespace utilities\r
+\r
+namespace rtree { namespace utilities {\r
+\r
+namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct gl_draw : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ inline gl_draw(Translator const& t,\r
+ size_t level_first = 0,\r
+ size_t level_last = (std::numeric_limits<size_t>::max)(),\r
+ typename coordinate_type<Box>::type z_coord_level_multiplier = 1\r
+ )\r
+ : tr(t)\r
+ , level_f(level_first)\r
+ , level_l(level_last)\r
+ , z_mul(z_coord_level_multiplier)\r
+ , level(0)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ if ( level_f <= level )\r
+ {\r
+ size_t level_rel = level - level_f;\r
+\r
+ if ( level_rel == 0 )\r
+ glColor3f(0.75f, 0.0f, 0.0f);\r
+ else if ( level_rel == 1 )\r
+ glColor3f(0.0f, 0.75f, 0.0f);\r
+ else if ( level_rel == 2 )\r
+ glColor3f(0.0f, 0.0f, 0.75f);\r
+ else if ( level_rel == 3 )\r
+ glColor3f(0.75f, 0.75f, 0.0f);\r
+ else if ( level_rel == 4 )\r
+ glColor3f(0.75f, 0.0f, 0.75f);\r
+ else if ( level_rel == 5 )\r
+ glColor3f(0.0f, 0.75f, 0.75f);\r
+ else\r
+ glColor3f(0.5f, 0.5f, 0.5f);\r
+\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ detail::utilities::gl_draw_indexable(it->first, level_rel * z_mul);\r
+ }\r
+ }\r
+ \r
+ size_t level_backup = level;\r
+ ++level;\r
+\r
+ if ( level < level_l )\r
+ {\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+ }\r
+\r
+ level = level_backup;\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ if ( level_f <= level )\r
+ {\r
+ size_t level_rel = level - level_f;\r
+\r
+ glColor3f(0.25f, 0.25f, 0.25f);\r
+\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ detail::utilities::gl_draw_indexable(tr(*it), level_rel * z_mul);\r
+ }\r
+ }\r
+ }\r
+\r
+ Translator const& tr;\r
+ size_t level_f;\r
+ size_t level_l;\r
+ typename coordinate_type<Box>::type z_mul;\r
+\r
+ size_t level;\r
+};\r
+\r
+} // namespace visitors\r
+\r
+template <typename Rtree> inline\r
+void gl_draw(Rtree const& tree,\r
+ size_t level_first = 0,\r
+ size_t level_last = (std::numeric_limits<size_t>::max)(),\r
+ typename coordinate_type<\r
+ typename Rtree::bounds_type\r
+ >::type z_coord_level_multiplier = 1\r
+ )\r
+{\r
+ typedef utilities::view<Rtree> RTV;\r
+ RTV rtv(tree);\r
+\r
+ if ( !tree.empty() )\r
+ {\r
+ glColor3f(0.75f, 0.75f, 0.75f);\r
+ detail::utilities::gl_draw_indexable(tree.bounds(), 0);\r
+ }\r
+\r
+ visitors::gl_draw<\r
+ typename RTV::value_type,\r
+ typename RTV::options_type,\r
+ typename RTV::translator_type,\r
+ typename RTV::box_type,\r
+ typename RTV::allocators_type\r
+ > gl_draw_v(rtv.translator(), level_first, level_last, z_coord_level_multiplier);\r
+\r
+ rtv.apply_visitor(gl_draw_v);\r
+}\r
+\r
+}} // namespace rtree::utilities\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree ostreaming visitor implementation\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP\r
+\r
+#include <iostream>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+ \r
+namespace utilities {\r
+\r
+namespace dispatch {\r
+\r
+template <typename Point, size_t Dimension>\r
+struct print_point\r
+{\r
+ BOOST_STATIC_ASSERT(0 < Dimension);\r
+\r
+ static inline void apply(std::ostream & os, Point const& p)\r
+ {\r
+ print_point<Point, Dimension - 1>::apply(os, p);\r
+\r
+ os << ", " << geometry::get<Dimension - 1>(p);\r
+ }\r
+};\r
+\r
+template <typename Point>\r
+struct print_point<Point, 1>\r
+{\r
+ static inline void apply(std::ostream & os, Point const& p)\r
+ {\r
+ os << geometry::get<0>(p);\r
+ }\r
+};\r
+\r
+template <typename Box, size_t Corner, size_t Dimension>\r
+struct print_corner\r
+{\r
+ BOOST_STATIC_ASSERT(0 < Dimension);\r
+\r
+ static inline void apply(std::ostream & os, Box const& b)\r
+ {\r
+ print_corner<Box, Corner, Dimension - 1>::apply(os, b);\r
+\r
+ os << ", " << geometry::get<Corner, Dimension - 1>(b);\r
+ }\r
+};\r
+\r
+template <typename Box, size_t Corner>\r
+struct print_corner<Box, Corner, 1>\r
+{\r
+ static inline void apply(std::ostream & os, Box const& b)\r
+ {\r
+ os << geometry::get<Corner, 0>(b);\r
+ }\r
+};\r
+\r
+template <typename Indexable, typename Tag>\r
+struct print_indexable\r
+{\r
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));\r
+};\r
+\r
+template <typename Indexable>\r
+struct print_indexable<Indexable, box_tag>\r
+{\r
+ static const size_t dimension = geometry::dimension<Indexable>::value;\r
+\r
+ static inline void apply(std::ostream &os, Indexable const& i)\r
+ {\r
+ os << '(';\r
+ print_corner<Indexable, min_corner, dimension>::apply(os, i);\r
+ os << ")x(";\r
+ print_corner<Indexable, max_corner, dimension>::apply(os, i);\r
+ os << ')';\r
+ }\r
+};\r
+\r
+template <typename Indexable>\r
+struct print_indexable<Indexable, point_tag>\r
+{\r
+ static const size_t dimension = geometry::dimension<Indexable>::value;\r
+\r
+ static inline void apply(std::ostream &os, Indexable const& i)\r
+ {\r
+ os << '(';\r
+ print_point<Indexable, dimension>::apply(os, i);\r
+ os << ')';\r
+ }\r
+};\r
+\r
+template <typename Indexable>\r
+struct print_indexable<Indexable, segment_tag>\r
+{\r
+ static const size_t dimension = geometry::dimension<Indexable>::value;\r
+\r
+ static inline void apply(std::ostream &os, Indexable const& i)\r
+ {\r
+ os << '(';\r
+ print_corner<Indexable, 0, dimension>::apply(os, i);\r
+ os << ")-(";\r
+ print_corner<Indexable, 1, dimension>::apply(os, i);\r
+ os << ')';\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+\r
+template <typename Indexable> inline\r
+void print_indexable(std::ostream & os, Indexable const& i)\r
+{\r
+ dispatch::print_indexable<\r
+ Indexable,\r
+ typename tag<Indexable>::type\r
+ >::apply(os, i);\r
+}\r
+\r
+} // namespace utilities\r
+\r
+namespace rtree { namespace utilities {\r
+\r
+namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct print : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ inline print(std::ostream & o, Translator const& t)\r
+ : os(o), tr(t), level(0)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ spaces(level) << "INTERNAL NODE - L:" << level << " Ch:" << elements.size() << " @:" << &n << '\n';\r
+ \r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ spaces(level);\r
+ detail::utilities::print_indexable(os, it->first);\r
+ os << " ->" << it->second << '\n';\r
+ }\r
+\r
+ size_t level_backup = level;\r
+ ++level;\r
+\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+\r
+ level = level_backup;\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ spaces(level) << "LEAF - L:" << level << " V:" << elements.size() << " @:" << &n << '\n';\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ spaces(level);\r
+ detail::utilities::print_indexable(os, tr(*it));\r
+ os << '\n';\r
+ }\r
+ }\r
+\r
+ inline std::ostream & spaces(size_t level)\r
+ {\r
+ for ( size_t i = 0 ; i < 2 * level ; ++i )\r
+ os << ' ';\r
+ return os;\r
+ }\r
+\r
+ std::ostream & os;\r
+ Translator const& tr;\r
+\r
+ size_t level;\r
+};\r
+\r
+} // namespace visitors\r
+\r
+template <typename Rtree> inline\r
+void print(std::ostream & os, Rtree const& tree)\r
+{\r
+ typedef utilities::view<Rtree> RTV;\r
+ RTV rtv(tree);\r
+\r
+ visitors::print<\r
+ typename RTV::value_type,\r
+ typename RTV::options_type,\r
+ typename RTV::translator_type,\r
+ typename RTV::box_type,\r
+ typename RTV::allocators_type\r
+ > print_v(os, rtv.translator());\r
+ rtv.apply_visitor(print_v);\r
+}\r
+\r
+}} // namespace rtree::utilities\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree visitor collecting basic statistics\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+// Copyright (c) 2013 Mateusz Loskot, London, UK.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP\r
+\r
+#include <algorithm>\r
+#include <boost/tuple/tuple.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {\r
+\r
+namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+struct statistics : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ inline statistics()\r
+ : level(0)\r
+ , levels(1) // count root\r
+ , nodes(0)\r
+ , leaves(0)\r
+ , values(0)\r
+ , values_min(0)\r
+ , values_max(0)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+ \r
+ ++nodes; // count node\r
+\r
+ size_t const level_backup = level;\r
+ ++level;\r
+\r
+ levels += level++ > levels ? 1 : 0; // count level (root already counted)\r
+ \r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+ \r
+ level = level_backup;\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ { \r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ ++leaves; // count leaves\r
+ \r
+ std::size_t const v = elements.size();\r
+ // count values spread per node and total\r
+ values_min = (std::min)(values_min == 0 ? v : values_min, v);\r
+ values_max = (std::max)(values_max, v);\r
+ values += v;\r
+ }\r
+ \r
+ std::size_t level;\r
+ std::size_t levels;\r
+ std::size_t nodes;\r
+ std::size_t leaves;\r
+ std::size_t values;\r
+ std::size_t values_min;\r
+ std::size_t values_max;\r
+};\r
+\r
+} // namespace visitors\r
+\r
+template <typename Rtree> inline\r
+boost::tuple<std::size_t, std::size_t, std::size_t, std::size_t, std::size_t, std::size_t>\r
+statistics(Rtree const& tree)\r
+{\r
+ typedef utilities::view<Rtree> RTV;\r
+ RTV rtv(tree);\r
+\r
+ visitors::statistics<\r
+ typename RTV::value_type,\r
+ typename RTV::options_type,\r
+ typename RTV::box_type,\r
+ typename RTV::allocators_type\r
+ > stats_v;\r
+\r
+ rtv.apply_visitor(stats_v);\r
+ \r
+ return boost::make_tuple(stats_v.levels, stats_v.nodes, stats_v.leaves, stats_v.values, stats_v.values_min, stats_v.values_max);\r
+}\r
+\r
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Rtree utilities view\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace utilities {\r
+\r
+template <typename Rtree>\r
+class view\r
+{\r
+public:\r
+ typedef typename Rtree::size_type size_type;\r
+\r
+ typedef typename Rtree::translator_type translator_type;\r
+ typedef typename Rtree::value_type value_type;\r
+ typedef typename Rtree::options_type options_type;\r
+ typedef typename Rtree::box_type box_type;\r
+ typedef typename Rtree::allocators_type allocators_type; \r
+\r
+ view(Rtree const& rt) : m_rtree(rt) {}\r
+\r
+ template <typename Visitor>\r
+ void apply_visitor(Visitor & vis) const\r
+ {\r
+ m_rtree.apply_visitor(vis);\r
+ }\r
+\r
+ // This will most certainly be removed in the future\r
+ translator_type translator() const\r
+ {\r
+ return m_rtree.translator();\r
+ }\r
+\r
+ // This will probably be removed in the future\r
+ size_type depth() const\r
+ {\r
+ return m_rtree.depth();\r
+ }\r
+\r
+private:\r
+ view(view const&);\r
+ view & operator=(view const&);\r
+\r
+ Rtree const& m_rtree;\r
+};\r
+\r
+}}} // namespace detail::rtree::utilities\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree node children box calculating visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class children_box\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+public:\r
+ inline children_box(Box & result, Translator const& tr)\r
+ : m_result(result), m_tr(tr)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ m_result = rtree::values_box<Box>(elements.begin(), elements.end(), m_tr);\r
+ }\r
+\r
+private:\r
+ Box & m_result;\r
+ Translator const& m_tr;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree deep copying visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class copy\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type\r
+{\r
+public:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+\r
+ explicit inline copy(Allocators & allocators)\r
+ : result(0)\r
+ , m_allocators(allocators)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ node_pointer raw_new_node = rtree::create_node<Allocators, internal_node>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)\r
+ subtree_destroyer new_node(raw_new_node, m_allocators);\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type & elements = rtree::elements(n);\r
+\r
+ elements_type & elements_dst = rtree::elements(rtree::get<internal_node>(*new_node));\r
+\r
+ for (typename elements_type::iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ rtree::apply_visitor(*this, *it->second); // MAY THROW (V, E: alloc, copy, N: alloc) \r
+\r
+ // for exception safety\r
+ subtree_destroyer auto_result(result, m_allocators);\r
+\r
+ elements_dst.push_back( rtree::make_ptr_pair(it->first, result) ); // MAY THROW, STRONG (E: alloc, copy)\r
+\r
+ auto_result.release();\r
+ }\r
+\r
+ result = new_node.get();\r
+ new_node.release();\r
+ }\r
+\r
+ inline void operator()(leaf & l)\r
+ {\r
+ node_pointer raw_new_node = rtree::create_node<Allocators, leaf>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)\r
+ subtree_destroyer new_node(raw_new_node, m_allocators);\r
+\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type & elements = rtree::elements(l);\r
+\r
+ elements_type & elements_dst = rtree::elements(rtree::get<leaf>(*new_node));\r
+\r
+ for (typename elements_type::iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ elements_dst.push_back(*it); // MAY THROW, STRONG (V: alloc, copy)\r
+ }\r
+\r
+ result = new_node.get();\r
+ new_node.release();\r
+ }\r
+\r
+ node_pointer result;\r
+\r
+private:\r
+ Allocators & m_allocators;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree count visitor implementation\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Indexable, typename Value>\r
+struct count_helper\r
+{\r
+ template <typename Translator>\r
+ static inline typename Translator::result_type indexable(Indexable const& i, Translator const&)\r
+ {\r
+ return i;\r
+ }\r
+ template <typename Translator>\r
+ static inline bool equals(Indexable const& i, Value const& v, Translator const& tr)\r
+ {\r
+ return geometry::equals(i, tr(v));\r
+ }\r
+};\r
+\r
+template <typename Value>\r
+struct count_helper<Value, Value>\r
+{\r
+ template <typename Translator>\r
+ static inline typename Translator::result_type indexable(Value const& v, Translator const& tr)\r
+ {\r
+ return tr(v);\r
+ }\r
+ template <typename Translator>\r
+ static inline bool equals(Value const& v1, Value const& v2, Translator const& tr)\r
+ {\r
+ return tr.equals(v1, v2);\r
+ }\r
+};\r
+\r
+template <typename ValueOrIndexable, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+struct count\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef count_helper<ValueOrIndexable, Value> count_help;\r
+\r
+ inline count(ValueOrIndexable const& vori, Translator const& t)\r
+ : value_or_indexable(vori), tr(t), found_count(0)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // traverse nodes meeting predicates\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ if ( geometry::covered_by(\r
+ return_ref_or_bounds(\r
+ count_help::indexable(value_or_indexable, tr)),\r
+ it->first) )\r
+ {\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // get all values meeting predicates\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ // if value meets predicates\r
+ if ( count_help::equals(value_or_indexable, *it, tr) )\r
+ {\r
+ ++found_count;\r
+ }\r
+ }\r
+ }\r
+\r
+ ValueOrIndexable const& value_or_indexable;\r
+ Translator const& tr;\r
+ typename Allocators::size_type found_count;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree destroying visitor implementation\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class destroy\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type\r
+{\r
+public:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+\r
+ inline destroy(node_pointer root_node, Allocators & allocators)\r
+ : m_current_node(root_node)\r
+ , m_allocators(allocators)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_current_node), "invalid pointers");\r
+\r
+ node_pointer node_to_destroy = m_current_node;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type & elements = rtree::elements(n);\r
+\r
+ for (typename elements_type::iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ m_current_node = it->second;\r
+ rtree::apply_visitor(*this, *m_current_node);\r
+ it->second = 0;\r
+ }\r
+\r
+ rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, node_to_destroy);\r
+ }\r
+\r
+ inline void operator()(leaf & l)\r
+ {\r
+ boost::ignore_unused(l);\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&l == &rtree::get<leaf>(*m_current_node), "invalid pointers");\r
+\r
+ rtree::destroy_node<Allocators, leaf>::apply(m_allocators, m_current_node);\r
+ }\r
+\r
+private:\r
+ node_pointer m_current_node;\r
+ Allocators & m_allocators;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree distance (knn, path, etc. ) query visitor implementation\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Translator, typename DistanceType, typename OutIt>\r
+class distance_query_result\r
+{\r
+public:\r
+ typedef DistanceType distance_type;\r
+\r
+ inline explicit distance_query_result(size_t k, OutIt out_it)\r
+ : m_count(k), m_out_it(out_it)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");\r
+\r
+ m_neighbors.reserve(m_count);\r
+ }\r
+\r
+ inline void store(Value const& val, distance_type const& curr_comp_dist)\r
+ {\r
+ if ( m_neighbors.size() < m_count )\r
+ {\r
+ m_neighbors.push_back(std::make_pair(curr_comp_dist, val));\r
+\r
+ if ( m_neighbors.size() == m_count )\r
+ std::make_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);\r
+ }\r
+ else\r
+ {\r
+ if ( curr_comp_dist < m_neighbors.front().first )\r
+ {\r
+ std::pop_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);\r
+ m_neighbors.back().first = curr_comp_dist;\r
+ m_neighbors.back().second = val;\r
+ std::push_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);\r
+ }\r
+ }\r
+ }\r
+\r
+ inline bool has_enough_neighbors() const\r
+ {\r
+ return m_count <= m_neighbors.size();\r
+ }\r
+\r
+ inline distance_type greatest_comparable_distance() const\r
+ {\r
+ // greatest distance is in the first neighbor only\r
+ // if there is at least m_count values found\r
+ // this is just for safety reasons since is_comparable_distance_valid() is checked earlier\r
+ // TODO - may be replaced by ASSERT\r
+ return m_neighbors.size() < m_count\r
+ ? (std::numeric_limits<distance_type>::max)()\r
+ : m_neighbors.front().first;\r
+ }\r
+\r
+ inline size_t finish()\r
+ {\r
+ typedef typename std::vector< std::pair<distance_type, Value> >::const_iterator neighbors_iterator;\r
+ for ( neighbors_iterator it = m_neighbors.begin() ; it != m_neighbors.end() ; ++it, ++m_out_it )\r
+ *m_out_it = it->second;\r
+\r
+ return m_neighbors.size();\r
+ }\r
+\r
+private:\r
+ inline static bool neighbors_less(\r
+ std::pair<distance_type, Value> const& p1,\r
+ std::pair<distance_type, Value> const& p2)\r
+ {\r
+ return p1.first < p2.first;\r
+ }\r
+\r
+ size_t m_count;\r
+ OutIt m_out_it;\r
+\r
+ std::vector< std::pair<distance_type, Value> > m_neighbors;\r
+};\r
+\r
+template <\r
+ typename Value,\r
+ typename Options,\r
+ typename Translator,\r
+ typename Box,\r
+ typename Allocators,\r
+ typename Predicates,\r
+ unsigned DistancePredicateIndex,\r
+ typename OutIter\r
+>\r
+class distance_query\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+public:\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;\r
+ typedef typename nearest_predicate_access::type nearest_predicate_type;\r
+ typedef typename indexable_type<Translator>::type indexable_type;\r
+\r
+ typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;\r
+ typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;\r
+ typedef typename calculate_value_distance::result_type value_distance_type;\r
+ typedef typename calculate_node_distance::result_type node_distance_type;\r
+\r
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;\r
+\r
+ inline distance_query(parameters_type const& parameters, Translator const& translator, Predicates const& pred, OutIter out_it)\r
+ : m_parameters(parameters), m_translator(translator)\r
+ , m_pred(pred)\r
+ , m_result(nearest_predicate_access::get(m_pred).count, out_it)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+\r
+ // array of active nodes\r
+ typedef typename index::detail::rtree::container_from_elements_type<\r
+ elements_type,\r
+ std::pair<node_distance_type, typename Allocators::node_pointer>\r
+ >::type active_branch_list_type;\r
+\r
+ active_branch_list_type active_branch_list;\r
+ active_branch_list.reserve(m_parameters.get_max_elements());\r
+ \r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // fill array of nodes meeting predicates\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ // if current node meets predicates\r
+ // 0 - dummy value\r
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )\r
+ {\r
+ // calculate node's distance(s) for distance predicate\r
+ node_distance_type node_distance;\r
+ // if distance isn't ok - move to the next node\r
+ if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // if current node is further than found neighbors - don't analyze it\r
+ if ( m_result.has_enough_neighbors() &&\r
+ is_node_prunable(m_result.greatest_comparable_distance(), node_distance) )\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // add current node's data into the list\r
+ active_branch_list.push_back( std::make_pair(node_distance, it->second) );\r
+ }\r
+ }\r
+\r
+ // if there aren't any nodes in ABL - return\r
+ if ( active_branch_list.empty() )\r
+ return;\r
+ \r
+ // sort array\r
+ std::sort(active_branch_list.begin(), active_branch_list.end(), abl_less);\r
+\r
+ // recursively visit nodes\r
+ for ( typename active_branch_list_type::const_iterator it = active_branch_list.begin();\r
+ it != active_branch_list.end() ; ++it )\r
+ {\r
+ // if current node is further than furthest neighbor, the rest of nodes also will be further\r
+ if ( m_result.has_enough_neighbors() &&\r
+ is_node_prunable(m_result.greatest_comparable_distance(), it->first) )\r
+ break;\r
+\r
+ rtree::apply_visitor(*this, *(it->second));\r
+ }\r
+\r
+ // ALTERNATIVE VERSION - use heap instead of sorted container\r
+ // It seems to be faster for greater MaxElements and slower otherwise\r
+ // CONSIDER: using one global container/heap for active branches\r
+ // instead of a sorted container per level\r
+ // This would also change the way how branches are traversed!\r
+ // The same may be applied to the iterative version which btw suffers\r
+ // from the copying of the whole containers on resize of the ABLs container\r
+\r
+ //// make a heap\r
+ //std::make_heap(active_branch_list.begin(), active_branch_list.end(), abl_greater);\r
+\r
+ //// recursively visit nodes\r
+ //while ( !active_branch_list.empty() )\r
+ //{\r
+ // //if current node is further than furthest neighbor, the rest of nodes also will be further\r
+ // if ( m_result.has_enough_neighbors()\r
+ // && is_node_prunable(m_result.greatest_comparable_distance(), active_branch_list.front().first) )\r
+ // {\r
+ // break;\r
+ // }\r
+\r
+ // rtree::apply_visitor(*this, *(active_branch_list.front().second));\r
+\r
+ // std::pop_heap(active_branch_list.begin(), active_branch_list.end(), abl_greater);\r
+ // active_branch_list.pop_back();\r
+ //}\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+ \r
+ // search leaf for closest value meeting predicates\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ // if value meets predicates\r
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, m_translator(*it)) )\r
+ {\r
+ // calculate values distance for distance predicate\r
+ value_distance_type value_distance;\r
+ // if distance is ok\r
+ if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) )\r
+ {\r
+ // store value\r
+ m_result.store(*it, value_distance);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ inline size_t finish()\r
+ {\r
+ return m_result.finish();\r
+ }\r
+\r
+private:\r
+ static inline bool abl_less(\r
+ std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,\r
+ std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)\r
+ {\r
+ return p1.first < p2.first;\r
+ }\r
+\r
+ //static inline bool abl_greater(\r
+ // std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,\r
+ // std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)\r
+ //{\r
+ // return p1.first > p2.first;\r
+ //}\r
+\r
+ template <typename Distance>\r
+ static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)\r
+ {\r
+ return greatest_dist <= d;\r
+ }\r
+\r
+ nearest_predicate_type const& predicate() const\r
+ {\r
+ return nearest_predicate_access::get(m_pred);\r
+ }\r
+\r
+ parameters_type const& m_parameters;\r
+ Translator const& m_translator;\r
+\r
+ Predicates m_pred;\r
+ distance_query_result<Value, Translator, value_distance_type, OutIter> m_result;\r
+};\r
+\r
+template <\r
+ typename Value,\r
+ typename Options,\r
+ typename Translator,\r
+ typename Box,\r
+ typename Allocators,\r
+ typename Predicates,\r
+ unsigned DistancePredicateIndex\r
+>\r
+class distance_query_incremental\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+public:\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;\r
+ typedef typename nearest_predicate_access::type nearest_predicate_type;\r
+ typedef typename indexable_type<Translator>::type indexable_type;\r
+ \r
+ typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;\r
+ typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;\r
+ typedef typename calculate_value_distance::result_type value_distance_type;\r
+ typedef typename calculate_node_distance::result_type node_distance_type;\r
+\r
+ typedef typename Allocators::size_type size_type;\r
+ typedef typename Allocators::const_reference const_reference;\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+\r
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type internal_elements;\r
+ typedef typename internal_elements::const_iterator internal_iterator;\r
+ typedef typename rtree::elements_type<leaf>::type leaf_elements;\r
+\r
+ typedef std::pair<node_distance_type, node_pointer> branch_data;\r
+ typedef typename index::detail::rtree::container_from_elements_type<\r
+ internal_elements, branch_data\r
+ >::type active_branch_list_type;\r
+ struct internal_stack_element\r
+ {\r
+ internal_stack_element() : current_branch(0) {}\r
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+ // Required in c++03 for containers using Boost.Move\r
+ internal_stack_element & operator=(internal_stack_element const& o)\r
+ {\r
+ branches = o.branches;\r
+ current_branch = o.current_branch;\r
+ return *this;\r
+ }\r
+#endif\r
+ active_branch_list_type branches;\r
+ typename active_branch_list_type::size_type current_branch;\r
+ };\r
+ typedef std::vector<internal_stack_element> internal_stack_type;\r
+\r
+ inline distance_query_incremental()\r
+ : m_translator(NULL)\r
+// , m_pred()\r
+ , current_neighbor((std::numeric_limits<size_type>::max)())\r
+// , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())\r
+ {}\r
+\r
+ inline distance_query_incremental(Translator const& translator, Predicates const& pred)\r
+ : m_translator(::boost::addressof(translator))\r
+ , m_pred(pred)\r
+ , current_neighbor((std::numeric_limits<size_type>::max)())\r
+\r
+ , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");\r
+ }\r
+\r
+ const_reference dereference() const\r
+ {\r
+ return *(neighbors[current_neighbor].second);\r
+ }\r
+\r
+ void initialize(node_pointer root)\r
+ {\r
+ rtree::apply_visitor(*this, *root);\r
+ increment();\r
+ }\r
+\r
+ void increment()\r
+ {\r
+ for (;;)\r
+ {\r
+ size_type new_neighbor = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;\r
+\r
+ if ( internal_stack.empty() )\r
+ {\r
+ if ( new_neighbor < neighbors.size() )\r
+ current_neighbor = new_neighbor;\r
+ else\r
+ {\r
+ current_neighbor = (std::numeric_limits<size_type>::max)();\r
+ // clear() is used to disable the condition above\r
+ neighbors.clear();\r
+ }\r
+\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ active_branch_list_type & branches = internal_stack.back().branches;\r
+ typename active_branch_list_type::size_type & current_branch = internal_stack.back().current_branch;\r
+\r
+ if ( branches.size() <= current_branch )\r
+ {\r
+ internal_stack.pop_back();\r
+ continue;\r
+ }\r
+\r
+ // if there are no nodes which can have closer values, set new value\r
+ if ( new_neighbor < neighbors.size() &&\r
+ // here must be < because otherwise neighbours may be sorted in different order\r
+ // if there is another value with equal distance\r
+ neighbors[new_neighbor].first < next_closest_node_distance )\r
+ {\r
+ current_neighbor = new_neighbor;\r
+ return;\r
+ }\r
+\r
+ // if node is further than the furthest neighbour, following nodes also will be further\r
+ BOOST_GEOMETRY_INDEX_ASSERT(neighbors.size() <= max_count(), "unexpected neighbours count");\r
+ if ( max_count() <= neighbors.size() &&\r
+ is_node_prunable(neighbors.back().first, branches[current_branch].first) )\r
+ {\r
+ // stop traversing current level\r
+ internal_stack.pop_back();\r
+ continue;\r
+ }\r
+ else\r
+ {\r
+ // new level - must increment current_branch before traversing of another level (mem reallocation)\r
+ ++current_branch;\r
+ rtree::apply_visitor(*this, *(branches[current_branch - 1].second));\r
+\r
+ next_closest_node_distance = calc_closest_node_distance(internal_stack.begin(), internal_stack.end());\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ bool is_end() const\r
+ {\r
+ return (std::numeric_limits<size_type>::max)() == current_neighbor;\r
+ }\r
+\r
+ friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||\r
+ (std::numeric_limits<size_type>::max)() == l.current_neighbor ||\r
+ (std::numeric_limits<size_type>::max)() == r.current_neighbor ||\r
+ l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,\r
+ "not corresponding iterators");\r
+ return l.current_neighbor == r.current_neighbor;\r
+ }\r
+\r
+ // Put node's elements into the list of active branches if those elements meets predicates\r
+ // and distance predicates(currently not used)\r
+ // and aren't further than found neighbours (if there is enough neighbours)\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // add new element\r
+ internal_stack.resize(internal_stack.size()+1);\r
+\r
+ // fill active branch list array of nodes meeting predicates\r
+ for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it )\r
+ {\r
+ // if current node meets predicates\r
+ // 0 - dummy value\r
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )\r
+ {\r
+ // calculate node's distance(s) for distance predicate\r
+ node_distance_type node_distance;\r
+ // if distance isn't ok - move to the next node\r
+ if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // if current node is further than found neighbors - don't analyze it\r
+ if ( max_count() <= neighbors.size() &&\r
+ is_node_prunable(neighbors.back().first, node_distance) )\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // add current node's data into the list\r
+ internal_stack.back().branches.push_back( std::make_pair(node_distance, it->second) );\r
+ }\r
+ }\r
+\r
+ if ( internal_stack.back().branches.empty() )\r
+ internal_stack.pop_back();\r
+ else\r
+ // sort array\r
+ std::sort(internal_stack.back().branches.begin(), internal_stack.back().branches.end(), abl_less);\r
+ }\r
+\r
+ // Put values into the list of neighbours if those values meets predicates\r
+ // and distance predicates(currently not used)\r
+ // and aren't further than already found neighbours (if there is enough neighbours)\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // store distance to the furthest neighbour\r
+ bool not_enough_neighbors = neighbors.size() < max_count();\r
+ value_distance_type greatest_distance = !not_enough_neighbors ? neighbors.back().first : (std::numeric_limits<value_distance_type>::max)();\r
+ \r
+ // search leaf for closest value meeting predicates\r
+ for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)\r
+ {\r
+ // if value meets predicates\r
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, (*m_translator)(*it)) )\r
+ {\r
+ // calculate values distance for distance predicate\r
+ value_distance_type value_distance;\r
+ // if distance is ok\r
+ if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) )\r
+ {\r
+ // if there is not enough values or current value is closer than furthest neighbour\r
+ if ( not_enough_neighbors || value_distance < greatest_distance )\r
+ {\r
+ neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it)));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // sort array\r
+ std::sort(neighbors.begin(), neighbors.end(), neighbors_less);\r
+ // remove furthest values\r
+ if ( max_count() < neighbors.size() )\r
+ neighbors.resize(max_count());\r
+ }\r
+\r
+private:\r
+ static inline bool abl_less(std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,\r
+ std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)\r
+ {\r
+ return p1.first < p2.first;\r
+ }\r
+\r
+ static inline bool neighbors_less(std::pair<value_distance_type, const Value *> const& p1,\r
+ std::pair<value_distance_type, const Value *> const& p2)\r
+ {\r
+ return p1.first < p2.first;\r
+ }\r
+\r
+ node_distance_type\r
+ calc_closest_node_distance(typename internal_stack_type::const_iterator first,\r
+ typename internal_stack_type::const_iterator last)\r
+ {\r
+ node_distance_type result = (std::numeric_limits<node_distance_type>::max)();\r
+ for ( ; first != last ; ++first )\r
+ {\r
+ if ( first->branches.size() <= first->current_branch )\r
+ continue;\r
+\r
+ node_distance_type curr_dist = first->branches[first->current_branch].first;\r
+ if ( curr_dist < result )\r
+ result = curr_dist;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ template <typename Distance>\r
+ static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)\r
+ {\r
+ return greatest_dist <= d;\r
+ }\r
+\r
+ inline unsigned max_count() const\r
+ {\r
+ return nearest_predicate_access::get(m_pred).count;\r
+ }\r
+\r
+ nearest_predicate_type const& predicate() const\r
+ {\r
+ return nearest_predicate_access::get(m_pred);\r
+ }\r
+\r
+ const Translator * m_translator;\r
+\r
+ Predicates m_pred;\r
+\r
+ internal_stack_type internal_stack;\r
+ std::vector< std::pair<value_distance_type, const Value *> > neighbors;\r
+ size_type current_neighbor;\r
+ node_distance_type next_closest_node_distance;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree inserting visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP\r
+\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>\r
+#include <boost/geometry/util/condition.hpp>\r
+\r
+#include <boost/geometry/index/detail/algorithms/content.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree {\r
+\r
+// Default choose_next_node\r
+template <typename Value, typename Options, typename Box, typename Allocators, typename ChooseNextNodeTag>\r
+class choose_next_node;\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+class choose_next_node<Value, Options, Box, Allocators, choose_by_content_diff_tag>\r
+{\r
+public:\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type children_type;\r
+\r
+ typedef typename index::detail::default_content_result<Box>::type content_type;\r
+\r
+ template <typename Indexable>\r
+ static inline size_t apply(internal_node & n,\r
+ Indexable const& indexable,\r
+ parameters_type const& /*parameters*/,\r
+ size_t /*node_relative_level*/)\r
+ {\r
+ children_type & children = rtree::elements(n);\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!children.empty(), "can't choose the next node if children are empty");\r
+\r
+ size_t children_count = children.size();\r
+\r
+ // choose index with smallest content change or smallest content\r
+ size_t choosen_index = 0;\r
+ content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();\r
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();\r
+\r
+ // caculate areas and areas of all nodes' boxes\r
+ for ( size_t i = 0 ; i < children_count ; ++i )\r
+ {\r
+ typedef typename children_type::value_type child_type;\r
+ child_type const& ch_i = children[i];\r
+\r
+ // expanded child node's box\r
+ Box box_exp(ch_i.first);\r
+ geometry::expand(box_exp, indexable);\r
+\r
+ // areas difference\r
+ content_type content = index::detail::content(box_exp);\r
+ content_type content_diff = content - index::detail::content(ch_i.first);\r
+\r
+ // update the result\r
+ if ( content_diff < smallest_content_diff ||\r
+ ( content_diff == smallest_content_diff && content < smallest_content ) )\r
+ {\r
+ smallest_content_diff = content_diff;\r
+ smallest_content = content;\r
+ choosen_index = i;\r
+ }\r
+ }\r
+\r
+ return choosen_index;\r
+ }\r
+};\r
+\r
+// ----------------------------------------------------------------------- //\r
+\r
+// Not implemented here\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename RedistributeTag>\r
+struct redistribute_elements\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_REDISTRIBUTE_TAG_TYPE,\r
+ (redistribute_elements));\r
+};\r
+\r
+// ----------------------------------------------------------------------- //\r
+\r
+// Split algorithm\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename SplitTag>\r
+class split\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_SPLIT_TAG_TYPE,\r
+ (split));\r
+};\r
+\r
+// Default split algorithm\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class split<Value, Options, Translator, Box, Allocators, split_default_tag>\r
+{\r
+protected:\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+\r
+public:\r
+ typedef index::detail::varray<\r
+ typename rtree::elements_type<internal_node>::type::value_type,\r
+ 1\r
+ > nodes_container_type;\r
+\r
+ template <typename Node>\r
+ static inline void apply(nodes_container_type & additional_nodes,\r
+ Node & n,\r
+ Box & n_box,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators)\r
+ {\r
+ // TODO - consider creating nodes always with sufficient memory allocated\r
+\r
+ // create additional node, use auto destroyer for automatic destruction on exception\r
+ subtree_destroyer second_node(rtree::create_node<Allocators, Node>::apply(allocators), allocators); // MAY THROW, STRONG (N: alloc)\r
+ // create reference to the newly created node\r
+ Node & n2 = rtree::get<Node>(*second_node);\r
+\r
+ // NOTE: thread-safety\r
+ // After throwing an exception by redistribute_elements the original node may be not changed or\r
+ // both nodes may be empty. In both cases the tree won't be valid r-tree.\r
+ // The alternative is to create 2 (or more) additional nodes here and store backup info\r
+ // in the original node, then, if exception was thrown, the node would always have more than max\r
+ // elements.\r
+ // The alternative is to use moving semantics in the implementations of redistribute_elements,\r
+ // it will be possible to throw from boost::move() in the case of e.g. static size nodes.\r
+\r
+ // redistribute elements\r
+ Box box2;\r
+ redistribute_elements<\r
+ Value,\r
+ Options,\r
+ Translator,\r
+ Box,\r
+ Allocators,\r
+ typename Options::redistribute_tag\r
+ >::apply(n, n2, n_box, box2, parameters, translator, allocators); // MAY THROW (V, E: alloc, copy, copy)\r
+\r
+ // check numbers of elements\r
+ BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n).size() &&\r
+ rtree::elements(n).size() <= parameters.get_max_elements(),\r
+ "unexpected number of elements");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n2).size() &&\r
+ rtree::elements(n2).size() <= parameters.get_max_elements(),\r
+ "unexpected number of elements");\r
+\r
+ // return the list of newly created nodes (this algorithm returns one)\r
+ additional_nodes.push_back(rtree::make_ptr_pair(box2, second_node.get())); // MAY THROW, STRONG (alloc, copy)\r
+\r
+ // release the ptr\r
+ second_node.release();\r
+ }\r
+};\r
+\r
+// ----------------------------------------------------------------------- //\r
+\r
+namespace visitors { namespace detail {\r
+\r
+template <typename InternalNode, typename InternalNodePtr, typename SizeType>\r
+struct insert_traverse_data\r
+{\r
+ typedef typename rtree::elements_type<InternalNode>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ typedef typename elements_type::size_type elements_size_type;\r
+ typedef SizeType size_type;\r
+\r
+ insert_traverse_data()\r
+ : parent(0), current_child_index(0), current_level(0)\r
+ {}\r
+\r
+ void move_to_next_level(InternalNodePtr new_parent,\r
+ elements_size_type new_child_index)\r
+ {\r
+ parent = new_parent;\r
+ current_child_index = new_child_index;\r
+ ++current_level;\r
+ }\r
+\r
+ bool current_is_root() const\r
+ {\r
+ return 0 == parent;\r
+ }\r
+\r
+ elements_type & parent_elements() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");\r
+ return rtree::elements(*parent);\r
+ }\r
+\r
+ element_type & current_element() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");\r
+ return rtree::elements(*parent)[current_child_index];\r
+ }\r
+\r
+ InternalNodePtr parent;\r
+ elements_size_type current_child_index;\r
+ size_type current_level;\r
+};\r
+\r
+// Default insert visitor\r
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class insert\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type\r
+{\r
+protected:\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ //typedef typename Allocators::internal_node_pointer internal_node_pointer;\r
+ typedef internal_node * internal_node_pointer;\r
+\r
+ inline insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Element const& element,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level = 0\r
+ )\r
+ : m_element(element)\r
+ , m_parameters(parameters)\r
+ , m_translator(translator)\r
+ , m_relative_level(relative_level)\r
+ , m_level(leafs_level - relative_level)\r
+ , m_root_node(root)\r
+ , m_leafs_level(leafs_level)\r
+ , m_traverse_data()\r
+ , m_allocators(allocators)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_relative_level <= leafs_level, "unexpected level value");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_level <= m_leafs_level, "unexpected level value");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 != m_root_node, "there is no root node");\r
+ // TODO\r
+ // assert - check if Box is correct\r
+\r
+ // When a value is inserted, during the tree traversal bounds of nodes\r
+ // on a path from the root to a leaf must be expanded. So prepare\r
+ // a bounding object at the beginning to not do it later for each node.\r
+ // NOTE: This is actually only needed because conditionally the bounding\r
+ // object may be expanded below. Otherwise the indexable could be\r
+ // directly used instead\r
+ index::detail::bounds(rtree::element_indexable(m_element, m_translator), m_element_bounds);\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON\r
+ // Enlarge it in case if it's not bounding geometry type.\r
+ // It's because Points and Segments are compared WRT machine epsilon\r
+ // This ensures that leafs bounds correspond to the stored elements\r
+ if (BOOST_GEOMETRY_CONDITION((\r
+ boost::is_same<Element, Value>::value\r
+ && ! index::detail::is_bounding_geometry\r
+ <\r
+ typename indexable_type<Translator>::type\r
+ >::value )) )\r
+ {\r
+ geometry::detail::expand_by_epsilon(m_element_bounds);\r
+ }\r
+#endif\r
+ }\r
+\r
+ template <typename Visitor>\r
+ inline void traverse(Visitor & visitor, internal_node & n)\r
+ {\r
+ // choose next node\r
+ size_t choosen_node_index = rtree::choose_next_node<Value, Options, Box, Allocators, typename Options::choose_next_node_tag>::\r
+ apply(n, rtree::element_indexable(m_element, m_translator), m_parameters, m_leafs_level - m_traverse_data.current_level);\r
+\r
+ // expand the node to contain value\r
+ geometry::expand(\r
+ rtree::elements(n)[choosen_node_index].first,\r
+ m_element_bounds\r
+ /*rtree::element_indexable(m_element, m_translator)*/);\r
+\r
+ // next traversing step\r
+ traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc)\r
+ }\r
+\r
+ // TODO: awulkiew - change post_traverse name to handle_overflow or overflow_treatment?\r
+\r
+ template <typename Node>\r
+ inline void post_traverse(Node &n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_traverse_data.current_is_root() ||\r
+ &n == &rtree::get<Node>(*m_traverse_data.current_element().second),\r
+ "if node isn't the root current_child_index should be valid");\r
+\r
+ // handle overflow\r
+ if ( m_parameters.get_max_elements() < rtree::elements(n).size() )\r
+ {\r
+ // NOTE: If the exception is thrown current node may contain more than MAX elements or be empty.\r
+ // Furthermore it may be empty root - internal node.\r
+ split(n); // MAY THROW (V, E: alloc, copy, N:alloc)\r
+ }\r
+ }\r
+\r
+ template <typename Visitor>\r
+ inline void traverse_apply_visitor(Visitor & visitor, internal_node &n, size_t choosen_node_index)\r
+ {\r
+ // save previous traverse inputs and set new ones\r
+ insert_traverse_data<internal_node, internal_node_pointer, size_type>\r
+ backup_traverse_data = m_traverse_data;\r
+\r
+ // calculate new traverse inputs\r
+ m_traverse_data.move_to_next_level(&n, choosen_node_index);\r
+\r
+ // next traversing step\r
+ rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N:alloc)\r
+\r
+ // restore previous traverse inputs\r
+ m_traverse_data = backup_traverse_data;\r
+ }\r
+\r
+ // TODO: consider - split result returned as OutIter is faster than reference to the container. Why?\r
+\r
+ template <typename Node>\r
+ inline void split(Node & n) const\r
+ {\r
+ typedef rtree::split<Value, Options, Translator, Box, Allocators, typename Options::split_tag> split_algo;\r
+\r
+ typename split_algo::nodes_container_type additional_nodes;\r
+ Box n_box;\r
+\r
+ split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators); // MAY THROW (V, E: alloc, copy, N:alloc)\r
+\r
+ BOOST_GEOMETRY_INDEX_ASSERT(additional_nodes.size() == 1, "unexpected number of additional nodes");\r
+\r
+ // TODO add all additional nodes\r
+ // For kmeans algorithm:\r
+ // elements number may be greater than node max elements count\r
+ // split and reinsert must take node with some elements count\r
+ // and container of additional elements (std::pair<Box, node*>s or Values)\r
+ // and translator + allocators\r
+ // where node_elements_count + additional_elements > node_max_elements_count\r
+ // What with elements other than std::pair<Box, node*> ?\r
+ // Implement template <node_tag> struct node_element_type or something like that\r
+\r
+ // for exception safety\r
+ subtree_destroyer additional_node_ptr(additional_nodes[0].second, m_allocators);\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_EXPERIMENTAL_ENLARGE_BY_EPSILON\r
+ // Enlarge bounds of a leaf node.\r
+ // It's because Points and Segments are compared WRT machine epsilon\r
+ // This ensures that leafs' bounds correspond to the stored elements.\r
+ if (BOOST_GEOMETRY_CONDITION((\r
+ boost::is_same<Node, leaf>::value\r
+ && ! index::detail::is_bounding_geometry\r
+ <\r
+ typename indexable_type<Translator>::type\r
+ >::value )))\r
+ {\r
+ geometry::detail::expand_by_epsilon(n_box);\r
+ geometry::detail::expand_by_epsilon(additional_nodes[0].first);\r
+ }\r
+#endif\r
+\r
+ // node is not the root - just add the new node\r
+ if ( !m_traverse_data.current_is_root() )\r
+ {\r
+ // update old node's box\r
+ m_traverse_data.current_element().first = n_box;\r
+ // add new node to parent's children\r
+ m_traverse_data.parent_elements().push_back(additional_nodes[0]); // MAY THROW, STRONG (V, E: alloc, copy)\r
+ }\r
+ // node is the root - add level\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*m_root_node), "node should be the root");\r
+\r
+ // create new root and add nodes\r
+ subtree_destroyer new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)\r
+\r
+ BOOST_TRY\r
+ {\r
+ rtree::elements(rtree::get<internal_node>(*new_root)).push_back(rtree::make_ptr_pair(n_box, m_root_node)); // MAY THROW, STRONG (E:alloc, copy)\r
+ rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]); // MAY THROW, STRONG (E:alloc, copy)\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ // clear new root to not delete in the ~subtree_destroyer() potentially stored old root node\r
+ rtree::elements(rtree::get<internal_node>(*new_root)).clear();\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ m_root_node = new_root.get();\r
+ ++m_leafs_level;\r
+\r
+ new_root.release();\r
+ }\r
+\r
+ additional_node_ptr.release();\r
+ }\r
+\r
+ // TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation\r
+\r
+ Element const& m_element;\r
+ Box m_element_bounds;\r
+ parameters_type const& m_parameters;\r
+ Translator const& m_translator;\r
+ size_type const m_relative_level;\r
+ size_type const m_level;\r
+\r
+ node_pointer & m_root_node;\r
+ size_type & m_leafs_level;\r
+\r
+ // traversing input parameters\r
+ insert_traverse_data<internal_node, internal_node_pointer, size_type> m_traverse_data;\r
+\r
+ Allocators & m_allocators;\r
+};\r
+\r
+} // namespace detail\r
+\r
+// Insert visitor forward declaration\r
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename InsertTag>\r
+class insert;\r
+\r
+// Default insert visitor used for nodes elements\r
+// After passing the Element to insert visitor the Element is managed by the tree\r
+// I.e. one should not delete the node passed to the insert visitor after exception is thrown\r
+// because this visitor may delete it\r
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag>\r
+ : public detail::insert<Element, Value, Options, Translator, Box, Allocators>\r
+{\r
+public:\r
+ typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;\r
+ typedef typename base::node node;\r
+ typedef typename base::internal_node internal_node;\r
+ typedef typename base::leaf leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+ typedef typename base::node_pointer node_pointer;\r
+ typedef typename base::size_type size_type;\r
+\r
+ inline insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Element const& element,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level = 0\r
+ )\r
+ : base(root, leafs_level, element, parameters, translator, allocators, relative_level)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");\r
+\r
+ if ( base::m_traverse_data.current_level < base::m_level )\r
+ {\r
+ // next traversing step\r
+ base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");\r
+\r
+ BOOST_TRY\r
+ {\r
+ // push new child node\r
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ // if the insert fails above, the element won't be stored in the tree\r
+\r
+ rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);\r
+ rtree::apply_visitor(del_v, *base::m_element.second);\r
+\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+ }\r
+\r
+ base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)\r
+ }\r
+\r
+ inline void operator()(leaf &)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");\r
+ }\r
+};\r
+\r
+// Default insert visitor specialized for Values elements\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class insert<Value, Value, Options, Translator, Box, Allocators, insert_default_tag>\r
+ : public detail::insert<Value, Value, Options, Translator, Box, Allocators>\r
+{\r
+public:\r
+ typedef detail::insert<Value, Value, Options, Translator, Box, Allocators> base;\r
+ typedef typename base::node node;\r
+ typedef typename base::internal_node internal_node;\r
+ typedef typename base::leaf leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+ typedef typename base::node_pointer node_pointer;\r
+ typedef typename base::size_type size_type;\r
+\r
+ inline insert(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Value const& value,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators,\r
+ size_type relative_level = 0\r
+ )\r
+ : base(root, leafs_level, value, parameters, translator, allocators, relative_level)\r
+ {}\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");\r
+\r
+ // next traversing step\r
+ base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)\r
+ }\r
+\r
+ inline void operator()(leaf & n)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level, "unexpected level");\r
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||\r
+ base::m_level == (std::numeric_limits<size_t>::max)(), "unexpected level");\r
+ \r
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)\r
+\r
+ base::post_traverse(n); // MAY THROW (V: alloc, copy, N: alloc)\r
+ }\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree leaf node checking visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Box, typename Allocators>\r
+struct is_leaf : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ is_leaf()\r
+ : result(false)\r
+ {}\r
+\r
+ inline void operator()(internal_node const&)\r
+ {\r
+ // result = false;\r
+ }\r
+\r
+ inline void operator()(leaf const&)\r
+ {\r
+ result = true;\r
+ }\r
+\r
+ bool result;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree iterator visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class iterator\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+public:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Allocators::size_type size_type;\r
+ typedef typename Allocators::const_reference const_reference;\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;\r
+ typedef typename rtree::elements_type<leaf>::type leaf_elements;\r
+ typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;\r
+\r
+ inline iterator()\r
+ : m_values(NULL)\r
+ , m_current()\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ m_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ m_values = ::boost::addressof(rtree::elements(n));\r
+ m_current = rtree::elements(n).begin();\r
+ }\r
+\r
+ const_reference dereference() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");\r
+ return *m_current;\r
+ }\r
+\r
+ void initialize(node_pointer root)\r
+ {\r
+ rtree::apply_visitor(*this, *root);\r
+ search_value();\r
+ }\r
+\r
+ void increment()\r
+ {\r
+ ++m_current;\r
+ search_value();\r
+ }\r
+\r
+ void search_value()\r
+ {\r
+ for (;;)\r
+ {\r
+ // if leaf is choosen, move to the next value in leaf\r
+ if ( m_values )\r
+ {\r
+ // there are more values in the current leaf\r
+ if ( m_current != m_values->end() )\r
+ {\r
+ return;\r
+ }\r
+ // no more values, clear current leaf\r
+ else\r
+ {\r
+ m_values = 0;\r
+ }\r
+ }\r
+ // if leaf isn't choosen, move to the next leaf\r
+ else\r
+ {\r
+ // return if there is no more nodes to traverse\r
+ if ( m_internal_stack.empty() )\r
+ return;\r
+\r
+ // no more children in current node, remove it from stack\r
+ if ( m_internal_stack.back().first == m_internal_stack.back().second )\r
+ {\r
+ m_internal_stack.pop_back();\r
+ continue;\r
+ }\r
+\r
+ internal_iterator it = m_internal_stack.back().first;\r
+ ++m_internal_stack.back().first;\r
+\r
+ // push the next node to the stack\r
+ rtree::apply_visitor(*this, *(it->second));\r
+ }\r
+ }\r
+ }\r
+\r
+ bool is_end() const\r
+ {\r
+ return 0 == m_values;\r
+ }\r
+\r
+ friend bool operator==(iterator const& l, iterator const& r)\r
+ {\r
+ return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );\r
+ }\r
+\r
+private:\r
+\r
+ std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;\r
+ const leaf_elements * m_values;\r
+ leaf_iterator m_current;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree removing visitor implementation\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP\r
+\r
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+// Default remove algorithm\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class remove\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type\r
+{\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type::size_type internal_size_type;\r
+\r
+ //typedef typename Allocators::internal_node_pointer internal_node_pointer;\r
+ typedef internal_node * internal_node_pointer;\r
+\r
+public:\r
+ inline remove(node_pointer & root,\r
+ size_type & leafs_level,\r
+ Value const& value,\r
+ parameters_type const& parameters,\r
+ Translator const& translator,\r
+ Allocators & allocators)\r
+ : m_value(value)\r
+ , m_parameters(parameters)\r
+ , m_translator(translator)\r
+ , m_allocators(allocators)\r
+ , m_root_node(root)\r
+ , m_leafs_level(leafs_level)\r
+ , m_is_value_removed(false)\r
+ , m_parent(0)\r
+ , m_current_child_index(0)\r
+ , m_current_level(0)\r
+ , m_is_underflow(false)\r
+ {\r
+ // TODO\r
+ // assert - check if Value/Box is correct\r
+ }\r
+\r
+ inline void operator()(internal_node & n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type children_type;\r
+ children_type & children = rtree::elements(n);\r
+\r
+ // traverse children which boxes intersects value's box\r
+ internal_size_type child_node_index = 0;\r
+ for ( ; child_node_index < children.size() ; ++child_node_index )\r
+ {\r
+ if ( geometry::covered_by(\r
+ return_ref_or_bounds(m_translator(m_value)),\r
+ children[child_node_index].first) )\r
+ {\r
+ // next traversing step\r
+ traverse_apply_visitor(n, child_node_index); // MAY THROW\r
+\r
+ if ( m_is_value_removed )\r
+ break;\r
+ }\r
+ }\r
+\r
+ // value was found and removed\r
+ if ( m_is_value_removed )\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ typedef typename elements_type::iterator element_iterator;\r
+ elements_type & elements = rtree::elements(n);\r
+\r
+ // underflow occured - child node should be removed\r
+ if ( m_is_underflow )\r
+ {\r
+ element_iterator underfl_el_it = elements.begin() + child_node_index;\r
+ size_type relative_level = m_leafs_level - m_current_level;\r
+\r
+ // move node to the container - store node's relative level as well and return new underflow state\r
+ // NOTE: if the min elements number is 1, then after an underflow\r
+ // here the child elements count is 0, so it's not required to store this node,\r
+ // it could just be destroyed\r
+ m_is_underflow = store_underflowed_node(elements, underfl_el_it, relative_level); // MAY THROW (E: alloc, copy)\r
+ }\r
+\r
+ // n is not root - adjust aabb\r
+ if ( 0 != m_parent )\r
+ {\r
+ // underflow state should be ok here\r
+ // note that there may be less than min_elems elements in root\r
+ // so this condition should be checked only here\r
+ BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state");\r
+\r
+ rtree::elements(*m_parent)[m_current_child_index].first\r
+ = rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator);\r
+ }\r
+ // n is root node\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root_node), "node must be the root");\r
+\r
+ // reinsert elements from removed nodes (underflows)\r
+ reinsert_removed_nodes_elements(); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ // shorten the tree\r
+ // NOTE: if the min elements number is 1, then after underflow\r
+ // here the number of elements may be equal to 0\r
+ // this can occur only for the last removed element\r
+ if ( rtree::elements(n).size() <= 1 )\r
+ {\r
+ node_pointer root_to_destroy = m_root_node;\r
+ if ( rtree::elements(n).size() == 0 )\r
+ m_root_node = 0;\r
+ else\r
+ m_root_node = rtree::elements(n)[0].second;\r
+ --m_leafs_level;\r
+\r
+ rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, root_to_destroy);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void operator()(leaf & n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type & elements = rtree::elements(n);\r
+\r
+ // find value and remove it\r
+ for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it )\r
+ {\r
+ if ( m_translator.equals(*it, m_value) )\r
+ {\r
+ rtree::move_from_back(elements, it); // MAY THROW (V: copy)\r
+ elements.pop_back();\r
+ m_is_value_removed = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ // if value was removed\r
+ if ( m_is_value_removed )\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_parameters.get_min_elements(), "min number of elements is too small");\r
+\r
+ // calc underflow\r
+ m_is_underflow = elements.size() < m_parameters.get_min_elements();\r
+\r
+ // n is not root - adjust aabb\r
+ if ( 0 != m_parent )\r
+ {\r
+ rtree::elements(*m_parent)[m_current_child_index].first\r
+ = rtree::values_box<Box>(elements.begin(), elements.end(), m_translator);\r
+ }\r
+ }\r
+ }\r
+\r
+ bool is_value_removed() const\r
+ {\r
+ return m_is_value_removed;\r
+ }\r
+\r
+private:\r
+\r
+ typedef std::vector< std::pair<size_type, node_pointer> > UnderflowNodes;\r
+\r
+ void traverse_apply_visitor(internal_node &n, internal_size_type choosen_node_index)\r
+ {\r
+ // save previous traverse inputs and set new ones\r
+ internal_node_pointer parent_bckup = m_parent;\r
+ internal_size_type current_child_index_bckup = m_current_child_index;\r
+ size_type current_level_bckup = m_current_level;\r
+\r
+ m_parent = &n;\r
+ m_current_child_index = choosen_node_index;\r
+ ++m_current_level;\r
+\r
+ // next traversing step\r
+ rtree::apply_visitor(*this, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ // restore previous traverse inputs\r
+ m_parent = parent_bckup;\r
+ m_current_child_index = current_child_index_bckup;\r
+ m_current_level = current_level_bckup;\r
+ }\r
+\r
+ bool store_underflowed_node(\r
+ typename rtree::elements_type<internal_node>::type & elements,\r
+ typename rtree::elements_type<internal_node>::type::iterator underfl_el_it,\r
+ size_type relative_level)\r
+ {\r
+ // move node to the container - store node's relative level as well\r
+ m_underflowed_nodes.push_back(std::make_pair(relative_level, underfl_el_it->second)); // MAY THROW (E: alloc, copy)\r
+\r
+ BOOST_TRY\r
+ {\r
+ // NOTE: those are elements of the internal node which means that copy/move shouldn't throw\r
+ // Though it's safer in case if the pointer type could throw in copy ctor.\r
+ // In the future this try-catch block could be removed.\r
+ rtree::move_from_back(elements, underfl_el_it); // MAY THROW (E: copy)\r
+ elements.pop_back();\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ m_underflowed_nodes.pop_back();\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ // calc underflow\r
+ return elements.size() < m_parameters.get_min_elements();\r
+ }\r
+\r
+ static inline bool is_leaf(node const& n)\r
+ {\r
+ visitors::is_leaf<Value, Options, Box, Allocators> ilv;\r
+ rtree::apply_visitor(ilv, n);\r
+ return ilv.result;\r
+ }\r
+\r
+ void reinsert_removed_nodes_elements()\r
+ {\r
+ typename UnderflowNodes::reverse_iterator it = m_underflowed_nodes.rbegin();\r
+\r
+ BOOST_TRY\r
+ {\r
+ // reinsert elements from removed nodes\r
+ // begin with levels closer to the root\r
+ for ( ; it != m_underflowed_nodes.rend() ; ++it )\r
+ {\r
+ // it->first is an index of a level of a node, not children\r
+ // counted from the leafs level\r
+ bool const node_is_leaf = it->first == 1;\r
+ BOOST_GEOMETRY_INDEX_ASSERT(node_is_leaf == is_leaf(*it->second), "unexpected condition");\r
+ if ( node_is_leaf )\r
+ {\r
+ reinsert_node_elements(rtree::get<leaf>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ rtree::destroy_node<Allocators, leaf>::apply(m_allocators, it->second);\r
+ }\r
+ else\r
+ {\r
+ reinsert_node_elements(rtree::get<internal_node>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, it->second);\r
+ }\r
+ }\r
+\r
+ //m_underflowed_nodes.clear();\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ // destroy current and remaining nodes\r
+ for ( ; it != m_underflowed_nodes.rend() ; ++it )\r
+ {\r
+ subtree_destroyer dummy(it->second, m_allocators);\r
+ }\r
+\r
+ //m_underflowed_nodes.clear();\r
+\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+ }\r
+\r
+ template <typename Node>\r
+ void reinsert_node_elements(Node &n, size_type node_relative_level)\r
+ {\r
+ typedef typename rtree::elements_type<Node>::type elements_type;\r
+ elements_type & elements = rtree::elements(n);\r
+\r
+ typename elements_type::iterator it = elements.begin();\r
+ BOOST_TRY\r
+ {\r
+ for ( ; it != elements.end() ; ++it )\r
+ {\r
+ visitors::insert<\r
+ typename elements_type::value_type,\r
+ Value, Options, Translator, Box, Allocators,\r
+ typename Options::insert_tag\r
+ > insert_v(\r
+ m_root_node, m_leafs_level, *it,\r
+ m_parameters, m_translator, m_allocators,\r
+ node_relative_level - 1);\r
+\r
+ rtree::apply_visitor(insert_v, *m_root_node); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+ }\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ ++it;\r
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>\r
+ ::apply(it, elements.end(), m_allocators);\r
+ elements.clear();\r
+ BOOST_RETHROW // RETHROW\r
+ }\r
+ BOOST_CATCH_END\r
+ }\r
+\r
+ Value const& m_value;\r
+ parameters_type const& m_parameters;\r
+ Translator const& m_translator;\r
+ Allocators & m_allocators;\r
+\r
+ node_pointer & m_root_node;\r
+ size_type & m_leafs_level;\r
+\r
+ bool m_is_value_removed;\r
+ UnderflowNodes m_underflowed_nodes;\r
+\r
+ // traversing input parameters\r
+ internal_node_pointer m_parent;\r
+ internal_size_type m_current_child_index;\r
+ size_type m_current_level;\r
+\r
+ // traversing output parameters\r
+ bool m_is_underflow;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree spatial query visitor implementation\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { namespace rtree { namespace visitors {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, typename OutIter>\r
+struct spatial_query\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;\r
+\r
+ inline spatial_query(Translator const& t, Predicates const& p, OutIter out_it)\r
+ : tr(t), pred(p), out_iter(out_it), found_count(0)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // traverse nodes meeting predicates\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ // if node meets predicates\r
+ // 0 - dummy value\r
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, it->first) )\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // get all values meeting predicates\r
+ for (typename elements_type::const_iterator it = elements.begin();\r
+ it != elements.end(); ++it)\r
+ {\r
+ // if value meets predicates\r
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(pred, *it, tr(*it)) )\r
+ {\r
+ *out_iter = *it;\r
+ ++out_iter;\r
+\r
+ ++found_count;\r
+ }\r
+ }\r
+ }\r
+\r
+ Translator const& tr;\r
+\r
+ Predicates pred;\r
+\r
+ OutIter out_iter;\r
+ size_type found_count;\r
+};\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>\r
+class spatial_query_incremental\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+public:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Allocators::size_type size_type;\r
+ typedef typename Allocators::const_reference const_reference;\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;\r
+ typedef typename rtree::elements_type<leaf>::type leaf_elements;\r
+ typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;\r
+\r
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;\r
+\r
+ inline spatial_query_incremental()\r
+ : m_translator(NULL)\r
+// , m_pred()\r
+ , m_values(NULL)\r
+ , m_current()\r
+ {}\r
+\r
+ inline spatial_query_incremental(Translator const& t, Predicates const& p)\r
+ : m_translator(::boost::addressof(t))\r
+ , m_pred(p)\r
+ , m_values(NULL)\r
+ , m_current()\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ m_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));\r
+ }\r
+\r
+ inline void operator()(leaf const& n)\r
+ {\r
+ m_values = ::boost::addressof(rtree::elements(n));\r
+ m_current = rtree::elements(n).begin();\r
+ }\r
+\r
+ const_reference dereference() const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_values, "not dereferencable");\r
+ return *m_current;\r
+ }\r
+\r
+ void initialize(node_pointer root)\r
+ {\r
+ rtree::apply_visitor(*this, *root);\r
+ search_value();\r
+ }\r
+\r
+ void increment()\r
+ {\r
+ ++m_current;\r
+ search_value();\r
+ }\r
+\r
+ void search_value()\r
+ {\r
+ for (;;)\r
+ {\r
+ // if leaf is choosen, move to the next value in leaf\r
+ if ( m_values )\r
+ {\r
+ if ( m_current != m_values->end() )\r
+ {\r
+ // return if next value is found\r
+ Value const& v = *m_current;\r
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, v, (*m_translator)(v)) )\r
+ return;\r
+\r
+ ++m_current;\r
+ }\r
+ // no more values, clear current leaf\r
+ else\r
+ {\r
+ m_values = 0;\r
+ }\r
+ }\r
+ // if leaf isn't choosen, move to the next leaf\r
+ else\r
+ {\r
+ // return if there is no more nodes to traverse\r
+ if ( m_internal_stack.empty() )\r
+ return;\r
+\r
+ // no more children in current node, remove it from stack\r
+ if ( m_internal_stack.back().first == m_internal_stack.back().second )\r
+ {\r
+ m_internal_stack.pop_back();\r
+ continue;\r
+ }\r
+\r
+ internal_iterator it = m_internal_stack.back().first;\r
+ ++m_internal_stack.back().first;\r
+\r
+ // next node is found, push it to the stack\r
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )\r
+ rtree::apply_visitor(*this, *(it->second));\r
+ }\r
+ }\r
+ }\r
+\r
+ bool is_end() const\r
+ {\r
+ return 0 == m_values;\r
+ }\r
+\r
+ friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)\r
+ {\r
+ return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );\r
+ }\r
+\r
+private:\r
+\r
+ const Translator * m_translator;\r
+\r
+ Predicates m_pred;\r
+\r
+ std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;\r
+ const leaf_elements * m_values;\r
+ leaf_iterator m_current;\r
+};\r
+\r
+}}} // namespace detail::rtree::visitors\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP\r
+\r
+//#include <boost/serialization/serialization.hpp>\r
+#include <boost/serialization/split_member.hpp>\r
+#include <boost/serialization/version.hpp>\r
+//#include <boost/serialization/nvp.hpp>\r
+\r
+// TODO\r
+// how about using the unsigned type capable of storing Max in compile-time versions?\r
+\r
+// TODO\r
+// - add wrappers for Point and Box and implement serialize for those wrappers instead of\r
+// raw geometries\r
+// PROBLEM: after implementing this, how Values would be set?\r
+// - store the name of the parameters to know how to load and detect errors\r
+// - in the header, once store info about the Indexable and Bounds types (geometry type, point CS, Dim, etc.)\r
+// each geometry save without this info\r
+\r
+// TODO - move to index/detail/serialization.hpp\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+// TODO - use boost::move?\r
+template<typename T>\r
+class serialization_storage\r
+{\r
+public:\r
+ template <typename Archive>\r
+ serialization_storage(Archive & ar, unsigned int version)\r
+ {\r
+ boost::serialization::load_construct_data_adl(ar, this->address(), version);\r
+ }\r
+ ~serialization_storage()\r
+ {\r
+ this->address()->~T();\r
+ }\r
+ T * address()\r
+ {\r
+ return static_cast<T*>(m_storage.address());\r
+ }\r
+private:\r
+ boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> m_storage;\r
+};\r
+\r
+// TODO - save and load item_version? see: collections_load_imp and collections_save_imp\r
+// this should be done once for the whole container\r
+// versions of all used types should be stored\r
+\r
+template <typename T, typename Archive> inline\r
+T serialization_load(const char * name, Archive & ar)\r
+{\r
+ namespace bs = boost::serialization; \r
+ serialization_storage<T> storage(ar, bs::version<T>::value); // load_construct_data\r
+ ar >> boost::serialization::make_nvp(name, *storage.address()); // serialize\r
+ //ar >> *storage.address(); // serialize\r
+ return *storage.address();\r
+}\r
+\r
+template <typename T, typename Archive> inline\r
+void serialization_save(T const& t, const char * name, Archive & ar)\r
+{\r
+ namespace bs = boost::serialization;\r
+ bs::save_construct_data_adl(ar, boost::addressof(t), bs::version<T>::value); // save_construct_data\r
+ ar << boost::serialization::make_nvp(name, t); // serialize\r
+ //ar << t; // serialize\r
+}\r
+ \r
+}}}}\r
+\r
+// TODO - move to index/serialization/rtree.hpp\r
+namespace boost { namespace serialization {\r
+\r
+// boost::geometry::index::linear\r
+\r
+template<class Archive, size_t Max, size_t Min>\r
+void save_construct_data(Archive & ar, const boost::geometry::index::linear<Max, Min> * params, unsigned int )\r
+{\r
+ size_t max = params->get_max_elements(), min = params->get_min_elements();\r
+ ar << boost::serialization::make_nvp("max", max);\r
+ ar << boost::serialization::make_nvp("min", min);\r
+}\r
+template<class Archive, size_t Max, size_t Min>\r
+void load_construct_data(Archive & ar, boost::geometry::index::linear<Max, Min> * params, unsigned int )\r
+{\r
+ size_t max, min;\r
+ ar >> boost::serialization::make_nvp("max", max);\r
+ ar >> boost::serialization::make_nvp("min", min);\r
+ if ( max != params->get_max_elements() || min != params->get_min_elements() )\r
+ // TODO change exception type\r
+ BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));\r
+ // the constructor musn't be called for this type\r
+ //::new(params)boost::geometry::index::linear<Max, Min>();\r
+}\r
+template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::linear<Max, Min> &, unsigned int) {}\r
+\r
+// boost::geometry::index::quadratic\r
+\r
+template<class Archive, size_t Max, size_t Min>\r
+void save_construct_data(Archive & ar, const boost::geometry::index::quadratic<Max, Min> * params, unsigned int )\r
+{\r
+ size_t max = params->get_max_elements(), min = params->get_min_elements();\r
+ ar << boost::serialization::make_nvp("max", max);\r
+ ar << boost::serialization::make_nvp("min", min);\r
+}\r
+template<class Archive, size_t Max, size_t Min>\r
+void load_construct_data(Archive & ar, boost::geometry::index::quadratic<Max, Min> * params, unsigned int )\r
+{\r
+ size_t max, min;\r
+ ar >> boost::serialization::make_nvp("max", max);\r
+ ar >> boost::serialization::make_nvp("min", min);\r
+ if ( max != params->get_max_elements() || min != params->get_min_elements() )\r
+ // TODO change exception type\r
+ BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));\r
+ // the constructor musn't be called for this type\r
+ //::new(params)boost::geometry::index::quadratic<Max, Min>();\r
+}\r
+template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::quadratic<Max, Min> &, unsigned int) {}\r
+\r
+// boost::geometry::index::rstar\r
+\r
+template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>\r
+void save_construct_data(Archive & ar, const boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )\r
+{\r
+ size_t max = params->get_max_elements()\r
+ , min = params->get_min_elements()\r
+ , re = params->get_reinserted_elements()\r
+ , oct = params->get_overlap_cost_threshold();\r
+ ar << boost::serialization::make_nvp("max", max);\r
+ ar << boost::serialization::make_nvp("min", min);\r
+ ar << boost::serialization::make_nvp("re", re);\r
+ ar << boost::serialization::make_nvp("oct", oct);\r
+}\r
+template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>\r
+void load_construct_data(Archive & ar, boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )\r
+{\r
+ size_t max, min, re, oct;\r
+ ar >> boost::serialization::make_nvp("max", max);\r
+ ar >> boost::serialization::make_nvp("min", min);\r
+ ar >> boost::serialization::make_nvp("re", re);\r
+ ar >> boost::serialization::make_nvp("oct", oct);\r
+ if ( max != params->get_max_elements() || min != params->get_min_elements() ||\r
+ re != params->get_reinserted_elements() || oct != params->get_overlap_cost_threshold() )\r
+ // TODO change exception type\r
+ BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));\r
+ // the constructor musn't be called for this type\r
+ //::new(params)boost::geometry::index::rstar<Max, Min, RE, OCT>();\r
+}\r
+template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>\r
+void serialize(Archive &, boost::geometry::index::rstar<Max, Min, RE, OCT> &, unsigned int) {}\r
+\r
+// boost::geometry::index::dynamic_linear\r
+\r
+template<class Archive>\r
+inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_linear * params, unsigned int )\r
+{\r
+ size_t max = params->get_max_elements(), min = params->get_min_elements();\r
+ ar << boost::serialization::make_nvp("max", max);\r
+ ar << boost::serialization::make_nvp("min", min);\r
+}\r
+template<class Archive>\r
+inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_linear * params, unsigned int )\r
+{\r
+ size_t max, min;\r
+ ar >> boost::serialization::make_nvp("max", max);\r
+ ar >> boost::serialization::make_nvp("min", min);\r
+ ::new(params)boost::geometry::index::dynamic_linear(max, min);\r
+}\r
+template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_linear &, unsigned int) {}\r
+\r
+// boost::geometry::index::dynamic_quadratic\r
+\r
+template<class Archive>\r
+inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_quadratic * params, unsigned int )\r
+{\r
+ size_t max = params->get_max_elements(), min = params->get_min_elements();\r
+ ar << boost::serialization::make_nvp("max", max);\r
+ ar << boost::serialization::make_nvp("min", min);\r
+}\r
+template<class Archive>\r
+inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_quadratic * params, unsigned int )\r
+{\r
+ size_t max, min;\r
+ ar >> boost::serialization::make_nvp("max", max);\r
+ ar >> boost::serialization::make_nvp("min", min);\r
+ ::new(params)boost::geometry::index::dynamic_quadratic(max, min);\r
+}\r
+template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_quadratic &, unsigned int) {}\r
+\r
+// boost::geometry::index::dynamic_rstar\r
+\r
+template<class Archive>\r
+inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_rstar * params, unsigned int )\r
+{\r
+ size_t max = params->get_max_elements()\r
+ , min = params->get_min_elements()\r
+ , re = params->get_reinserted_elements()\r
+ , oct = params->get_overlap_cost_threshold();\r
+ ar << boost::serialization::make_nvp("max", max);\r
+ ar << boost::serialization::make_nvp("min", min);\r
+ ar << boost::serialization::make_nvp("re", re);\r
+ ar << boost::serialization::make_nvp("oct", oct);\r
+}\r
+template<class Archive>\r
+inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_rstar * params, unsigned int )\r
+{\r
+ size_t max, min, re, oct;\r
+ ar >> boost::serialization::make_nvp("max", max);\r
+ ar >> boost::serialization::make_nvp("min", min);\r
+ ar >> boost::serialization::make_nvp("re", re);\r
+ ar >> boost::serialization::make_nvp("oct", oct);\r
+ ::new(params)boost::geometry::index::dynamic_rstar(max, min, re, oct);\r
+}\r
+template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_rstar &, unsigned int) {}\r
+\r
+}} // boost::serialization\r
+\r
+// TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename P, size_t I = 0, size_t D = geometry::dimension<P>::value>\r
+struct serialize_point\r
+{\r
+ template <typename Archive>\r
+ static inline void save(Archive & ar, P const& p, unsigned int version)\r
+ {\r
+ typename coordinate_type<P>::type c = get<I>(p);\r
+ ar << boost::serialization::make_nvp("c", c);\r
+ serialize_point<P, I+1, D>::save(ar, p, version);\r
+ }\r
+\r
+ template <typename Archive>\r
+ static inline void load(Archive & ar, P & p, unsigned int version)\r
+ {\r
+ typename geometry::coordinate_type<P>::type c;\r
+ ar >> boost::serialization::make_nvp("c", c);\r
+ set<I>(p, c);\r
+ serialize_point<P, I+1, D>::load(ar, p, version);\r
+ }\r
+};\r
+\r
+template <typename P, size_t D>\r
+struct serialize_point<P, D, D>\r
+{\r
+ template <typename Archive> static inline void save(Archive &, P const&, unsigned int) {}\r
+ template <typename Archive> static inline void load(Archive &, P &, unsigned int) {}\r
+};\r
+\r
+}}}}\r
+\r
+// TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp\r
+namespace boost { namespace serialization {\r
+\r
+template<class Archive, typename T, size_t D, typename C>\r
+void save(Archive & ar, boost::geometry::model::point<T, D, C> const& p, unsigned int version)\r
+{\r
+ boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::save(ar, p, version);\r
+}\r
+template<class Archive, typename T, size_t D, typename C>\r
+void load(Archive & ar, boost::geometry::model::point<T, D, C> & p, unsigned int version)\r
+{\r
+ boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::load(ar, p, version);\r
+}\r
+template<class Archive, typename T, size_t D, typename C>\r
+inline void serialize(Archive & ar, boost::geometry::model::point<T, D, C> & o, const unsigned int version) { split_free(ar, o, version); }\r
+\r
+template<class Archive, typename P>\r
+inline void serialize(Archive & ar, boost::geometry::model::box<P> & b, const unsigned int)\r
+{\r
+ ar & boost::serialization::make_nvp("min", b.min_corner());\r
+ ar & boost::serialization::make_nvp("max", b.max_corner());\r
+}\r
+\r
+}} // boost::serialization\r
+\r
+// TODO - move to index/detail/rtree/visitors/save.hpp\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors {\r
+\r
+// TODO move saving and loading of the rtree outside the rtree, this will require adding some kind of members_view\r
+\r
+template <typename Archive, typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class save\r
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type\r
+{\r
+public:\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ save(Archive & archive, unsigned int version)\r
+ : m_archive(archive), m_version(version)\r
+ {}\r
+\r
+ inline void operator()(internal_node const& n)\r
+ {\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ elements_type const& elements = rtree::elements(n);\r
+\r
+ // CONSIDER: change to elements_type::size_type or size_type\r
+ // or use fixed-size type like uint32 or even uint16?\r
+ size_t s = elements.size();\r
+ m_archive << boost::serialization::make_nvp("s", s);\r
+\r
+ for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)\r
+ {\r
+ serialization_save(it->first, "b", m_archive);\r
+\r
+ rtree::apply_visitor(*this, *it->second);\r
+ }\r
+ }\r
+\r
+ inline void operator()(leaf const& l)\r
+ {\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ //typedef typename elements_type::size_type elements_size;\r
+ elements_type const& elements = rtree::elements(l);\r
+\r
+ // CONSIDER: change to elements_type::size_type or size_type\r
+ // or use fixed-size type like uint32 or even uint16?\r
+ size_t s = elements.size();\r
+ m_archive << boost::serialization::make_nvp("s", s);\r
+\r
+ for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)\r
+ {\r
+ serialization_save(*it, "v", m_archive);\r
+ }\r
+ }\r
+\r
+private:\r
+ Archive & m_archive;\r
+ unsigned int m_version;\r
+};\r
+\r
+}}}}}} // boost::geometry::index::detail::rtree::visitors\r
+\r
+// TODO - move to index/detail/rtree/load.hpp\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {\r
+\r
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>\r
+class load\r
+{\r
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;\r
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;\r
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;\r
+\r
+ typedef typename Options::parameters_type parameters_type;\r
+\r
+ typedef typename Allocators::node_pointer node_pointer;\r
+ typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;\r
+ typedef typename Allocators::size_type size_type;\r
+\r
+public:\r
+ template <typename Archive> inline static\r
+ node_pointer apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators)\r
+ {\r
+ values_count = 0;\r
+ return raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators);\r
+ }\r
+\r
+private:\r
+ template <typename Archive> inline static\r
+ node_pointer raw_apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators, size_type current_level = 0)\r
+ {\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(current_level <= leafs_level, "invalid parameter");\r
+\r
+ typedef typename rtree::elements_type<internal_node>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ //typedef typename elements_type::size_type elements_size;\r
+\r
+ // CONSIDER: change to elements_type::size_type or size_type\r
+ // or use fixed-size type like uint32 or even uint16?\r
+ size_t elements_count;\r
+ ar >> boost::serialization::make_nvp("s", elements_count);\r
+\r
+ if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )\r
+ BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));\r
+\r
+ if ( current_level < leafs_level )\r
+ {\r
+ node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)\r
+ subtree_destroyer auto_remover(n, allocators); \r
+ internal_node & in = rtree::get<internal_node>(*n);\r
+\r
+ elements_type & elements = rtree::elements(in);\r
+\r
+ elements.reserve(elements_count); // MAY THROW (A)\r
+\r
+ for ( size_t i = 0 ; i < elements_count ; ++i )\r
+ {\r
+ typedef typename elements_type::value_type::first_type box_type;\r
+ box_type b = serialization_load<box_type>("b", ar);\r
+ node_pointer n = raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators, current_level+1); // recursive call\r
+ elements.push_back(element_type(b, n));\r
+ }\r
+\r
+ auto_remover.release();\r
+ return n;\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");\r
+\r
+ node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)\r
+ subtree_destroyer auto_remover(n, allocators);\r
+ leaf & l = rtree::get<leaf>(*n);\r
+\r
+ typedef typename rtree::elements_type<leaf>::type elements_type;\r
+ typedef typename elements_type::value_type element_type;\r
+ elements_type & elements = rtree::elements(l);\r
+\r
+ values_count += elements_count;\r
+\r
+ elements.reserve(elements_count); // MAY THROW (A)\r
+\r
+ for ( size_t i = 0 ; i < elements_count ; ++i )\r
+ {\r
+ element_type el = serialization_load<element_type>("v", ar); // MAY THROW (C)\r
+ elements.push_back(el); // MAY THROW (C)\r
+ }\r
+\r
+ auto_remover.release();\r
+ return n;\r
+ }\r
+ }\r
+};\r
+\r
+}}}}} // boost::geometry::index::detail::rtree\r
+\r
+// TODO - move to index/detail/rtree/private_view.hpp\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {\r
+\r
+template <typename Rtree>\r
+class const_private_view\r
+{\r
+public:\r
+ typedef typename Rtree::size_type size_type;\r
+\r
+ typedef typename Rtree::translator_type translator_type;\r
+ typedef typename Rtree::value_type value_type;\r
+ typedef typename Rtree::options_type options_type;\r
+ typedef typename Rtree::box_type box_type;\r
+ typedef typename Rtree::allocators_type allocators_type; \r
+\r
+ const_private_view(Rtree const& rt) : m_rtree(rt) {}\r
+\r
+ typedef typename Rtree::members_holder members_holder;\r
+\r
+ members_holder const& members() const { return m_rtree.m_members; }\r
+\r
+private:\r
+ const_private_view(const_private_view const&);\r
+ const_private_view & operator=(const_private_view const&);\r
+\r
+ Rtree const& m_rtree;\r
+};\r
+\r
+template <typename Rtree>\r
+class private_view\r
+{\r
+public:\r
+ typedef typename Rtree::size_type size_type;\r
+\r
+ typedef typename Rtree::translator_type translator_type;\r
+ typedef typename Rtree::value_type value_type;\r
+ typedef typename Rtree::options_type options_type;\r
+ typedef typename Rtree::box_type box_type;\r
+ typedef typename Rtree::allocators_type allocators_type; \r
+\r
+ private_view(Rtree & rt) : m_rtree(rt) {}\r
+\r
+ typedef typename Rtree::members_holder members_holder;\r
+\r
+ members_holder & members() { return m_rtree.m_members; }\r
+ members_holder const& members() const { return m_rtree.m_members; }\r
+\r
+private:\r
+ private_view(private_view const&);\r
+ private_view & operator=(private_view const&);\r
+\r
+ Rtree & m_rtree;\r
+};\r
+\r
+}}}}} // namespace boost::geometry::index::detail::rtree\r
+\r
+// TODO - move to index/serialization/rtree.hpp\r
+namespace boost { namespace serialization {\r
+\r
+template<class Archive, typename V, typename P, typename I, typename E, typename A>\r
+void save(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)\r
+{\r
+ namespace detail = boost::geometry::index::detail;\r
+\r
+ typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;\r
+ typedef detail::rtree::const_private_view<rtree> view;\r
+ typedef typename view::translator_type translator_type;\r
+ typedef typename view::value_type value_type;\r
+ typedef typename view::options_type options_type;\r
+ typedef typename view::box_type box_type;\r
+ typedef typename view::allocators_type allocators_type;\r
+\r
+ view tree(rt);\r
+\r
+ detail::serialization_save(tree.members().parameters(), "parameters", ar);\r
+\r
+ ar << boost::serialization::make_nvp("values_count", tree.members().values_count);\r
+ ar << boost::serialization::make_nvp("leafs_level", tree.members().leafs_level);\r
+\r
+ if ( tree.members().values_count )\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(tree.members().root, "root shouldn't be null_ptr");\r
+\r
+ detail::rtree::visitors::save<Archive, value_type, options_type, translator_type, box_type, allocators_type> save_v(ar, version);\r
+ detail::rtree::apply_visitor(save_v, *tree.members().root);\r
+ }\r
+}\r
+\r
+template<class Archive, typename V, typename P, typename I, typename E, typename A>\r
+void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)\r
+{\r
+ namespace detail = boost::geometry::index::detail;\r
+\r
+ typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;\r
+ typedef detail::rtree::private_view<rtree> view;\r
+ typedef typename view::size_type size_type;\r
+ typedef typename view::translator_type translator_type;\r
+ typedef typename view::value_type value_type;\r
+ typedef typename view::options_type options_type;\r
+ typedef typename view::box_type box_type;\r
+ typedef typename view::allocators_type allocators_type;\r
+\r
+ typedef typename options_type::parameters_type parameters_type;\r
+ typedef typename allocators_type::node_pointer node_pointer;\r
+ typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;\r
+\r
+ view tree(rt);\r
+\r
+ parameters_type params = detail::serialization_load<parameters_type>("parameters", ar);\r
+\r
+ size_type values_count, leafs_level;\r
+ ar >> boost::serialization::make_nvp("values_count", values_count);\r
+ ar >> boost::serialization::make_nvp("leafs_level", leafs_level);\r
+\r
+ node_pointer n(0);\r
+ if ( 0 < values_count )\r
+ {\r
+ size_type loaded_values_count = 0;\r
+ n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>\r
+ ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW\r
+\r
+ subtree_destroyer remover(n, tree.members().allocators());\r
+ if ( loaded_values_count != values_count )\r
+ BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type\r
+ remover.release();\r
+ }\r
+\r
+ tree.members().parameters() = params;\r
+ tree.members().values_count = values_count;\r
+ tree.members().leafs_level = leafs_level;\r
+\r
+ subtree_destroyer remover(tree.members().root, tree.members().allocators());\r
+ tree.members().root = n;\r
+}\r
+\r
+template<class Archive, typename V, typename P, typename I, typename E, typename A> inline\r
+void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)\r
+{\r
+ split_free(ar, rt, version);\r
+}\r
+\r
+template<class Archive, typename V, typename P, typename I, typename E, typename A> inline\r
+void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)\r
+{\r
+ split_free(ar, rt, version);\r
+}\r
+\r
+}} // boost::serialization\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Tags used by the predicates checks implementation.\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TAGS_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_TAGS_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail {\r
+\r
+struct value_tag {};\r
+struct bounds_tag {};\r
+\r
+} // namespace detail\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_RTREE_TAGS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail {\r
+\r
+template <typename IndexableGetter, typename EqualTo>\r
+struct translator\r
+ : public IndexableGetter\r
+ , public EqualTo\r
+{\r
+ typedef typename IndexableGetter::result_type result_type;\r
+\r
+ translator(IndexableGetter const& i, EqualTo const& e)\r
+ : IndexableGetter(i), EqualTo(e)\r
+ {}\r
+\r
+ template <typename Value>\r
+ result_type operator()(Value const& value) const\r
+ {\r
+ return IndexableGetter::operator()(value);\r
+ }\r
+\r
+ template <typename Value>\r
+ bool equals(Value const& v1, Value const& v2) const\r
+ {\r
+ return EqualTo::operator()(v1, v2);\r
+ }\r
+};\r
+\r
+template <typename IndexableGetter>\r
+struct result_type\r
+{\r
+ typedef typename IndexableGetter::result_type type;\r
+};\r
+\r
+template <typename IndexableGetter>\r
+struct indexable_type\r
+{\r
+ typedef typename boost::remove_const<\r
+ typename boost::remove_reference<\r
+ typename result_type<IndexableGetter>::type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+} // namespace detail\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP\r
+\r
+#include <boost/tuple/tuple.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+// TODO move this to index/tuples and separate algorithms\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+namespace tuples {\r
+\r
+// find_index\r
+\r
+namespace detail {\r
+\r
+template <typename Tuple, typename El, size_t N>\r
+struct find_index;\r
+\r
+template <typename Tuple, typename El, size_t N, typename CurrentEl>\r
+struct find_index_impl\r
+{\r
+ static const size_t value = find_index<Tuple, El, N - 1>::value;\r
+};\r
+\r
+template <typename Tuple, typename El, size_t N>\r
+struct find_index_impl<Tuple, El, N, El>\r
+{\r
+ static const size_t value = N - 1;\r
+};\r
+\r
+template <typename Tuple, typename El, typename CurrentEl>\r
+struct find_index_impl<Tuple, El, 1, CurrentEl>\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ ELEMENT_NOT_FOUND,\r
+ (find_index_impl));\r
+};\r
+\r
+template <typename Tuple, typename El>\r
+struct find_index_impl<Tuple, El, 1, El>\r
+{\r
+ static const size_t value = 0;\r
+};\r
+\r
+template <typename Tuple, typename El, size_t N>\r
+struct find_index\r
+{\r
+ static const size_t value =\r
+ find_index_impl<\r
+ Tuple,\r
+ El,\r
+ N,\r
+ typename boost::tuples::element<N - 1, Tuple>::type\r
+ >::value;\r
+};\r
+\r
+} // namespace detail\r
+\r
+template <typename Tuple, typename El>\r
+struct find_index\r
+{\r
+ static const size_t value =\r
+ detail::find_index<\r
+ Tuple,\r
+ El,\r
+ boost::tuples::length<Tuple>::value\r
+ >::value;\r
+};\r
+\r
+// has\r
+\r
+namespace detail {\r
+\r
+template <typename Tuple, typename El, size_t N>\r
+struct has\r
+{\r
+ static const bool value\r
+ = boost::is_same<\r
+ typename boost::tuples::element<N - 1, Tuple>::type,\r
+ El\r
+ >::value\r
+ || has<Tuple, El, N - 1>::value;\r
+};\r
+\r
+template <typename Tuple, typename El>\r
+struct has<Tuple, El, 1>\r
+{\r
+ static const bool value\r
+ = boost::is_same<\r
+ typename boost::tuples::element<0, Tuple>::type,\r
+ El\r
+ >::value;\r
+};\r
+\r
+} // namespace detail\r
+\r
+template <typename Tuple, typename El>\r
+struct has\r
+{\r
+ static const bool value\r
+ = detail::has<\r
+ Tuple,\r
+ El,\r
+ boost::tuples::length<Tuple>::value\r
+ >::value;\r
+};\r
+\r
+// add\r
+\r
+template <typename Tuple, typename El>\r
+struct add\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (false),\r
+ NOT_IMPLEMENTED_FOR_THIS_TUPLE_TYPE,\r
+ (add));\r
+};\r
+\r
+template <typename T1, typename T>\r
+struct add<boost::tuple<T1>, T>\r
+{\r
+ typedef boost::tuple<T1, T> type;\r
+};\r
+\r
+template <typename T1, typename T2, typename T>\r
+struct add<boost::tuple<T1, T2>, T>\r
+{\r
+ typedef boost::tuple<T1, T2, T> type;\r
+};\r
+\r
+// add_if\r
+\r
+template <typename Tuple, typename El, bool Cond>\r
+struct add_if\r
+{\r
+ typedef Tuple type;\r
+};\r
+\r
+template <typename Tuple, typename El>\r
+struct add_if<Tuple, El, true>\r
+{\r
+ typedef typename add<Tuple, El>::type type;\r
+};\r
+\r
+// add_unique\r
+\r
+template <typename Tuple, typename El>\r
+struct add_unique\r
+{\r
+ typedef typename add_if<\r
+ Tuple,\r
+ El,\r
+ !has<Tuple, El>::value\r
+ >::type type;\r
+};\r
+\r
+template <typename Tuple,\r
+ typename T,\r
+ size_t I = 0,\r
+ size_t N = boost::tuples::length<Tuple>::value>\r
+struct push_back\r
+{\r
+ typedef\r
+ boost::tuples::cons<\r
+ typename boost::tuples::element<I, Tuple>::type,\r
+ typename push_back<Tuple, T, I+1, N>::type\r
+ > type;\r
+\r
+ static type apply(Tuple const& tup, T const& t)\r
+ {\r
+ return\r
+ type(\r
+ boost::get<I>(tup),\r
+ push_back<Tuple, T, I+1, N>::apply(tup, t)\r
+ );\r
+ }\r
+};\r
+\r
+template <typename Tuple, typename T, size_t N>\r
+struct push_back<Tuple, T, N, N>\r
+{\r
+ typedef boost::tuples::cons<T, boost::tuples::null_type> type;\r
+\r
+ static type apply(Tuple const&, T const& t)\r
+ {\r
+ return type(t, boost::tuples::null_type());\r
+ }\r
+};\r
+\r
+} // namespace tuples\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_TAGS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#include <boost/swap.hpp>\r
+//#include <boost/type_traits/is_empty.hpp>\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template<class T>\r
+static inline void assign_cond(T & l, T const& r, boost::mpl::bool_<true> const&)\r
+{\r
+ l = r;\r
+}\r
+\r
+template<class T>\r
+static inline void assign_cond(T &, T const&, boost::mpl::bool_<false> const&) {}\r
+\r
+template<class T>\r
+static inline void move_cond(T & l, T & r, boost::mpl::bool_<true> const&)\r
+{\r
+ l = ::boost::move(r);\r
+}\r
+\r
+template<class T>\r
+static inline void move_cond(T &, T &, boost::mpl::bool_<false> const&) {}\r
+\r
+template <typename T> inline\r
+void swap_cond(T & l, T & r, boost::mpl::bool_<true> const&)\r
+{\r
+ ::boost::swap(l, r);\r
+}\r
+\r
+template <typename T> inline\r
+void swap_cond(T &, T &, boost::mpl::bool_<false> const&) {}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP\r
--- /dev/null
+// Boost.Container varray\r
+//\r
+// Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland.\r
+// Copyright (c) 2011-2013 Andrew Hundt.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP\r
+\r
+// TODO - REMOVE/CHANGE\r
+#include <boost/container/detail/config_begin.hpp>\r
+#include <boost/container/detail/workaround.hpp>\r
+\r
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+#include <boost/move/detail/fwd_macros.hpp>\r
+#endif\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/swap.hpp>\r
+#include <boost/integer.hpp>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/type_traits/is_unsigned.hpp>\r
+#include <boost/type_traits/alignment_of.hpp>\r
+#include <boost/type_traits/aligned_storage.hpp>\r
+\r
+// TODO - use std::reverse_iterator and std::iterator_traits\r
+// instead Boost.Iterator to remove dependency?\r
+// or boost/detail/iterator.hpp ?\r
+#include <boost/iterator/reverse_iterator.hpp>\r
+#include <boost/iterator/iterator_concepts.hpp>\r
+\r
+#include <boost/geometry/index/detail/assert.hpp>\r
+#include <boost/geometry/index/detail/exception.hpp>\r
+\r
+#include <boost/geometry/index/detail/varray_detail.hpp>\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+/*!\r
+\defgroup varray_non_member varray non-member functions\r
+*/\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+ \r
+namespace varray_detail {\r
+\r
+template <typename Value, std::size_t Capacity>\r
+struct varray_traits\r
+{\r
+ typedef Value value_type;\r
+ typedef std::size_t size_type;\r
+ typedef std::ptrdiff_t difference_type;\r
+ typedef Value * pointer;\r
+ typedef const Value * const_pointer;\r
+ typedef Value & reference;\r
+ typedef const Value & const_reference;\r
+\r
+ typedef boost::false_type use_memop_in_swap_and_move;\r
+ typedef boost::false_type use_optimized_swap;\r
+ typedef boost::false_type disable_trivial_init;\r
+};\r
+\r
+template <typename Varray>\r
+struct checker\r
+{\r
+ typedef typename Varray::size_type size_type;\r
+ typedef typename Varray::const_iterator const_iterator;\r
+\r
+ static inline void check_capacity(Varray const& v, size_type s)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(s <= v.capacity(), "size too big");\r
+\r
+ ::boost::ignore_unused_variable_warning(v);\r
+ ::boost::ignore_unused_variable_warning(s);\r
+ }\r
+\r
+ static inline void throw_out_of_bounds(Varray const& v, size_type i)\r
+ {\r
+ if ( v.size() <= i )\r
+ throw_out_of_range("index out of bounds");\r
+\r
+ ::boost::ignore_unused_variable_warning(v);\r
+ ::boost::ignore_unused_variable_warning(i);\r
+ }\r
+\r
+ static inline void check_index(Varray const& v, size_type i)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(i < v.size(), "index out of bounds");\r
+\r
+ ::boost::ignore_unused_variable_warning(v);\r
+ ::boost::ignore_unused_variable_warning(i);\r
+ }\r
+\r
+ static inline void check_not_empty(Varray const& v)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(!v.empty(), "the container is empty");\r
+ \r
+ ::boost::ignore_unused_variable_warning(v);\r
+ }\r
+\r
+ static inline void check_iterator_end_neq(Varray const& v, const_iterator position)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(v.begin() <= position && position < v.end(), "iterator out of bounds");\r
+\r
+ ::boost::ignore_unused_variable_warning(v);\r
+ ::boost::ignore_unused_variable_warning(position);\r
+ }\r
+\r
+ static inline void check_iterator_end_eq(Varray const& v, const_iterator position)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(v.begin() <= position && position <= v.end(), "iterator out of bounds");\r
+\r
+ ::boost::ignore_unused_variable_warning(v);\r
+ ::boost::ignore_unused_variable_warning(position);\r
+ }\r
+};\r
+\r
+} // namespace varray_detail\r
+\r
+/*!\r
+\brief A variable-size array container with fixed capacity.\r
+\r
+varray is a sequence container like boost::container::vector with contiguous storage that can\r
+change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.\r
+\r
+A varray is a sequence that supports random access to elements, constant time insertion and\r
+removal of elements at the end, and linear time insertion and removal of elements at the beginning or \r
+in the middle. The number of elements in a varray may vary dynamically up to a fixed capacity\r
+because elements are stored within the object itself similarly to an array. However, objects are \r
+initialized as they are inserted into varray unlike C arrays or std::array which must construct\r
+all elements on instantiation. The behavior of varray enables the use of statically allocated\r
+elements in cases with complex object lifetime requirements that would otherwise not be trivially \r
+possible.\r
+\r
+\par Error Handling\r
+ Insertion beyond the capacity and out of bounds errors result in undefined behavior unless\r
+ otherwise specified. In this respect if size() == capacity(), then varray::push_back()\r
+ behaves like std::vector pop_front() if size() == empty(). The reason for this difference\r
+ is because unlike vectors, varray does not perform allocation.\r
+\r
+\par Advanced Usage\r
+ Error handling behavior can be modified to more closely match std::vector exception behavior\r
+ when exceeding bounds by providing an alternate Strategy and varray_traits instantiation.\r
+\r
+\tparam Value The type of element that will be stored.\r
+\tparam Capacity The maximum number of elements varray can store, fixed at compile time.\r
+\tparam Strategy Defines the public typedefs and error handlers,\r
+ implements StaticVectorStrategy and has some similarities\r
+ to an Allocator.\r
+*/\r
+template <typename Value, std::size_t Capacity>\r
+class varray\r
+{\r
+ typedef varray_detail::varray_traits<Value, Capacity> vt;\r
+ typedef varray_detail::checker<varray> errh;\r
+\r
+ BOOST_MPL_ASSERT_MSG(\r
+ ( boost::is_unsigned<typename vt::size_type>::value &&\r
+ sizeof(typename boost::uint_value_t<Capacity>::least) <= sizeof(typename vt::size_type) ),\r
+ SIZE_TYPE_IS_TOO_SMALL_FOR_SPECIFIED_CAPACITY,\r
+ (varray)\r
+ );\r
+\r
+ typedef boost::aligned_storage<\r
+ sizeof(Value[Capacity]),\r
+ boost::alignment_of<Value[Capacity]>::value\r
+ > aligned_storage_type;\r
+\r
+ template <typename V, std::size_t C>\r
+ friend class varray;\r
+\r
+ BOOST_COPYABLE_AND_MOVABLE(varray)\r
+\r
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+public:\r
+ template <std::size_t C>\r
+ varray & operator=(varray<Value, C> & sv)\r
+ {\r
+ typedef varray<Value, C> other;\r
+ this->operator=(static_cast<const ::boost::rv<other> &>(const_cast<const other &>(sv)));\r
+ return *this;\r
+ }\r
+#endif\r
+\r
+public:\r
+ //! @brief The type of elements stored in the container.\r
+ typedef typename vt::value_type value_type;\r
+ //! @brief The unsigned integral type used by the container.\r
+ typedef typename vt::size_type size_type;\r
+ //! @brief The pointers difference type.\r
+ typedef typename vt::difference_type difference_type;\r
+ //! @brief The pointer type.\r
+ typedef typename vt::pointer pointer;\r
+ //! @brief The const pointer type.\r
+ typedef typename vt::const_pointer const_pointer;\r
+ //! @brief The value reference type.\r
+ typedef typename vt::reference reference;\r
+ //! @brief The value const reference type.\r
+ typedef typename vt::const_reference const_reference;\r
+\r
+ //! @brief The iterator type.\r
+ typedef pointer iterator;\r
+ //! @brief The const iterator type.\r
+ typedef const_pointer const_iterator;\r
+ //! @brief The reverse iterator type.\r
+ typedef boost::reverse_iterator<iterator> reverse_iterator;\r
+ //! @brief The const reverse iterator.\r
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;\r
+\r
+ //! @brief Constructs an empty varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ varray()\r
+ : m_size(0)\r
+ {}\r
+\r
+ //! @pre <tt>count <= capacity()</tt>\r
+ //!\r
+ //! @brief Constructs a varray containing count default constructed Values.\r
+ //!\r
+ //! @param count The number of values which will be contained in the container.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's default constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ explicit varray(size_type count)\r
+ : m_size(0)\r
+ {\r
+ this->resize(count); // may throw\r
+ }\r
+\r
+ //! @pre <tt>count <= capacity()</tt>\r
+ //!\r
+ //! @brief Constructs a varray containing count copies of value.\r
+ //!\r
+ //! @param count The number of copies of a values that will be contained in the container.\r
+ //! @param value The value which will be used to copy construct values.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ varray(size_type count, value_type const& value)\r
+ : m_size(0)\r
+ {\r
+ this->resize(count, value); // may throw\r
+ }\r
+\r
+ //! @pre\r
+ //! @li <tt>distance(first, last) <= capacity()</tt>\r
+ //! @li Iterator must meet the \c ForwardTraversalIterator concept.\r
+ //!\r
+ //! @brief Constructs a varray containing copy of a range <tt>[first, last)</tt>.\r
+ //!\r
+ //! @param first The iterator to the first element in range.\r
+ //! @param last The iterator to the one after the last element in range.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's constructor taking a dereferenced Iterator throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <typename Iterator>\r
+ varray(Iterator first, Iterator last)\r
+ : m_size(0)\r
+ {\r
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator\r
+ \r
+ this->assign(first, last); // may throw\r
+ }\r
+\r
+ //! @brief Constructs a copy of other varray.\r
+ //!\r
+ //! @param other The varray which content will be copied to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor throws.\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ varray(varray const& other)\r
+ : m_size(other.size())\r
+ {\r
+ namespace sv = varray_detail;\r
+ sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw\r
+ }\r
+\r
+ //! @pre <tt>other.size() <= capacity()</tt>.\r
+ //!\r
+ //! @brief Constructs a copy of other varray.\r
+ //!\r
+ //! @param other The varray which content will be copied to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <std::size_t C>\r
+ varray(varray<value_type, C> const& other)\r
+ : m_size(other.size())\r
+ {\r
+ errh::check_capacity(*this, other.size()); // may throw\r
+ \r
+ namespace sv = varray_detail;\r
+ sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw\r
+ }\r
+\r
+ //! @brief Copy assigns Values stored in the other varray to this one.\r
+ //!\r
+ //! @param other The varray which content will be copied to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor or copy assignment throws.\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)\r
+ {\r
+ this->assign(other.begin(), other.end()); // may throw\r
+\r
+ return *this;\r
+ }\r
+\r
+ //! @pre <tt>other.size() <= capacity()</tt>\r
+ //!\r
+ //! @brief Copy assigns Values stored in the other varray to this one.\r
+ //!\r
+ //! @param other The varray which content will be copied to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor or copy assignment throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <std::size_t C>\r
+ varray & operator=(BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(varray, value_type, C) other)\r
+ {\r
+ this->assign(other.begin(), other.end()); // may throw\r
+\r
+ return *this;\r
+ }\r
+\r
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.\r
+ //!\r
+ //! @param other The varray which content will be moved to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.\r
+ //! @internal\r
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ varray(BOOST_RV_REF(varray) other)\r
+ {\r
+ typedef typename\r
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;\r
+\r
+ this->move_ctor_dispatch(other, use_memop_in_swap_and_move());\r
+ }\r
+\r
+ //! @pre <tt>other.size() <= capacity()</tt>\r
+ //!\r
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.\r
+ //!\r
+ //! @param other The varray which content will be moved to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.\r
+ //! @internal\r
+ //! @li It throws only if \c use_memop_in_swap_and_move is false_type - default.\r
+ //! @endinternal\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <std::size_t C>\r
+ varray(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)\r
+ : m_size(other.m_size)\r
+ {\r
+ errh::check_capacity(*this, other.size()); // may throw\r
+\r
+ typedef typename\r
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;\r
+\r
+ this->move_ctor_dispatch(other, use_memop_in_swap_and_move());\r
+ }\r
+\r
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.\r
+ //!\r
+ //! @param other The varray which content will be moved to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.\r
+ //! @internal\r
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ varray & operator=(BOOST_RV_REF(varray) other)\r
+ {\r
+ if ( &other == this )\r
+ return *this;\r
+\r
+ typedef typename\r
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;\r
+\r
+ this->move_assign_dispatch(other, use_memop_in_swap_and_move());\r
+\r
+ return *this;\r
+ }\r
+\r
+ //! @pre <tt>other.size() <= capacity()</tt>\r
+ //!\r
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.\r
+ //!\r
+ //! @param other The varray which content will be moved to this one.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.\r
+ //! @internal\r
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.\r
+ //! @endinternal\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <std::size_t C>\r
+ varray & operator=(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)\r
+ {\r
+ errh::check_capacity(*this, other.size()); // may throw\r
+\r
+ typedef typename\r
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;\r
+\r
+ this->move_assign_dispatch(other, use_memop_in_swap_and_move());\r
+\r
+ return *this;\r
+ }\r
+\r
+ //! @brief Destructor. Destroys Values stored in this container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ ~varray()\r
+ {\r
+ namespace sv = varray_detail;\r
+ sv::destroy(this->begin(), this->end());\r
+ }\r
+\r
+ //! @brief Swaps contents of the other varray and this one.\r
+ //!\r
+ //! @param other The varray which content will be swapped with this one's content.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,\r
+ //! @internal\r
+ //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ void swap(varray & other)\r
+ {\r
+ typedef typename\r
+ vt::use_optimized_swap use_optimized_swap;\r
+\r
+ this->swap_dispatch(other, use_optimized_swap());\r
+ }\r
+\r
+ //! @pre <tt>other.size() <= capacity() && size() <= other.capacity()</tt>\r
+ //!\r
+ //! @brief Swaps contents of the other varray and this one.\r
+ //!\r
+ //! @param other The varray which content will be swapped with this one's content.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,\r
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,\r
+ //! @internal\r
+ //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.\r
+ //! @endinternal\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <std::size_t C>\r
+ void swap(varray<value_type, C> & other)\r
+ {\r
+ errh::check_capacity(*this, other.size());\r
+ errh::check_capacity(other, this->size());\r
+\r
+ typedef typename\r
+ vt::use_optimized_swap use_optimized_swap;\r
+\r
+ this->swap_dispatch(other, use_optimized_swap()); \r
+ }\r
+\r
+ //! @pre <tt>count <= capacity()</tt>\r
+ //!\r
+ //! @brief Inserts or erases elements at the end such that\r
+ //! the size becomes count. New elements are default constructed.\r
+ //!\r
+ //! @param count The number of elements which will be stored in the container.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's default constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ void resize(size_type count)\r
+ {\r
+ namespace sv = varray_detail;\r
+ typedef typename vt::disable_trivial_init dti;\r
+\r
+ if ( count < m_size )\r
+ {\r
+ sv::destroy(this->begin() + count, this->end());\r
+ }\r
+ else\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+\r
+ sv::uninitialized_fill(this->end(), this->begin() + count, dti()); // may throw\r
+ }\r
+ m_size = count; // update end\r
+ }\r
+\r
+ //! @pre <tt>count <= capacity()</tt>\r
+ //!\r
+ //! @brief Inserts or erases elements at the end such that\r
+ //! the size becomes count. New elements are copy constructed from value.\r
+ //!\r
+ //! @param count The number of elements which will be stored in the container.\r
+ //! @param value The value used to copy construct the new element.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ void resize(size_type count, value_type const& value)\r
+ {\r
+ if ( count < m_size )\r
+ {\r
+ namespace sv = varray_detail;\r
+ sv::destroy(this->begin() + count, this->end());\r
+ }\r
+ else\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ \r
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw\r
+ }\r
+ m_size = count; // update end\r
+ }\r
+\r
+ //! @pre <tt>count <= capacity()</tt>\r
+ //!\r
+ //! @brief This call has no effect because the Capacity of this container is constant.\r
+ //!\r
+ //! @param count The number of elements which the container should be able to contain.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ void reserve(size_type count)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ //! @pre <tt>size() < capacity()</tt>\r
+ //!\r
+ //! @brief Adds a copy of value at the end.\r
+ //!\r
+ //! @param value The value used to copy construct the new element.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ void push_back(value_type const& value)\r
+ {\r
+ typedef typename vt::disable_trivial_init dti;\r
+\r
+ errh::check_capacity(*this, m_size + 1); // may throw\r
+ \r
+ namespace sv = varray_detail;\r
+ sv::construct(dti(), this->end(), value); // may throw\r
+ ++m_size; // update end\r
+ }\r
+\r
+ //! @pre <tt>size() < capacity()</tt>\r
+ //!\r
+ //! @brief Moves value to the end.\r
+ //!\r
+ //! @param value The value to move construct the new element.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's move constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ void push_back(BOOST_RV_REF(value_type) value)\r
+ {\r
+ typedef typename vt::disable_trivial_init dti;\r
+\r
+ errh::check_capacity(*this, m_size + 1); // may throw\r
+\r
+ namespace sv = varray_detail;\r
+ sv::construct(dti(), this->end(), ::boost::move(value)); // may throw\r
+ ++m_size; // update end\r
+ }\r
+\r
+ //! @pre <tt>!empty()</tt>\r
+ //!\r
+ //! @brief Destroys last value and decreases the size.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ void pop_back()\r
+ {\r
+ errh::check_not_empty(*this);\r
+\r
+ namespace sv = varray_detail;\r
+ sv::destroy(this->end() - 1);\r
+ --m_size; // update end\r
+ }\r
+\r
+ //! @pre\r
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.\r
+ //! @li <tt>size() < capacity()</tt>\r
+ //!\r
+ //! @brief Inserts a copy of element at position.\r
+ //!\r
+ //! @param position The position at which the new value will be inserted.\r
+ //! @param value The value used to copy construct the new element.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If Value's copy constructor or copy assignment throws\r
+ //! @li If Value's move constructor or move assignment throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant or linear.\r
+ iterator insert(iterator position, value_type const& value)\r
+ {\r
+ typedef typename vt::disable_trivial_init dti;\r
+ namespace sv = varray_detail;\r
+\r
+ errh::check_iterator_end_eq(*this, position);\r
+ errh::check_capacity(*this, m_size + 1); // may throw\r
+\r
+ if ( position == this->end() )\r
+ {\r
+ sv::construct(dti(), position, value); // may throw\r
+ ++m_size; // update end\r
+ }\r
+ else\r
+ {\r
+ // TODO - should move be used only if it's nonthrowing?\r
+ value_type & r = *(this->end() - 1);\r
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw\r
+ ++m_size; // update end\r
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw\r
+ sv::assign(position, value); // may throw\r
+ }\r
+\r
+ return position;\r
+ }\r
+\r
+ //! @pre\r
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.\r
+ //! @li <tt>size() < capacity()</tt>\r
+ //!\r
+ //! @brief Inserts a move-constructed element at position.\r
+ //!\r
+ //! @param position The position at which the new value will be inserted.\r
+ //! @param value The value used to move construct the new element.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's move constructor or move assignment throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant or linear.\r
+ iterator insert(iterator position, BOOST_RV_REF(value_type) value)\r
+ {\r
+ typedef typename vt::disable_trivial_init dti;\r
+ namespace sv = varray_detail;\r
+\r
+ errh::check_iterator_end_eq(*this, position);\r
+ errh::check_capacity(*this, m_size + 1); // may throw\r
+\r
+ if ( position == this->end() )\r
+ {\r
+ sv::construct(dti(), position, boost::move(value)); // may throw\r
+ ++m_size; // update end\r
+ }\r
+ else\r
+ {\r
+ // TODO - should move be used only if it's nonthrowing?\r
+ value_type & r = *(this->end() - 1);\r
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw\r
+ ++m_size; // update end\r
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw\r
+ sv::assign(position, boost::move(value)); // may throw\r
+ }\r
+\r
+ return position;\r
+ }\r
+\r
+ //! @pre\r
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.\r
+ //! @li <tt>size() + count <= capacity()</tt>\r
+ //!\r
+ //! @brief Inserts a count copies of value at position.\r
+ //!\r
+ //! @param position The position at which new elements will be inserted.\r
+ //! @param count The number of new elements which will be inserted.\r
+ //! @param value The value used to copy construct new elements.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If Value's copy constructor or copy assignment throws.\r
+ //! @li If Value's move constructor or move assignment throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ iterator insert(iterator position, size_type count, value_type const& value)\r
+ {\r
+ errh::check_iterator_end_eq(*this, position);\r
+ errh::check_capacity(*this, m_size + count); // may throw\r
+\r
+ if ( position == this->end() )\r
+ {\r
+ std::uninitialized_fill(position, position + count, value); // may throw\r
+ m_size += count; // update end\r
+ }\r
+ else\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ difference_type to_move = std::distance(position, this->end());\r
+ \r
+ // TODO - should following lines check for exception and revert to the old size?\r
+\r
+ if ( count < static_cast<size_type>(to_move) )\r
+ {\r
+ sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw\r
+ m_size += count; // update end\r
+ sv::move_backward(position, position + to_move - count, this->end() - count); // may throw\r
+ std::fill_n(position, count, value); // may throw\r
+ }\r
+ else\r
+ {\r
+ std::uninitialized_fill(this->end(), position + count, value); // may throw\r
+ m_size += count - to_move; // update end\r
+ sv::uninitialized_move(position, position + to_move, position + count); // may throw\r
+ m_size += to_move; // update end\r
+ std::fill_n(position, to_move, value); // may throw\r
+ }\r
+ }\r
+\r
+ return position;\r
+ }\r
+\r
+ //! @pre\r
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.\r
+ //! @li <tt>distance(first, last) <= capacity()</tt>\r
+ //! @li \c Iterator must meet the \c ForwardTraversalIterator concept.\r
+ //!\r
+ //! @brief Inserts a copy of a range <tt>[first, last)</tt> at position.\r
+ //!\r
+ //! @param position The position at which new elements will be inserted.\r
+ //! @param first The iterator to the first element of a range used to construct new elements.\r
+ //! @param last The iterator to the one after the last element of a range used to construct new elements.\r
+ //!\r
+ //! @par Throws\r
+ //! @li If Value's constructor and assignment taking a dereferenced \c Iterator.\r
+ //! @li If Value's move constructor or move assignment throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <typename Iterator>\r
+ iterator insert(iterator position, Iterator first, Iterator last)\r
+ {\r
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator\r
+\r
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;\r
+ this->insert_dispatch(position, first, last, traversal());\r
+\r
+ return position;\r
+ }\r
+\r
+ //! @pre \c position must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>\r
+ //!\r
+ //! @brief Erases Value from position.\r
+ //!\r
+ //! @param position The position of the element which will be erased from the container.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's move assignment throws.\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ iterator erase(iterator position)\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ errh::check_iterator_end_neq(*this, position);\r
+\r
+ //TODO - add empty check?\r
+ //errh::check_empty(*this);\r
+\r
+ sv::move(position + 1, this->end(), position); // may throw\r
+ sv::destroy(this->end() - 1);\r
+ --m_size;\r
+\r
+ return position;\r
+ }\r
+\r
+ //! @pre\r
+ //! @li \c first and \c last must define a valid range\r
+ //! @li iterators must be in range <tt>[begin(), end()]</tt>\r
+ //!\r
+ //! @brief Erases Values from a range <tt>[first, last)</tt>.\r
+ //!\r
+ //! @param first The position of the first element of a range which will be erased from the container.\r
+ //! @param last The position of the one after the last element of a range which will be erased from the container.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's move assignment throws.\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ iterator erase(iterator first, iterator last)\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ errh::check_iterator_end_eq(*this, first);\r
+ errh::check_iterator_end_eq(*this, last);\r
+ \r
+ difference_type n = std::distance(first, last);\r
+ \r
+ //TODO - add invalid range check?\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 <= n, "invalid range");\r
+ //TODO - add this->size() check?\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(n <= this->size(), "invalid range");\r
+\r
+ sv::move(last, this->end(), first); // may throw\r
+ sv::destroy(this->end() - n, this->end());\r
+ m_size -= n;\r
+\r
+ return first;\r
+ }\r
+\r
+ //! @pre <tt>distance(first, last) <= capacity()</tt>\r
+ //!\r
+ //! @brief Assigns a range <tt>[first, last)</tt> of Values to this container.\r
+ //!\r
+ //! @param first The iterator to the first element of a range used to construct new content of this container.\r
+ //! @param last The iterator to the one after the last element of a range used to construct new content of this container.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor or copy assignment throws,\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ template <typename Iterator>\r
+ void assign(Iterator first, Iterator last)\r
+ {\r
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator\r
+\r
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;\r
+ this->assign_dispatch(first, last, traversal()); // may throw\r
+ }\r
+\r
+ //! @pre <tt>count <= capacity()</tt>\r
+ //!\r
+ //! @brief Assigns a count copies of value to this container.\r
+ //!\r
+ //! @param count The new number of elements which will be container in the container.\r
+ //! @param value The value which will be used to copy construct the new content.\r
+ //!\r
+ //! @par Throws\r
+ //! If Value's copy constructor or copy assignment throws.\r
+ //!\r
+ //! @par Complexity\r
+ //! Linear O(N).\r
+ void assign(size_type count, value_type const& value)\r
+ {\r
+ if ( count < m_size )\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ std::fill_n(this->begin(), count, value); // may throw\r
+ sv::destroy(this->begin() + count, this->end());\r
+ }\r
+ else\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+\r
+ std::fill_n(this->begin(), m_size, value); // may throw\r
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw\r
+ }\r
+ m_size = count; // update end\r
+ }\r
+\r
+#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)\r
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)\r
+ //! @pre <tt>size() < capacity()</tt>\r
+ //!\r
+ //! @brief Inserts a Value constructed with\r
+ //! \c std::forward<Args>(args)... in the end of the container.\r
+ //!\r
+ //! @param args The arguments of the constructor of the new element which will be created at the end of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! If in-place constructor throws or Value's move constructor throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ template<class ...Args>\r
+ void emplace_back(BOOST_FWD_REF(Args) ...args)\r
+ {\r
+ typedef typename vt::disable_trivial_init dti;\r
+\r
+ errh::check_capacity(*this, m_size + 1); // may throw\r
+\r
+ namespace sv = varray_detail;\r
+ sv::construct(dti(), this->end(), ::boost::forward<Args>(args)...); // may throw\r
+ ++m_size; // update end\r
+ }\r
+\r
+ //! @pre\r
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>\r
+ //! @li <tt>size() < capacity()</tt>\r
+ //!\r
+ //! @brief Inserts a Value constructed with\r
+ //! \c std::forward<Args>(args)... before position\r
+ //!\r
+ //! @param position The position at which new elements will be inserted.\r
+ //! @param args The arguments of the constructor of the new element.\r
+ //!\r
+ //! @par Throws\r
+ //! If in-place constructor throws or if Value's move constructor or move assignment throws.\r
+ //! @internal\r
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).\r
+ //! @endinternal\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant or linear.\r
+ template<class ...Args>\r
+ iterator emplace(iterator position, BOOST_FWD_REF(Args) ...args)\r
+ {\r
+ typedef typename vt::disable_trivial_init dti;\r
+\r
+ namespace sv = varray_detail;\r
+\r
+ errh::check_iterator_end_eq(*this, position);\r
+ errh::check_capacity(*this, m_size + 1); // may throw\r
+\r
+ if ( position == this->end() )\r
+ {\r
+ sv::construct(dti(), position, ::boost::forward<Args>(args)...); // may throw\r
+ ++m_size; // update end\r
+ }\r
+ else\r
+ {\r
+ // TODO - should following lines check for exception and revert to the old size?\r
+\r
+ // TODO - should move be used only if it's nonthrowing?\r
+ value_type & r = *(this->end() - 1);\r
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw\r
+ ++m_size; // update end\r
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw\r
+\r
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage;\r
+ value_type * val_p = static_cast<value_type *>(temp_storage.address());\r
+ sv::construct(dti(), val_p, ::boost::forward<Args>(args)...); // may throw\r
+ sv::scoped_destructor<value_type> d(val_p);\r
+ sv::assign(position, ::boost::move(*val_p)); // may throw\r
+ }\r
+\r
+ return position;\r
+ }\r
+\r
+#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)\r
+\r
+ #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE(N) \\r
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \\r
+ void emplace_back(BOOST_MOVE_UREF##N) \\r
+ { \\r
+ typedef typename vt::disable_trivial_init dti; \\r
+ \\r
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\\r
+ \\r
+ namespace sv = varray_detail; \\r
+ sv::construct(dti(), this->end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\\r
+ ++m_size; /*update end*/ \\r
+ } \\r
+ \\r
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \\r
+ iterator emplace(iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \\r
+ { \\r
+ typedef typename vt::disable_trivial_init dti; \\r
+ namespace sv = varray_detail; \\r
+ \\r
+ errh::check_iterator_end_eq(*this, position); \\r
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\\r
+ \\r
+ if ( position == this->end() ) \\r
+ { \\r
+ sv::construct(dti(), position BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\\r
+ ++m_size; /*update end*/ \\r
+ } \\r
+ else \\r
+ { \\r
+ /* TODO - should following lines check for exception and revert to the old size? */ \\r
+ /* TODO - should move be used only if it's nonthrowing? */ \\r
+ \\r
+ value_type & r = *(this->end() - 1); \\r
+ sv::construct(dti(), this->end(), boost::move(r)); /*may throw*/\\r
+ ++m_size; /*update end*/ \\r
+ sv::move_backward(position, this->end() - 2, this->end() - 1); /*may throw*/\\r
+ \\r
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage; \\r
+ value_type * val_p = static_cast<value_type *>(temp_storage.address()); \\r
+ sv::construct(dti(), val_p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\\r
+ sv::scoped_destructor<value_type> d(val_p); \\r
+ sv::assign(position, ::boost::move(*val_p)); /*may throw*/\\r
+ } \\r
+ \\r
+ return position; \\r
+ } \\r
+ \r
+ BOOST_MOVE_ITERATE_0TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE)\r
+ #undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE\r
+\r
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)\r
+#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE\r
+\r
+ //! @brief Removes all elements from the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ void clear()\r
+ {\r
+ namespace sv = varray_detail;\r
+ sv::destroy(this->begin(), this->end());\r
+ m_size = 0; // update end\r
+ }\r
+\r
+ //! @pre <tt>i < size()</tt>\r
+ //!\r
+ //! @brief Returns reference to the i-th element.\r
+ //!\r
+ //! @param i The element's index.\r
+ //!\r
+ //! @return reference to the i-th element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! \c std::out_of_range exception by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ reference at(size_type i)\r
+ {\r
+ errh::throw_out_of_bounds(*this, i); // may throw\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ //! @pre <tt>i < size()</tt>\r
+ //!\r
+ //! @brief Returns const reference to the i-th element.\r
+ //!\r
+ //! @param i The element's index.\r
+ //!\r
+ //! @return const reference to the i-th element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! \c std::out_of_range exception by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reference at(size_type i) const\r
+ {\r
+ errh::throw_out_of_bounds(*this, i); // may throw\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ //! @pre <tt>i < size()</tt>\r
+ //!\r
+ //! @brief Returns reference to the i-th element.\r
+ //!\r
+ //! @param i The element's index.\r
+ //!\r
+ //! @return reference to the i-th element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ reference operator[](size_type i)\r
+ {\r
+ // TODO: Remove bounds check? std::vector and std::array operator[] don't check.\r
+ errh::check_index(*this, i);\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ //! @pre <tt>i < size()</tt>\r
+ //!\r
+ //! @brief Returns const reference to the i-th element.\r
+ //!\r
+ //! @param i The element's index.\r
+ //!\r
+ //! @return const reference to the i-th element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reference operator[](size_type i) const\r
+ {\r
+ errh::check_index(*this, i);\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ //! @pre \c !empty()\r
+ //!\r
+ //! @brief Returns reference to the first element.\r
+ //!\r
+ //! @return reference to the first element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ reference front()\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->begin());\r
+ }\r
+\r
+ //! @pre \c !empty()\r
+ //!\r
+ //! @brief Returns const reference to the first element.\r
+ //!\r
+ //! @return const reference to the first element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reference front() const\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->begin());\r
+ }\r
+\r
+ //! @pre \c !empty()\r
+ //!\r
+ //! @brief Returns reference to the last element.\r
+ //!\r
+ //! @return reference to the last element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ reference back()\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->end() - 1);\r
+ }\r
+\r
+ //! @pre \c !empty()\r
+ //!\r
+ //! @brief Returns const reference to the first element.\r
+ //!\r
+ //! @return const reference to the last element\r
+ //! from the beginning of the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing by default.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reference back() const\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->end() - 1);\r
+ }\r
+\r
+ //! @brief Pointer such that <tt>[data(), data() + size())</tt> is a valid range.\r
+ //! For a non-empty vector <tt>data() == &front()</tt>.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ Value * data()\r
+ {\r
+ return boost::addressof(*(this->ptr()));\r
+ }\r
+\r
+ //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.\r
+ //! For a non-empty vector <tt>data() == &front()</tt>.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const Value * data() const\r
+ {\r
+ return boost::addressof(*(this->ptr()));\r
+ }\r
+\r
+ \r
+ //! @brief Returns iterator to the first element.\r
+ //!\r
+ //! @return iterator to the first element contained in the vector.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ iterator begin() { return this->ptr(); }\r
+\r
+ //! @brief Returns const iterator to the first element.\r
+ //!\r
+ //! @return const_iterator to the first element contained in the vector.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_iterator begin() const { return this->ptr(); }\r
+\r
+ //! @brief Returns const iterator to the first element.\r
+ //!\r
+ //! @return const_iterator to the first element contained in the vector.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_iterator cbegin() const { return this->ptr(); }\r
+\r
+ //! @brief Returns iterator to the one after the last element.\r
+ //!\r
+ //! @return iterator pointing to the one after the last element contained in the vector.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ iterator end() { return this->begin() + m_size; }\r
+\r
+ //! @brief Returns const iterator to the one after the last element.\r
+ //!\r
+ //! @return const_iterator pointing to the one after the last element contained in the vector.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_iterator end() const { return this->begin() + m_size; }\r
+\r
+ //! @brief Returns const iterator to the one after the last element.\r
+ //!\r
+ //! @return const_iterator pointing to the one after the last element contained in the vector.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_iterator cend() const { return this->cbegin() + m_size; }\r
+\r
+ //! @brief Returns reverse iterator to the first element of the reversed container.\r
+ //!\r
+ //! @return reverse_iterator pointing to the beginning\r
+ //! of the reversed varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }\r
+\r
+ //! @brief Returns const reverse iterator to the first element of the reversed container.\r
+ //!\r
+ //! @return const_reverse_iterator pointing to the beginning\r
+ //! of the reversed varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(this->end()); }\r
+\r
+ //! @brief Returns const reverse iterator to the first element of the reversed container.\r
+ //!\r
+ //! @return const_reverse_iterator pointing to the beginning\r
+ //! of the reversed varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(this->end()); }\r
+\r
+ //! @brief Returns reverse iterator to the one after the last element of the reversed container.\r
+ //!\r
+ //! @return reverse_iterator pointing to the one after the last element\r
+ //! of the reversed varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }\r
+\r
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.\r
+ //!\r
+ //! @return const_reverse_iterator pointing to the one after the last element\r
+ //! of the reversed varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reverse_iterator rend() const { return const_reverse_iterator(this->begin()); }\r
+\r
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.\r
+ //!\r
+ //! @return const_reverse_iterator pointing to the one after the last element\r
+ //! of the reversed varray.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ const_reverse_iterator crend() const { return const_reverse_iterator(this->begin()); }\r
+\r
+ //! @brief Returns container's capacity.\r
+ //!\r
+ //! @return container's capacity.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ static size_type capacity() { return Capacity; }\r
+\r
+ //! @brief Returns container's capacity.\r
+ //!\r
+ //! @return container's capacity.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ static size_type max_size() { return Capacity; }\r
+\r
+ //! @brief Returns the number of stored elements.\r
+ //!\r
+ //! @return Number of elements contained in the container.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ size_type size() const { return m_size; }\r
+\r
+ //! @brief Queries if the container contains elements.\r
+ //!\r
+ //! @return true if the number of elements contained in the\r
+ //! container is equal to 0.\r
+ //!\r
+ //! @par Throws\r
+ //! Nothing.\r
+ //!\r
+ //! @par Complexity\r
+ //! Constant O(1).\r
+ bool empty() const { return 0 == m_size; }\r
+\r
+private:\r
+\r
+ // @par Throws\r
+ // Nothing.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <std::size_t C>\r
+ void move_ctor_dispatch(varray<value_type, C> & other, boost::true_type /*use_memop*/)\r
+ {\r
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);\r
+ m_size = other.m_size;\r
+ }\r
+\r
+ // @par Throws\r
+ // @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor throws\r
+ // @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <std::size_t C>\r
+ void move_ctor_dispatch(varray<value_type, C> & other, boost::false_type /*use_memop*/)\r
+ {\r
+ namespace sv = varray_detail;\r
+ sv::uninitialized_move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw\r
+ m_size = other.m_size;\r
+ }\r
+\r
+ // @par Throws\r
+ // Nothing.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <std::size_t C>\r
+ void move_assign_dispatch(varray<value_type, C> & other, boost::true_type /*use_memop*/)\r
+ {\r
+ this->clear();\r
+\r
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);\r
+ std::swap(m_size, other.m_size);\r
+ }\r
+\r
+ // @par Throws\r
+ // @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor or move assignment throws\r
+ // @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor or move assignment throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <std::size_t C>\r
+ void move_assign_dispatch(varray<value_type, C> & other, boost::false_type /*use_memop*/)\r
+ {\r
+ namespace sv = varray_detail;\r
+ if ( m_size <= static_cast<size_type>(other.size()) )\r
+ {\r
+ sv::move_if_noexcept(other.begin(), other.begin() + m_size, this->begin()); // may throw\r
+ // TODO - perform uninitialized_copy first?\r
+ sv::uninitialized_move_if_noexcept(other.begin() + m_size, other.end(), this->end()); // may throw\r
+ }\r
+ else\r
+ {\r
+ sv::move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw\r
+ sv::destroy(this->begin() + other.size(), this->end());\r
+ }\r
+ m_size = other.size(); // update end\r
+ }\r
+\r
+ // @par Throws\r
+ // Nothing.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <std::size_t C>\r
+ void swap_dispatch(varray<value_type, C> & other, boost::true_type const& /*use_optimized_swap*/)\r
+ {\r
+ typedef typename\r
+ boost::mpl::if_c<\r
+ Capacity < C,\r
+ aligned_storage_type,\r
+ typename varray<value_type, C>::aligned_storage_type\r
+ >::type\r
+ storage_type;\r
+ \r
+ storage_type temp;\r
+ Value * temp_ptr = reinterpret_cast<Value*>(temp.address());\r
+\r
+ ::memcpy(temp_ptr, this->data(), sizeof(Value) * this->size());\r
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.size());\r
+ ::memcpy(other.data(), temp_ptr, sizeof(Value) * this->size());\r
+\r
+ std::swap(m_size, other.m_size);\r
+ }\r
+\r
+ // @par Throws\r
+ // If Value's move constructor or move assignment throws\r
+ // but only if use_memop_in_swap_and_move is false_type - default.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <std::size_t C>\r
+ void swap_dispatch(varray<value_type, C> & other, boost::false_type const& /*use_optimized_swap*/)\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ typedef typename\r
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;\r
+\r
+ if ( this->size() < other.size() )\r
+ swap_dispatch_impl(this->begin(), this->end(), other.begin(), other.end(), use_memop_in_swap_and_move()); // may throw\r
+ else\r
+ swap_dispatch_impl(other.begin(), other.end(), this->begin(), this->end(), use_memop_in_swap_and_move()); // may throw\r
+ std::swap(m_size, other.m_size);\r
+ }\r
+\r
+ // @par Throws\r
+ // Nothing.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::true_type const& /*use_memop*/)\r
+ {\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la),\r
+ // "incompatible ranges");\r
+\r
+ namespace sv = varray_detail;\r
+ for (; first_sm != last_sm ; ++first_sm, ++first_la)\r
+ {\r
+ boost::aligned_storage<\r
+ sizeof(value_type),\r
+ boost::alignment_of<value_type>::value\r
+ > temp_storage;\r
+ value_type * temp_ptr = reinterpret_cast<value_type*>(temp_storage.address());\r
+\r
+ ::memcpy(temp_ptr, boost::addressof(*first_sm), sizeof(value_type));\r
+ ::memcpy(boost::addressof(*first_sm), boost::addressof(*first_la), sizeof(value_type));\r
+ ::memcpy(boost::addressof(*first_la), temp_ptr, sizeof(value_type));\r
+ }\r
+\r
+ ::memcpy(first_sm, first_la, sizeof(value_type) * std::distance(first_la, last_la));\r
+ }\r
+\r
+ // @par Throws\r
+ // If Value's move constructor or move assignment throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::false_type const& /*use_memop*/)\r
+ {\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la),\r
+ // "incompatible ranges");\r
+\r
+ namespace sv = varray_detail;\r
+ for (; first_sm != last_sm ; ++first_sm, ++first_la)\r
+ {\r
+ //boost::swap(*first_sm, *first_la); // may throw\r
+ value_type temp(boost::move(*first_sm)); // may throw\r
+ *first_sm = boost::move(*first_la); // may throw\r
+ *first_la = boost::move(temp); // may throw\r
+ }\r
+ sv::uninitialized_move(first_la, last_la, first_sm); // may throw\r
+ sv::destroy(first_la, last_la);\r
+ }\r
+\r
+ // insert\r
+\r
+ // @par Throws\r
+ // If Value's move constructor, move assignment throws\r
+ // or if Value's copy constructor or copy assignment throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <typename Iterator>\r
+ void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&)\r
+ {\r
+ BOOST_CONCEPT_ASSERT((boost_concepts::RandomAccessTraversal<Iterator>)); // Make sure you passed a RandomAccessIterator\r
+ \r
+ errh::check_iterator_end_eq(*this, position);\r
+ \r
+ typename boost::iterator_difference<Iterator>::type\r
+ count = std::distance(first, last);\r
+\r
+ errh::check_capacity(*this, m_size + count); // may throw\r
+\r
+ if ( position == this->end() )\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ sv::uninitialized_copy(first, last, position); // may throw\r
+ m_size += count; // update end\r
+ }\r
+ else\r
+ {\r
+ this->insert_in_the_middle(position, first, last, count); // may throw\r
+ }\r
+ }\r
+\r
+ // @par Throws\r
+ // If Value's move constructor, move assignment throws\r
+ // or if Value's copy constructor or copy assignment throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <typename Iterator, typename Traversal>\r
+ void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/)\r
+ {\r
+ errh::check_iterator_end_eq(*this, position);\r
+\r
+ if ( position == this->end() )\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ std::ptrdiff_t d = std::distance(position, this->begin() + Capacity);\r
+ std::size_t count = sv::uninitialized_copy_s(first, last, position, d); // may throw\r
+ \r
+ errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? m_size + count : Capacity + 1); // may throw\r
+\r
+ m_size += count;\r
+ }\r
+ else\r
+ {\r
+ typename boost::iterator_difference<Iterator>::type\r
+ count = std::distance(first, last);\r
+ \r
+ errh::check_capacity(*this, m_size + count); // may throw\r
+\r
+ this->insert_in_the_middle(position, first, last, count); // may throw\r
+ }\r
+ }\r
+\r
+ // @par Throws\r
+ // If Value's move constructor, move assignment throws\r
+ // or if Value's copy constructor or copy assignment throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <typename Iterator>\r
+ void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ difference_type to_move = std::distance(position, this->end());\r
+\r
+ // TODO - should following lines check for exception and revert to the old size?\r
+\r
+ if ( count < to_move )\r
+ {\r
+ sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw\r
+ m_size += count; // update end\r
+ sv::move_backward(position, position + to_move - count, this->end() - count); // may throw\r
+ sv::copy(first, last, position); // may throw\r
+ }\r
+ else\r
+ {\r
+ Iterator middle_iter = first;\r
+ std::advance(middle_iter, to_move);\r
+\r
+ sv::uninitialized_copy(middle_iter, last, this->end()); // may throw\r
+ m_size += count - to_move; // update end\r
+ sv::uninitialized_move(position, position + to_move, position + count); // may throw\r
+ m_size += to_move; // update end\r
+ sv::copy(first, middle_iter, position); // may throw\r
+ }\r
+ }\r
+\r
+ // assign\r
+\r
+ // @par Throws\r
+ // If Value's constructor or assignment taking dereferenced Iterator throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <typename Iterator>\r
+ void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/)\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ typename boost::iterator_difference<Iterator>::type\r
+ s = std::distance(first, last);\r
+\r
+ errh::check_capacity(*this, s); // may throw\r
+\r
+ if ( m_size <= static_cast<size_type>(s) )\r
+ {\r
+ sv::copy(first, first + m_size, this->begin()); // may throw\r
+ // TODO - perform uninitialized_copy first?\r
+ sv::uninitialized_copy(first + m_size, last, this->end()); // may throw\r
+ }\r
+ else\r
+ {\r
+ sv::copy(first, last, this->begin()); // may throw\r
+ sv::destroy(this->begin() + s, this->end());\r
+ }\r
+ m_size = s; // update end\r
+ }\r
+\r
+ // @par Throws\r
+ // If Value's constructor or assignment taking dereferenced Iterator throws.\r
+ // @par Complexity\r
+ // Linear O(N).\r
+ template <typename Iterator, typename Traversal>\r
+ void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)\r
+ {\r
+ namespace sv = varray_detail;\r
+\r
+ size_type s = 0;\r
+ iterator it = this->begin();\r
+\r
+ for ( ; it != this->end() && first != last ; ++it, ++first, ++s )\r
+ *it = *first; // may throw\r
+\r
+ sv::destroy(it, this->end());\r
+\r
+ std::ptrdiff_t d = std::distance(it, this->begin() + Capacity);\r
+ std::size_t count = sv::uninitialized_copy_s(first, last, it, d); // may throw\r
+ s += count;\r
+\r
+ errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? s : Capacity + 1); // may throw\r
+\r
+ m_size = s; // update end\r
+ }\r
+\r
+ pointer ptr()\r
+ {\r
+ return pointer(static_cast<Value*>(m_storage.address()));\r
+ }\r
+\r
+ const_pointer ptr() const\r
+ {\r
+ return const_pointer(static_cast<const Value*>(m_storage.address()));\r
+ }\r
+\r
+ size_type m_size;\r
+ aligned_storage_type m_storage;\r
+};\r
+\r
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)\r
+\r
+template<typename Value>\r
+class varray<Value, 0>\r
+{\r
+ typedef varray_detail::varray_traits<Value, 0> vt;\r
+ typedef varray_detail::checker<varray> errh;\r
+\r
+public:\r
+ typedef typename vt::value_type value_type;\r
+ typedef typename vt::size_type size_type;\r
+ typedef typename vt::difference_type difference_type;\r
+ typedef typename vt::pointer pointer;\r
+ typedef typename vt::const_pointer const_pointer;\r
+ typedef typename vt::reference reference;\r
+ typedef typename vt::const_reference const_reference;\r
+\r
+ typedef pointer iterator;\r
+ typedef const_pointer const_iterator;\r
+ typedef boost::reverse_iterator<iterator> reverse_iterator;\r
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;\r
+\r
+ // nothrow\r
+ varray() {}\r
+\r
+ // strong\r
+ explicit varray(size_type count)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ // strong\r
+ varray(size_type count, value_type const&)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ // strong\r
+ varray(varray const& /*other*/)\r
+ {\r
+ //errh::check_capacity(*this, count);\r
+ }\r
+\r
+ // strong\r
+ template <std::size_t C>\r
+ varray(varray<value_type, C> const& other)\r
+ {\r
+ errh::check_capacity(*this, other.size()); // may throw\r
+ }\r
+\r
+ // strong\r
+ template <typename Iterator>\r
+ varray(Iterator first, Iterator last)\r
+ {\r
+ errh::check_capacity(*this, std::distance(first, last)); // may throw\r
+ }\r
+\r
+ // basic\r
+ varray & operator=(varray const& /*other*/)\r
+ {\r
+ //errh::check_capacity(*this, other.size());\r
+ return *this;\r
+ }\r
+\r
+ // basic\r
+ template <size_t C>\r
+ varray & operator=(varray<value_type, C> const& other)\r
+ {\r
+ errh::check_capacity(*this, other.size()); // may throw\r
+ return *this;\r
+ }\r
+\r
+ // nothrow\r
+ ~varray() {}\r
+\r
+ // strong\r
+ void resize(size_type count)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ // strong\r
+ void resize(size_type count, value_type const&)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ \r
+ // nothrow\r
+ void reserve(size_type count)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ // strong\r
+ void push_back(value_type const&)\r
+ {\r
+ errh::check_capacity(*this, 1); // may throw\r
+ }\r
+\r
+ // nothrow\r
+ void pop_back()\r
+ {\r
+ errh::check_not_empty(*this);\r
+ }\r
+\r
+ // basic\r
+ void insert(iterator position, value_type const&)\r
+ {\r
+ errh::check_iterator_end_eq(*this, position);\r
+ errh::check_capacity(*this, 1); // may throw\r
+ }\r
+\r
+ // basic\r
+ void insert(iterator position, size_type count, value_type const&)\r
+ {\r
+ errh::check_iterator_end_eq(*this, position);\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ // basic\r
+ template <typename Iterator>\r
+ void insert(iterator, Iterator first, Iterator last)\r
+ {\r
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator\r
+ errh::check_capacity(*this, std::distance(first, last)); // may throw\r
+ }\r
+\r
+ // basic\r
+ void erase(iterator position)\r
+ {\r
+ errh::check_iterator_end_neq(*this, position);\r
+ }\r
+\r
+ // basic\r
+ void erase(iterator first, iterator last)\r
+ {\r
+ errh::check_iterator_end_eq(*this, first);\r
+ errh::check_iterator_end_eq(*this, last);\r
+\r
+ //BOOST_GEOMETRY_INDEX_ASSERT(0 <= n, "invalid range");\r
+ }\r
+\r
+ // basic\r
+ template <typename Iterator>\r
+ void assign(Iterator first, Iterator last)\r
+ {\r
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator\r
+ errh::check_capacity(*this, std::distance(first, last)); // may throw\r
+ }\r
+\r
+ // basic\r
+ void assign(size_type count, value_type const&)\r
+ {\r
+ errh::check_capacity(*this, count); // may throw\r
+ }\r
+\r
+ // nothrow\r
+ void clear() {}\r
+\r
+ // strong\r
+ reference at(size_type i)\r
+ {\r
+ errh::throw_out_of_bounds(*this, i); // may throw\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ // strong\r
+ const_reference at(size_type i) const\r
+ {\r
+ errh::throw_out_of_bounds(*this, i); // may throw\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ // nothrow\r
+ reference operator[](size_type i)\r
+ {\r
+ errh::check_index(*this, i);\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ // nothrow\r
+ const_reference operator[](size_type i) const\r
+ {\r
+ errh::check_index(*this, i);\r
+ return *(this->begin() + i);\r
+ }\r
+\r
+ // nothrow\r
+ reference front()\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->begin());\r
+ }\r
+\r
+ // nothrow\r
+ const_reference front() const\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->begin());\r
+ }\r
+\r
+ // nothrow\r
+ reference back()\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->end() - 1);\r
+ }\r
+\r
+ // nothrow\r
+ const_reference back() const\r
+ {\r
+ errh::check_not_empty(*this);\r
+ return *(this->end() - 1);\r
+ }\r
+\r
+ // nothrow\r
+ Value * data() { return boost::addressof(*(this->ptr())); }\r
+ const Value * data() const { return boost::addressof(*(this->ptr())); }\r
+\r
+ // nothrow\r
+ iterator begin() { return this->ptr(); }\r
+ const_iterator begin() const { return this->ptr(); }\r
+ const_iterator cbegin() const { return this->ptr(); }\r
+ iterator end() { return this->begin(); }\r
+ const_iterator end() const { return this->begin(); }\r
+ const_iterator cend() const { return this->cbegin(); }\r
+ // nothrow\r
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }\r
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }\r
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }\r
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }\r
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }\r
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }\r
+\r
+ // nothrow\r
+ size_type capacity() const { return 0; }\r
+ size_type max_size() const { return 0; }\r
+ size_type size() const { return 0; }\r
+ bool empty() const { return true; }\r
+\r
+private:\r
+ pointer ptr()\r
+ {\r
+ return pointer(reinterpret_cast<Value*>(this));\r
+ }\r
+\r
+ const_pointer ptr() const\r
+ {\r
+ return const_pointer(reinterpret_cast<const Value*>(this));\r
+ }\r
+};\r
+\r
+#endif // !BOOST_CONTAINER_DOXYGEN_INVOKED\r
+\r
+//! @brief Checks if contents of two varrays are equal.\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @return \c true if containers have the same size and elements in both containers are equal.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+bool operator== (varray<V, C1> const& x, varray<V, C2> const& y)\r
+{\r
+ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());\r
+}\r
+\r
+//! @brief Checks if contents of two varrays are not equal.\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @return \c true if containers have different size or elements in both containers are not equal.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+bool operator!= (varray<V, C1> const& x, varray<V, C2> const& y)\r
+{\r
+ return !(x==y);\r
+}\r
+\r
+//! @brief Lexicographically compares varrays.\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @return \c true if x compares lexicographically less than y.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+bool operator< (varray<V, C1> const& x, varray<V, C2> const& y)\r
+{\r
+ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());\r
+}\r
+\r
+//! @brief Lexicographically compares varrays.\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @return \c true if y compares lexicographically less than x.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+bool operator> (varray<V, C1> const& x, varray<V, C2> const& y)\r
+{\r
+ return y<x;\r
+}\r
+\r
+//! @brief Lexicographically compares varrays.\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @return \c true if y don't compare lexicographically less than x.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+bool operator<= (varray<V, C1> const& x, varray<V, C2> const& y)\r
+{\r
+ return !(y<x);\r
+}\r
+\r
+//! @brief Lexicographically compares varrays.\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @return \c true if x don't compare lexicographically less than y.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+bool operator>= (varray<V, C1> const& x, varray<V, C2> const& y)\r
+{\r
+ return !(x<y);\r
+}\r
+\r
+//! @brief Swaps contents of two varrays.\r
+//!\r
+//! This function calls varray::swap().\r
+//!\r
+//! @ingroup varray_non_member\r
+//!\r
+//! @param x The first varray.\r
+//! @param y The second varray.\r
+//!\r
+//! @par Complexity\r
+//! Linear O(N).\r
+template<typename V, std::size_t C1, std::size_t C2>\r
+inline void swap(varray<V, C1> & x, varray<V, C2> & y)\r
+{\r
+ x.swap(y);\r
+}\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+// TODO - REMOVE/CHANGE\r
+#include <boost/container/detail/config_end.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP\r
--- /dev/null
+// Boost.Geometry\r
+//\r
+// varray details\r
+//\r
+// Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland.\r
+// Copyright (c) 2011-2013 Andrew Hundt.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP\r
+\r
+#include <cstddef>\r
+#include <cstring>\r
+#include <memory>\r
+#include <limits>\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/and.hpp>\r
+#include <boost/mpl/or.hpp>\r
+#include <boost/mpl/int.hpp>\r
+\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+#include <boost/type_traits/has_trivial_assign.hpp>\r
+#include <boost/type_traits/has_trivial_copy.hpp>\r
+#include <boost/type_traits/has_trivial_constructor.hpp>\r
+#include <boost/type_traits/has_trivial_destructor.hpp>\r
+#include <boost/type_traits/has_trivial_move_constructor.hpp>\r
+#include <boost/type_traits/has_trivial_move_assign.hpp>\r
+//#include <boost/type_traits/has_nothrow_constructor.hpp>\r
+//#include <boost/type_traits/has_nothrow_copy.hpp>\r
+//#include <boost/type_traits/has_nothrow_assign.hpp>\r
+//#include <boost/type_traits/has_nothrow_destructor.hpp>\r
+\r
+#include <boost/detail/no_exceptions_support.hpp>\r
+#include <boost/config.hpp>\r
+#include <boost/move/move.hpp>\r
+#include <boost/core/addressof.hpp>\r
+#include <boost/iterator/iterator_traits.hpp>\r
+\r
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+#include <boost/move/detail/fwd_macros.hpp>\r
+#endif\r
+\r
+// TODO - move vectors iterators optimization to the other, optional file instead of checking defines?\r
+\r
+#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)\r
+#include <vector>\r
+#include <boost/container/vector.hpp>\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail {\r
+\r
+template <typename I>\r
+struct are_elements_contiguous : boost::is_pointer<I>\r
+{};\r
+ \r
+// EXPERIMENTAL - not finished\r
+// Conditional setup - mark vector iterators defined in known implementations\r
+// as iterators pointing to contiguous ranges\r
+\r
+#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)\r
+ \r
+template <typename Pointer>\r
+struct are_elements_contiguous<\r
+ boost::container::container_detail::vector_const_iterator<Pointer>\r
+> : boost::true_type\r
+{};\r
+\r
+template <typename Pointer>\r
+struct are_elements_contiguous<\r
+ boost::container::container_detail::vector_iterator<Pointer>\r
+> : boost::true_type\r
+{};\r
+\r
+#if defined(BOOST_DINKUMWARE_STDLIB)\r
+ \r
+template <typename T>\r
+struct are_elements_contiguous<\r
+ std::_Vector_const_iterator<T>\r
+> : boost::true_type\r
+{};\r
+\r
+template <typename T>\r
+struct are_elements_contiguous<\r
+ std::_Vector_iterator<T>\r
+> : boost::true_type\r
+{};\r
+\r
+#elif defined(BOOST_GNU_STDLIB)\r
+\r
+template <typename P, typename T, typename A>\r
+struct are_elements_contiguous<\r
+ __gnu_cxx::__normal_iterator<P, std::vector<T, A> >\r
+> : boost::true_type\r
+{};\r
+\r
+#elif defined(_LIBCPP_VERSION)\r
+\r
+// TODO - test it first\r
+//template <typename P>\r
+//struct are_elements_contiguous<\r
+// __wrap_iter<P>\r
+//> : boost::true_type\r
+//{};\r
+\r
+#else // OTHER_STDLIB\r
+\r
+// TODO - add other iterators implementations\r
+ \r
+#endif // STDLIB\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS\r
+\r
+// True if iterator values are the same and both iterators points to the ranges of contiguous elements\r
+\r
+template <typename I, typename O>\r
+struct are_corresponding :\r
+ ::boost::mpl::and_<\r
+ ::boost::is_same<\r
+ ::boost::remove_const<\r
+ typename ::boost::iterator_value<I>::type\r
+ >,\r
+ ::boost::remove_const<\r
+ typename ::boost::iterator_value<O>::type\r
+ >\r
+ >,\r
+ are_elements_contiguous<I>,\r
+ are_elements_contiguous<O>\r
+ >\r
+{};\r
+\r
+template <typename I, typename V>\r
+struct is_corresponding_value :\r
+ ::boost::is_same<\r
+ ::boost::remove_const<\r
+ typename ::boost::iterator_value<I>::type\r
+ >,\r
+ ::boost::remove_const<V>\r
+ >\r
+{};\r
+\r
+// destroy(I, I)\r
+\r
+template <typename I>\r
+void destroy_dispatch(I /*first*/, I /*last*/,\r
+ boost::true_type const& /*has_trivial_destructor*/)\r
+{}\r
+\r
+template <typename I>\r
+void destroy_dispatch(I first, I last,\r
+ boost::false_type const& /*has_trivial_destructor*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ for ( ; first != last ; ++first )\r
+ first->~value_type();\r
+}\r
+\r
+template <typename I>\r
+void destroy(I first, I last)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ destroy_dispatch(first, last, has_trivial_destructor<value_type>());\r
+}\r
+\r
+// destroy(I)\r
+\r
+template <typename I>\r
+void destroy_dispatch(I /*pos*/,\r
+ boost::true_type const& /*has_trivial_destructor*/)\r
+{}\r
+\r
+template <typename I>\r
+void destroy_dispatch(I pos,\r
+ boost::false_type const& /*has_trivial_destructor*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ pos->~value_type();\r
+}\r
+\r
+template <typename I>\r
+void destroy(I pos)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ destroy_dispatch(pos, has_trivial_destructor<value_type>());\r
+}\r
+\r
+// copy(I, I, O)\r
+\r
+template <typename I, typename O>\r
+inline O copy_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<true> const& /*use_memmove*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);\r
+\r
+ ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);\r
+ return dst + d;\r
+}\r
+\r
+template <typename I, typename O>\r
+inline O copy_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<false> const& /*use_memmove*/)\r
+{\r
+ return std::copy(first, last, dst); // may throw\r
+}\r
+\r
+template <typename I, typename O>\r
+inline O copy(I first, I last, O dst)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ are_corresponding<I, O>,\r
+ ::boost::has_trivial_assign<\r
+ typename ::boost::iterator_value<O>::type\r
+ >\r
+ >::type\r
+ use_memmove;\r
+ \r
+ return copy_dispatch(first, last, dst, use_memmove()); // may throw\r
+}\r
+\r
+// uninitialized_copy(I, I, O)\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_copy_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<true> const& /*use_memcpy*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);\r
+\r
+ ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);\r
+ return dst + d;\r
+}\r
+\r
+template <typename I, typename F>\r
+inline\r
+F uninitialized_copy_dispatch(I first, I last, F dst,\r
+ boost::mpl::bool_<false> const& /*use_memcpy*/)\r
+{\r
+ return std::uninitialized_copy(first, last, dst); // may throw\r
+}\r
+\r
+template <typename I, typename F>\r
+inline\r
+F uninitialized_copy(I first, I last, F dst)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ are_corresponding<I, F>,\r
+ ::boost::has_trivial_copy<\r
+ typename ::boost::iterator_value<F>::type\r
+ >\r
+ >::type\r
+ use_memcpy;\r
+\r
+ return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw\r
+}\r
+\r
+// uninitialized_move(I, I, O)\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_move_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<true> const& /*use_memcpy*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);\r
+\r
+ ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);\r
+ return dst + d;\r
+}\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_move_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<false> const& /*use_memcpy*/)\r
+{\r
+ //return boost::uninitialized_move(first, last, dst); // may throw\r
+\r
+ O o = dst;\r
+\r
+ BOOST_TRY\r
+ {\r
+ typedef typename std::iterator_traits<O>::value_type value_type;\r
+ for (; first != last; ++first, ++o )\r
+ new (boost::addressof(*o)) value_type(boost::move(*first));\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ destroy(dst, o);\r
+ BOOST_RETHROW;\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ return dst;\r
+}\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_move(I first, I last, O dst)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ are_corresponding<I, O>,\r
+ ::boost::has_trivial_copy<\r
+ typename ::boost::iterator_value<O>::type\r
+ >\r
+ >::type\r
+ use_memcpy;\r
+\r
+ return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw\r
+}\r
+\r
+// TODO - move uses memmove - implement 2nd version using memcpy?\r
+\r
+// move(I, I, O)\r
+\r
+template <typename I, typename O>\r
+inline\r
+O move_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<true> const& /*use_memmove*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);\r
+\r
+ ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);\r
+ return dst + d;\r
+}\r
+\r
+template <typename I, typename O>\r
+inline\r
+O move_dispatch(I first, I last, O dst,\r
+ boost::mpl::bool_<false> const& /*use_memmove*/)\r
+{\r
+ return boost::move(first, last, dst); // may throw\r
+}\r
+\r
+template <typename I, typename O>\r
+inline\r
+O move(I first, I last, O dst)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ are_corresponding<I, O>,\r
+ ::boost::has_trivial_assign<\r
+ typename ::boost::iterator_value<O>::type\r
+ >\r
+ >::type\r
+ use_memmove;\r
+\r
+ return move_dispatch(first, last, dst, use_memmove()); // may throw\r
+}\r
+\r
+// move_backward(BDI, BDI, BDO)\r
+\r
+template <typename BDI, typename BDO>\r
+inline\r
+BDO move_backward_dispatch(BDI first, BDI last, BDO dst,\r
+ boost::mpl::bool_<true> const& /*use_memmove*/)\r
+{\r
+ typedef typename boost::iterator_value<BDI>::type value_type;\r
+ typename boost::iterator_difference<BDI>::type d = std::distance(first, last);\r
+\r
+ BDO foo(dst - d);\r
+ ::memmove(boost::addressof(*foo), boost::addressof(*first), sizeof(value_type) * d);\r
+ return foo;\r
+}\r
+\r
+template <typename BDI, typename BDO>\r
+inline\r
+BDO move_backward_dispatch(BDI first, BDI last, BDO dst,\r
+ boost::mpl::bool_<false> const& /*use_memmove*/)\r
+{\r
+ return boost::move_backward(first, last, dst); // may throw\r
+}\r
+\r
+template <typename BDI, typename BDO>\r
+inline\r
+BDO move_backward(BDI first, BDI last, BDO dst)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ are_corresponding<BDI, BDO>,\r
+ ::boost::has_trivial_assign<\r
+ typename ::boost::iterator_value<BDO>::type\r
+ >\r
+ >::type\r
+ use_memmove;\r
+\r
+ return move_backward_dispatch(first, last, dst, use_memmove()); // may throw\r
+}\r
+\r
+template <typename T>\r
+struct has_nothrow_move : public\r
+ ::boost::mpl::or_<\r
+ boost::mpl::bool_<\r
+ ::boost::has_nothrow_move<\r
+ typename ::boost::remove_const<T>::type\r
+ >::value\r
+ >,\r
+ boost::mpl::bool_<\r
+ ::boost::has_nothrow_move<T>::value\r
+ >\r
+ >\r
+{};\r
+\r
+// uninitialized_move_if_noexcept(I, I, O)\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)\r
+{ return varray_detail::uninitialized_move(first, last, dst); }\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)\r
+{ return varray_detail::uninitialized_copy(first, last, dst); }\r
+\r
+template <typename I, typename O>\r
+inline\r
+O uninitialized_move_if_noexcept(I first, I last, O dst)\r
+{\r
+ typedef typename has_nothrow_move<\r
+ typename ::boost::iterator_value<O>::type\r
+ >::type use_move;\r
+\r
+ return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw\r
+}\r
+\r
+// move_if_noexcept(I, I, O)\r
+\r
+template <typename I, typename O>\r
+inline\r
+O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)\r
+{ return move(first, last, dst); }\r
+\r
+template <typename I, typename O>\r
+inline\r
+O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)\r
+{ return copy(first, last, dst); }\r
+\r
+template <typename I, typename O>\r
+inline\r
+O move_if_noexcept(I first, I last, O dst)\r
+{\r
+ typedef typename has_nothrow_move<\r
+ typename ::boost::iterator_value<O>::type\r
+ >::type use_move;\r
+\r
+ return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw\r
+}\r
+\r
+// uninitialized_fill(I, I)\r
+\r
+template <typename I>\r
+inline\r
+void uninitialized_fill_dispatch(I /*first*/, I /*last*/,\r
+ boost::true_type const& /*has_trivial_constructor*/,\r
+ boost::true_type const& /*disable_trivial_init*/)\r
+{}\r
+\r
+template <typename I>\r
+inline\r
+void uninitialized_fill_dispatch(I first, I last,\r
+ boost::true_type const& /*has_trivial_constructor*/,\r
+ boost::false_type const& /*disable_trivial_init*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ for ( ; first != last ; ++first )\r
+ new (boost::addressof(*first)) value_type();\r
+}\r
+\r
+template <typename I, typename DisableTrivialInit>\r
+inline\r
+void uninitialized_fill_dispatch(I first, I last,\r
+ boost::false_type const& /*has_trivial_constructor*/,\r
+ DisableTrivialInit const& /*not_used*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ I it = first;\r
+\r
+ BOOST_TRY\r
+ {\r
+ for ( ; it != last ; ++it )\r
+ new (boost::addressof(*it)) value_type(); // may throw\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ destroy(first, it);\r
+ BOOST_RETHROW;\r
+ }\r
+ BOOST_CATCH_END\r
+}\r
+\r
+template <typename I, typename DisableTrivialInit>\r
+inline\r
+void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)\r
+{\r
+ typedef typename boost::iterator_value<I>::type value_type;\r
+ uninitialized_fill_dispatch(first, last, boost::has_trivial_constructor<value_type>(), disable_trivial_init); // may throw\r
+}\r
+\r
+// construct(I)\r
+\r
+template <typename I>\r
+inline\r
+void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I /*pos*/)\r
+{}\r
+\r
+template <typename I>\r
+inline\r
+void construct_dispatch(boost::mpl::bool_<false> const& /*dont_init*/, I pos)\r
+{\r
+ typedef typename ::boost::iterator_value<I>::type value_type;\r
+ new (static_cast<void*>(::boost::addressof(*pos))) value_type(); // may throw\r
+}\r
+\r
+template <typename DisableTrivialInit, typename I>\r
+inline\r
+void construct(DisableTrivialInit const&, I pos)\r
+{\r
+ typedef typename ::boost::iterator_value<I>::type value_type;\r
+ typedef typename ::boost::mpl::and_<\r
+ boost::has_trivial_constructor<value_type>,\r
+ DisableTrivialInit\r
+ >::type dont_init;\r
+\r
+ construct_dispatch(dont_init(), pos); // may throw\r
+}\r
+\r
+// construct(I, V)\r
+\r
+template <typename I, typename V>\r
+inline\r
+void construct_copy_dispatch(I pos, V const& v,\r
+ boost::mpl::bool_<true> const& /*use_memcpy*/)\r
+{\r
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));\r
+}\r
+\r
+template <typename I, typename P>\r
+inline\r
+void construct_copy_dispatch(I pos, P const& p,\r
+ boost::mpl::bool_<false> const& /*use_memcpy*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type V;\r
+ new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw\r
+}\r
+\r
+template <typename DisableTrivialInit, typename I, typename P>\r
+inline\r
+void construct(DisableTrivialInit const&,\r
+ I pos, P const& p)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ is_corresponding_value<I, P>,\r
+ ::boost::has_trivial_copy<P>\r
+ >::type\r
+ use_memcpy;\r
+\r
+ construct_copy_dispatch(pos, p, use_memcpy()); // may throw\r
+}\r
+\r
+// Needed by push_back(V &&)\r
+\r
+template <typename I, typename V>\r
+inline\r
+void construct_move_dispatch(I pos, V const& v,\r
+ boost::mpl::bool_<true> const& /*use_memcpy*/)\r
+{\r
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));\r
+}\r
+\r
+template <typename I, typename P>\r
+inline\r
+void construct_move_dispatch(I pos, BOOST_RV_REF(P) p,\r
+ boost::mpl::bool_<false> const& /*use_memcpy*/)\r
+{\r
+ typedef typename boost::iterator_value<I>::type V;\r
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw\r
+}\r
+\r
+template <typename DisableTrivialInit, typename I, typename P>\r
+inline\r
+void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ is_corresponding_value<I, P>,\r
+ ::boost::has_trivial_move_constructor<P>\r
+ >::type\r
+ use_memcpy;\r
+\r
+ construct_move_dispatch(pos, ::boost::move(p), use_memcpy()); // may throw\r
+}\r
+\r
+// Needed by emplace_back() and emplace()\r
+\r
+#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)\r
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+\r
+template <typename DisableTrivialInit, typename I, class ...Args>\r
+inline\r
+void construct(DisableTrivialInit const&,\r
+ I pos,\r
+ BOOST_FWD_REF(Args) ...args)\r
+{\r
+ typedef typename boost::iterator_value<I>::type V;\r
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw\r
+}\r
+\r
+#else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES\r
+\r
+// BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0\r
+// !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0\r
+// which means that version with one parameter may take V const& v\r
+\r
+#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT(N) \\r
+template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \\r
+inline \\r
+void construct(DisableTrivialInit const&, \\r
+ I pos, \\r
+ BOOST_FWD_REF(P) p \\r
+ BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \\r
+{ \\r
+ typedef typename boost::iterator_value<I>::type V; \\r
+ new \\r
+ (static_cast<void*>(boost::addressof(*pos))) \\r
+ V(boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/ \\r
+} \\r
+\r
+BOOST_MOVE_ITERATE_1TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT)\r
+#undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT\r
+\r
+#endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES\r
+#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE\r
+\r
+// assign(I, V)\r
+\r
+template <typename I, typename V>\r
+inline\r
+void assign_copy_dispatch(I pos, V const& v,\r
+ boost::mpl::bool_<true> const& /*use_memcpy*/)\r
+{\r
+// TODO - use memmove here?\r
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));\r
+}\r
+\r
+template <typename I, typename V>\r
+inline\r
+void assign_copy_dispatch(I pos, V const& v,\r
+ boost::mpl::bool_<false> const& /*use_memcpy*/)\r
+{\r
+ *pos = v; // may throw\r
+}\r
+\r
+template <typename I, typename V>\r
+inline\r
+void assign(I pos, V const& v)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ is_corresponding_value<I, V>,\r
+ ::boost::has_trivial_assign<V>\r
+ >::type\r
+ use_memcpy;\r
+\r
+ assign_copy_dispatch(pos, v, use_memcpy()); // may throw\r
+}\r
+\r
+template <typename I, typename V>\r
+inline\r
+void assign_move_dispatch(I pos, V const& v,\r
+ boost::mpl::bool_<true> const& /*use_memcpy*/)\r
+{\r
+// TODO - use memmove here?\r
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));\r
+}\r
+\r
+template <typename I, typename V>\r
+inline\r
+void assign_move_dispatch(I pos, BOOST_RV_REF(V) v,\r
+ boost::mpl::bool_<false> const& /*use_memcpy*/)\r
+{\r
+ *pos = boost::move(v); // may throw\r
+}\r
+\r
+template <typename I, typename V>\r
+inline\r
+void assign(I pos, BOOST_RV_REF(V) v)\r
+{\r
+ typedef typename\r
+ ::boost::mpl::and_<\r
+ is_corresponding_value<I, V>,\r
+ ::boost::has_trivial_move_assign<V>\r
+ >::type\r
+ use_memcpy;\r
+\r
+ assign_move_dispatch(pos, ::boost::move(v), use_memcpy());\r
+}\r
+\r
+// uninitialized_copy_s\r
+\r
+template <typename I, typename F>\r
+inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)\r
+{\r
+ std::size_t count = 0;\r
+ F it = dest;\r
+\r
+ BOOST_TRY\r
+ {\r
+ for ( ; first != last ; ++it, ++first, ++count )\r
+ {\r
+ if ( max_count <= count )\r
+ return (std::numeric_limits<std::size_t>::max)();\r
+\r
+ // dummy 0 as DisableTrivialInit\r
+ construct(0, it, *first); // may throw\r
+ }\r
+ }\r
+ BOOST_CATCH(...)\r
+ {\r
+ destroy(dest, it);\r
+ BOOST_RETHROW;\r
+ }\r
+ BOOST_CATCH_END\r
+\r
+ return count;\r
+}\r
+\r
+// scoped_destructor\r
+\r
+template<class T>\r
+class scoped_destructor\r
+{\r
+public:\r
+ scoped_destructor(T * ptr) : m_ptr(ptr) {}\r
+\r
+ ~scoped_destructor()\r
+ {\r
+ if(m_ptr)\r
+ destroy(m_ptr);\r
+ }\r
+\r
+ void release() { m_ptr = 0; }\r
+\r
+private:\r
+ T * m_ptr;\r
+};\r
+\r
+}}}}} // namespace boost::geometry::index::detail::varray_detail\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Spatial index distance predicates, calculators and checkers used in nearest neighbor query\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP\r
+#define BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP\r
+\r
+#include <boost/geometry/index/detail/distance_predicates.hpp>\r
+\r
+/*!\r
+\defgroup nearest_relations Nearest relations (boost::geometry::index::)\r
+*/\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+// relations generators\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+\r
+/*!\r
+\brief Generate to_nearest() relationship.\r
+\r
+Generate a nearest query Point and Value's Indexable relationship while calculating\r
+distances. This function may be used to define that knn query should calculate distances\r
+as smallest as possible between query Point and Indexable's points. In other words it\r
+should be the distance to the nearest Indexable's point. This function may be also used\r
+to define distances bounds which indicates that Indexable's nearest point should be\r
+closer or further than value v. This is default relation.\r
+\r
+\ingroup nearest_relations\r
+\r
+\tparam T Type of wrapped object. This may be a Point for PointRelation or CoordinateType for\r
+ MinRelation or MaxRelation\r
+\r
+\param v Point or distance value.\r
+*/\r
+template <typename T>\r
+detail::to_nearest<T> to_nearest(T const& v)\r
+{\r
+ return detail::to_nearest<T>(v);\r
+}\r
+\r
+/*!\r
+\brief Generate to_centroid() relationship.\r
+\r
+Generate a nearest query Point and Value's Indexable relationship while calculating\r
+distances. This function may be used to define that knn query should calculate distances\r
+between query Point and Indexable's centroid. This function may be also used\r
+to define distances bounds which indicates that Indexable's centroid should be\r
+closer or further than value v.\r
+\r
+\ingroup nearest_relations\r
+\r
+\tparam T Type of wrapped object. This may be a Point for PointRelation or some CoordinateType for\r
+ MinRelation or MaxRelation\r
+\r
+\param v Point or distance value.\r
+*/\r
+template <typename T>\r
+detail::to_centroid<T> to_centroid(T const& v)\r
+{\r
+ return detail::to_centroid<T>(v);\r
+}\r
+\r
+/*!\r
+\brief Generate to_furthest() relationship.\r
+\r
+Generate a nearest query Point and Value's Indexable relationship while calculating\r
+distances. This function may be used to define that knn query should calculate distances\r
+as biggest as possible between query Point and Indexable's points. In other words it\r
+should be the distance to the furthest Indexable's point. This function may be also used\r
+to define distances bounds which indicates that Indexable's furthest point should be\r
+closer or further than value v.\r
+\r
+\ingroup nearest_relations\r
+\r
+\tparam T Type of wrapped object. This may be a Point for PointRelation or some CoordinateType for\r
+ MinRelation or MaxRelation\r
+\r
+\param v Point or distance value.\r
+*/\r
+template <typename T>\r
+detail::to_furthest<T> to_furthest(T const& v)\r
+{\r
+ return detail::to_furthest<T>(v);\r
+}\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+\r
+// distance predicates generators\r
+\r
+/*!\r
+\brief Generate unbounded() distance predicate.\r
+\r
+Generate a distance predicate. This defines distances bounds which are used by knn query.\r
+This function indicates that there is no distance bounds and Values should be returned\r
+if distances between Point and Indexable are the smallest. Distance calculation is defined\r
+by PointRelation. This is default nearest predicate.\r
+\r
+\ingroup distance_predicates\r
+\r
+\tparam PointRelation PointRelation type.\r
+\r
+\param pr The point relation. This may be generated by \c index::to_nearest(),\r
+ \c index::to_centroid() or \c index::to_furthest() with \c Point passed as a parameter.\r
+*/\r
+//template <typename PointRelation>\r
+//inline detail::unbounded<PointRelation>\r
+//unbounded(PointRelation const& pr)\r
+//{\r
+// return detail::unbounded<PointRelation>(pr);\r
+//}\r
+\r
+/*!\r
+\brief Generate min_bounded() distance predicate.\r
+\r
+Generate a distance predicate. This defines distances bounds which are used by knn query.\r
+This function indicates that Values should be returned only if distances between Point and\r
+Indexable are greater or equal to some min_distance passed in MinRelation. Check for closest Value is\r
+defined by PointRelation. So it is possible e.g. to return Values with centroids closest to some\r
+Point but only if nearest points are further than some distance.\r
+\r
+\ingroup distance_predicates\r
+\r
+\tparam PointRelation PointRelation type.\r
+\tparam MinRelation MinRelation type.\r
+\r
+\param pr The point relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with \c Point passed as a parameter.\r
+\param minr The minimum bound relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.\r
+*/\r
+//template <typename PointRelation, typename MinRelation>\r
+//inline detail::min_bounded<PointRelation, MinRelation>\r
+//min_bounded(PointRelation const& pr, MinRelation const& minr)\r
+//{\r
+// return detail::min_bounded<PointRelation, MinRelation>(pr, minr);\r
+//}\r
+\r
+/*!\r
+\brief Generate max_bounded() distance predicate.\r
+\r
+Generate a distance predicate. This defines distances bounds which are used by knn query.\r
+This function indicates that Values should be returned only if distances between Point and\r
+Indexable are lesser or equal to some max_distance passed in MaxRelation. Check for closest Value is\r
+defined by PointRelation. So it is possible e.g. to return Values with centroids closest to some\r
+Point but only if nearest points are closer than some distance.\r
+\r
+\ingroup distance_predicates\r
+\r
+\tparam PointRelation PointRelation type.\r
+\tparam MaxRelation MaxRelation type.\r
+\r
+\param pr The point relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with \c Point passed as a parameter.\r
+\param maxr The maximum bound relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.\r
+*/\r
+//template <typename PointRelation, typename MaxRelation>\r
+//inline detail::max_bounded<PointRelation, MaxRelation>\r
+//max_bounded(PointRelation const& pr, MaxRelation const& maxr)\r
+//{\r
+// return detail::max_bounded<PointRelation, MaxRelation>(pr, maxr);\r
+//}\r
+\r
+/*!\r
+\brief Generate bounded() distance predicate.\r
+\r
+Generate a distance predicate. This defines distances bounds which are used by knn query.\r
+This function indicates that Values should be returned only if distances between Point and\r
+Indexable are greater or equal to some min_distance passed in MinRelation and lesser or equal to\r
+some max_distance passed in MaxRelation. Check for closest Value is defined by PointRelation.\r
+So it is possible e.g. to return Values with centroids closest to some Point but only if nearest\r
+points are further than some distance and closer than some other distance.\r
+\r
+\ingroup distance_predicates\r
+\r
+\tparam PointRelation PointRelation type.\r
+\tparam MinRelation MinRelation type.\r
+\tparam MaxRelation MaxRelation type.\r
+\r
+\param pr The point relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with \c Point passed as a parameter.\r
+\param minr The minimum bound relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.\r
+\param maxr The maximum bound relation. This may be generated by \c to_nearest(),\r
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.\r
+*/\r
+//template <typename PointRelation, typename MinRelation, typename MaxRelation>\r
+//inline detail::bounded<PointRelation, MinRelation, MaxRelation>\r
+//bounded(PointRelation const& pr, MinRelation const& minr, MaxRelation const& maxr)\r
+//{\r
+// return detail::bounded<PointRelation, MinRelation, MaxRelation>(pr, minr, maxr);\r
+//}\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP\r
+#define BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/index/indexable.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename geometry::tag<Geometry>::type>\r
+struct equals\r
+{\r
+ inline static bool apply(Geometry const& g1, Geometry const& g2)\r
+ {\r
+ return geometry::equals(g1, g2);\r
+ }\r
+};\r
+\r
+template <typename Geometry, typename Tag>\r
+struct equals<Geometry *, Tag>\r
+{\r
+ inline static bool apply(const Geometry * g1, const Geometry * g2)\r
+ {\r
+ return g1 == g2;\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct equals<T, void>\r
+{\r
+ inline static bool apply(T const& v1, T const& v2)\r
+ {\r
+ return v1 == v2;\r
+ }\r
+};\r
+\r
+template <typename Tuple, size_t I, size_t N>\r
+struct tuple_equals\r
+{\r
+ inline static bool apply(Tuple const& t1, Tuple const& t2)\r
+ {\r
+ typedef typename boost::tuples::element<I, Tuple>::type T;\r
+\r
+ return equals<T>::apply(boost::get<I>(t1), boost::get<I>(t2))\r
+ && tuple_equals<Tuple, I+1, N>::apply(t1, t2);\r
+ }\r
+};\r
+\r
+template <typename Tuple, size_t I>\r
+struct tuple_equals<Tuple, I, I>\r
+{\r
+ inline static bool apply(Tuple const&, Tuple const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+// TODO: Consider this: Since equal_to<> is using geometry::equals() it's possible that\r
+// two compared Indexables are not exactly the same! They will be spatially equal\r
+// but not strictly equal. Consider 2 Segments with reversed order of points.\r
+// Therefore it's possible that during the Value removal different value will be\r
+// removed than the one that was passed.\r
+\r
+/*!\r
+\brief The function object comparing Values.\r
+\r
+It compares Geometries using geometry::equals() function. Other types are compared using operator==.\r
+The default version handles Values which are Indexables.\r
+This template is also specialized for std::pair<T1, T2> and boost::tuple<...>.\r
+\r
+\tparam Value The type of objects which are compared by this function object.\r
+\tparam IsIndexable If true, Values are compared using boost::geometry::equals() functions.\r
+*/\r
+template <typename Value,\r
+ bool IsIndexable = is_indexable<Value>::value>\r
+struct equal_to\r
+{\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef bool result_type;\r
+ \r
+ /*!\r
+ \brief Compare values. If Value is a Geometry geometry::equals() function is used.\r
+ \r
+ \param l First value.\r
+ \param r Second value.\r
+ \return true if values are equal.\r
+ */\r
+ inline bool operator()(Value const& l, Value const& r) const\r
+ {\r
+ return detail::equals<Value>::apply(l ,r);\r
+ }\r
+};\r
+\r
+/*!\r
+\brief The function object comparing Values.\r
+\r
+This specialization compares values of type std::pair<T1, T2>.\r
+It compares pairs' first values, then second values.\r
+\r
+\tparam T1 The first type.\r
+\tparam T2 The second type.\r
+*/\r
+template <typename T1, typename T2>\r
+struct equal_to<std::pair<T1, T2>, false>\r
+{\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef bool result_type;\r
+\r
+ /*!\r
+ \brief Compare values. If pair<> Value member is a Geometry geometry::equals() function is used.\r
+ \r
+ \param l First value.\r
+ \param r Second value.\r
+ \return true if values are equal.\r
+ */\r
+ inline bool operator()(std::pair<T1, T2> const& l, std::pair<T1, T2> const& r) const\r
+ {\r
+ return detail::equals<T1>::apply(l.first, r.first)\r
+ && detail::equals<T2>::apply(l.second, r.second);\r
+ }\r
+};\r
+\r
+/*!\r
+\brief The function object comparing Values.\r
+\r
+This specialization compares values of type boost::tuple<...>.\r
+It compares all members of the tuple from the first one to the last one.\r
+*/\r
+template <typename T0, typename T1, typename T2, typename T3, typename T4,\r
+ typename T5, typename T6, typename T7, typename T8, typename T9>\r
+struct equal_to<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false>\r
+{\r
+ typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;\r
+\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef bool result_type;\r
+\r
+ /*!\r
+ \brief Compare values. If tuple<> Value member is a Geometry geometry::equals() function is used.\r
+ \r
+ \param l First value.\r
+ \param r Second value.\r
+ \return true if values are equal.\r
+ */\r
+ inline bool operator()(value_type const& l, value_type const& r) const\r
+ {\r
+ return detail::tuple_equals<\r
+ value_type, 0, boost::tuples::length<value_type>::value\r
+ >::apply(l ,r);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+\r
+#include <tuple>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+template <typename Tuple, size_t I, size_t N>\r
+struct std_tuple_equals\r
+{\r
+ inline static bool apply(Tuple const& t1, Tuple const& t2)\r
+ {\r
+ typedef typename std::tuple_element<I, Tuple>::type T;\r
+\r
+ return equals<T>::apply(std::get<I>(t1), std::get<I>(t2))\r
+ && std_tuple_equals<Tuple, I+1, N>::apply(t1, t2);\r
+ }\r
+};\r
+\r
+template <typename Tuple, size_t I>\r
+struct std_tuple_equals<Tuple, I, I>\r
+{\r
+ inline static bool apply(Tuple const&, Tuple const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+/*!\r
+\brief The function object comparing Values.\r
+\r
+This specialization compares values of type std::tuple<Args...>.\r
+It's defined if the compiler supports tuples and variadic templates.\r
+It compares all members of the tuple from the first one to the last one.\r
+*/\r
+template <typename ...Args>\r
+struct equal_to<std::tuple<Args...>, false>\r
+{\r
+ typedef std::tuple<Args...> value_type;\r
+\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef bool result_type;\r
+\r
+ /*!\r
+ \brief Compare values. If tuple<> Value member is a Geometry geometry::equals() function is used.\r
+ \r
+ \param l First value.\r
+ \param r Second value.\r
+ \return true if values are equal.\r
+ */\r
+ bool operator()(value_type const& l, value_type const& r) const\r
+ {\r
+ return detail::std_tuple_equals<\r
+ value_type, 0, std::tuple_size<value_type>::value\r
+ >::apply(l ,r);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+/*!\r
+\brief The function object comparing Values.\r
+\r
+The default version handles Values which are Indexables, std::pair<T1, T2>, boost::tuple<...>\r
+and std::tuple<...> if STD tuples and variadic templates are supported.\r
+All members are compared from left to right, Geometries using boost::geometry::equals() function,\r
+other types using operator==.\r
+\r
+\tparam Value The type of objects which are compared by this function object.\r
+*/\r
+template <typename Value>\r
+struct equal_to\r
+ : detail::equal_to<Value>\r
+{\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef typename detail::equal_to<Value>::result_type result_type;\r
+ \r
+ /*!\r
+ \brief Compare Values.\r
+ \r
+ \param l First value.\r
+ \param r Second value.\r
+ \return true if Values are equal.\r
+ */\r
+ inline bool operator()(Value const& l, Value const& r) const\r
+ {\r
+ return detail::equal_to<Value>::operator()(l ,r);\r
+ }\r
+};\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_INDEXABLE_HPP\r
+#define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/index/detail/is_indexable.hpp>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+/*!\r
+\brief The function object extracting Indexable from Value.\r
+\r
+It translates Value object to Indexable object. The default version handles Values which are Indexables.\r
+This template is also specialized for std::pair<Indexable, T2>, boost::tuple<Indexable, ...>\r
+and std::tuple<Indexable, ...>.\r
+\r
+\tparam Value The Value type which may be translated directly to the Indexable.\r
+\tparam IsIndexable If true, the const reference to Value is returned.\r
+*/\r
+template <typename Value, bool IsIndexable = is_indexable<Value>::value>\r
+struct indexable\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (detail::is_indexable<Value>::value),\r
+ NOT_VALID_INDEXABLE_TYPE,\r
+ (Value)\r
+ );\r
+\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef Value const& result_type;\r
+\r
+ /*!\r
+ \brief Return indexable extracted from the value.\r
+ \r
+ \param v The value.\r
+ \return The indexable.\r
+ */\r
+ inline result_type operator()(Value const& v) const\r
+ {\r
+ return v;\r
+ }\r
+};\r
+\r
+/*!\r
+\brief The function object extracting Indexable from Value.\r
+\r
+This specialization translates from std::pair<Indexable, T2>.\r
+\r
+\tparam Indexable The Indexable type.\r
+\tparam T2 The second type.\r
+*/\r
+template <typename Indexable, typename T2>\r
+struct indexable<std::pair<Indexable, T2>, false>\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (detail::is_indexable<Indexable>::value),\r
+ NOT_VALID_INDEXABLE_TYPE,\r
+ (Indexable)\r
+ );\r
+\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef Indexable const& result_type;\r
+\r
+ /*!\r
+ \brief Return indexable extracted from the value.\r
+ \r
+ \param v The value.\r
+ \return The indexable.\r
+ */\r
+ inline result_type operator()(std::pair<Indexable, T2> const& v) const\r
+ {\r
+ return v.first;\r
+ }\r
+};\r
+\r
+/*!\r
+\brief The function object extracting Indexable from Value.\r
+\r
+This specialization translates from boost::tuple<Indexable, ...>.\r
+\r
+\tparam Indexable The Indexable type.\r
+*/\r
+template <typename Indexable, typename T1, typename T2, typename T3, typename T4,\r
+ typename T5, typename T6, typename T7, typename T8, typename T9>\r
+struct indexable<boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false>\r
+{\r
+ typedef boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;\r
+\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (detail::is_indexable<Indexable>::value),\r
+ NOT_VALID_INDEXABLE_TYPE,\r
+ (Indexable)\r
+ );\r
+\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef Indexable const& result_type;\r
+\r
+ /*!\r
+ \brief Return indexable extracted from the value.\r
+ \r
+ \param v The value.\r
+ \return The indexable.\r
+ */\r
+ inline result_type operator()(value_type const& v) const\r
+ {\r
+ return boost::get<0>(v);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+\r
+#include <tuple>\r
+\r
+namespace boost { namespace geometry { namespace index { namespace detail {\r
+\r
+/*!\r
+\brief The function object extracting Indexable from Value.\r
+\r
+This specialization translates from std::tuple<Indexable, Args...>.\r
+It's defined if the compiler supports tuples and variadic templates.\r
+\r
+\tparam Indexable The Indexable type.\r
+*/\r
+template <typename Indexable, typename ...Args>\r
+struct indexable<std::tuple<Indexable, Args...>, false>\r
+{\r
+ typedef std::tuple<Indexable, Args...> value_type;\r
+\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (detail::is_indexable<Indexable>::value),\r
+ NOT_VALID_INDEXABLE_TYPE,\r
+ (Indexable)\r
+ );\r
+\r
+ /*! \brief The type of result returned by function object. */\r
+ typedef Indexable const& result_type;\r
+\r
+ /*!\r
+ \brief Return indexable extracted from the value.\r
+ \r
+ \param v The value.\r
+ \return The indexable.\r
+ */\r
+ result_type operator()(value_type const& v) const\r
+ {\r
+ return std::get<0>(v);\r
+ }\r
+};\r
+\r
+}}}} // namespace boost::geometry::index::detail\r
+\r
+#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+/*!\r
+\brief The function object extracting Indexable from Value.\r
+\r
+It translates Value object to Indexable object. By default, it can handle Values which are Indexables,\r
+std::pair<Indexable, T2>, boost::tuple<Indexable, ...> and std::tuple<Indexable, ...> if STD tuples\r
+and variadic templates are supported.\r
+\r
+\tparam Value The Value type which may be translated directly to the Indexable.\r
+*/\r
+template <typename Value>\r
+struct indexable\r
+ : detail::indexable<Value>\r
+{\r
+ /*! \brief The type of result returned by function object. It should be const Indexable reference. */\r
+ typedef typename detail::indexable<Value>::result_type result_type;\r
+\r
+ /*!\r
+ \brief Return indexable extracted from the value.\r
+ \r
+ \param v The value.\r
+ \return The indexable.\r
+ */\r
+ inline result_type operator()(Value const& v) const\r
+ {\r
+ return detail::indexable<Value>::operator()(v);\r
+ }\r
+};\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_INDEXABLE_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Insert iterator\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_INSERTER_HPP\r
+#define BOOST_GEOMETRY_INDEX_INSERTER_HPP\r
+\r
+#include <iterator>\r
+\r
+/*!\r
+\defgroup inserters Inserters (boost::geometry::index::)\r
+*/\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+template <class Container>\r
+class insert_iterator :\r
+ public std::iterator<std::output_iterator_tag, void, void, void, void>\r
+{\r
+public:\r
+ typedef Container container_type;\r
+\r
+ inline explicit insert_iterator(Container & c)\r
+ : container(&c)\r
+ {}\r
+ \r
+ insert_iterator & operator=(typename Container::value_type const& value)\r
+ {\r
+ container->insert(value);\r
+ return *this;\r
+ }\r
+\r
+ insert_iterator & operator* ()\r
+ {\r
+ return *this;\r
+ }\r
+\r
+ insert_iterator & operator++ ()\r
+ {\r
+ return *this;\r
+ }\r
+\r
+ insert_iterator operator++(int)\r
+ {\r
+ return *this;\r
+ }\r
+\r
+private:\r
+ Container * container;\r
+};\r
+\r
+/*!\r
+\brief Insert iterator generator.\r
+\r
+Returns insert iterator capable to insert values to the container\r
+(spatial index) which has member function insert(value_type const&) defined.\r
+\r
+\ingroup inserters\r
+\r
+\param c The reference to the container (spatial index) to which values will be inserted.\r
+\r
+\return The insert iterator inserting values to the container.\r
+*/\r
+template <typename Container>\r
+insert_iterator<Container> inserter(Container & c)\r
+{\r
+ return insert_iterator<Container>(c);\r
+}\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_INSERTER_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree algorithms parameters\r
+//\r
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP\r
+#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP\r
+\r
+#include <limits>\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+namespace detail { \r
+\r
+template <size_t MaxElements>\r
+struct default_min_elements_s\r
+{\r
+ static const size_t raw_value = (MaxElements * 3) / 10;\r
+ static const size_t value = 1 <= raw_value ? raw_value : 1;\r
+};\r
+\r
+inline size_t default_min_elements_d()\r
+{\r
+ return (std::numeric_limits<size_t>::max)();\r
+}\r
+\r
+inline size_t default_min_elements_d_calc(size_t max_elements, size_t min_elements)\r
+{\r
+ if ( default_min_elements_d() == min_elements )\r
+ {\r
+ size_t raw_value = (max_elements * 3) / 10;\r
+ return 1 <= raw_value ? raw_value : 1;\r
+ }\r
+ \r
+ return min_elements;\r
+}\r
+\r
+template <size_t MaxElements>\r
+struct default_rstar_reinserted_elements_s\r
+{\r
+ static const size_t value = (MaxElements * 3) / 10;\r
+};\r
+\r
+inline size_t default_rstar_reinserted_elements_d()\r
+{\r
+ return (std::numeric_limits<size_t>::max)();\r
+}\r
+\r
+inline size_t default_rstar_reinserted_elements_d_calc(size_t max_elements, size_t reinserted_elements)\r
+{\r
+ if ( default_rstar_reinserted_elements_d() == reinserted_elements )\r
+ {\r
+ return (max_elements * 3) / 10;\r
+ }\r
+ \r
+ return reinserted_elements;\r
+}\r
+\r
+} // namespace detail\r
+\r
+/*!\r
+\brief Linear r-tree creation algorithm parameters.\r
+\r
+\tparam MaxElements Maximum number of elements in nodes.\r
+\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.\r
+*/\r
+template <size_t MaxElements,\r
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value>\r
+struct linear\r
+{\r
+ BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),\r
+ INVALID_STATIC_MIN_MAX_PARAMETERS, (linear));\r
+\r
+ static const size_t max_elements = MaxElements;\r
+ static const size_t min_elements = MinElements;\r
+\r
+ static size_t get_max_elements() { return MaxElements; }\r
+ static size_t get_min_elements() { return MinElements; }\r
+};\r
+\r
+/*!\r
+\brief Quadratic r-tree creation algorithm parameters.\r
+\r
+\tparam MaxElements Maximum number of elements in nodes.\r
+\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.\r
+*/\r
+template <size_t MaxElements,\r
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value>\r
+struct quadratic\r
+{\r
+ BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),\r
+ INVALID_STATIC_MIN_MAX_PARAMETERS, (quadratic));\r
+\r
+ static const size_t max_elements = MaxElements;\r
+ static const size_t min_elements = MinElements;\r
+\r
+ static size_t get_max_elements() { return MaxElements; }\r
+ static size_t get_min_elements() { return MinElements; }\r
+};\r
+\r
+/*!\r
+\brief R*-tree creation algorithm parameters.\r
+\r
+\tparam MaxElements Maximum number of elements in nodes.\r
+\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.\r
+\tparam ReinsertedElements The number of elements reinserted by forced reinsertions algorithm.\r
+ If 0 forced reinsertions are disabled. Maximum value is Max+1-Min.\r
+ Greater values are truncated. Default: 0.3*Max.\r
+\tparam OverlapCostThreshold The number of most suitable leafs taken into account while choosing\r
+ the leaf node to which currently inserted value will be added. If\r
+ value is in range (0, MaxElements) - the algorithm calculates\r
+ nearly minimum overlap cost, otherwise all leafs are analyzed\r
+ and true minimum overlap cost is calculated. Default: 32.\r
+*/\r
+template <size_t MaxElements,\r
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value,\r
+ size_t ReinsertedElements = detail::default_rstar_reinserted_elements_s<MaxElements>::value,\r
+ size_t OverlapCostThreshold = 32>\r
+struct rstar\r
+{\r
+ BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),\r
+ INVALID_STATIC_MIN_MAX_PARAMETERS, (rstar));\r
+\r
+ static const size_t max_elements = MaxElements;\r
+ static const size_t min_elements = MinElements;\r
+ static const size_t reinserted_elements = ReinsertedElements;\r
+ static const size_t overlap_cost_threshold = OverlapCostThreshold;\r
+\r
+ static size_t get_max_elements() { return MaxElements; }\r
+ static size_t get_min_elements() { return MinElements; }\r
+ static size_t get_reinserted_elements() { return ReinsertedElements; }\r
+ static size_t get_overlap_cost_threshold() { return OverlapCostThreshold; }\r
+};\r
+\r
+//template <size_t MaxElements, size_t MinElements>\r
+//struct kmeans\r
+//{\r
+// static const size_t max_elements = MaxElements;\r
+// static const size_t min_elements = MinElements;\r
+//};\r
+\r
+/*!\r
+\brief Linear r-tree creation algorithm parameters - run-time version.\r
+*/\r
+class dynamic_linear\r
+{\r
+public:\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ \param max_elements Maximum number of elements in nodes.\r
+ \param min_elements Minimum number of elements in nodes. Default: 0.3*Max.\r
+ */\r
+ dynamic_linear(size_t max_elements,\r
+ size_t min_elements = detail::default_min_elements_d())\r
+ : m_max_elements(max_elements)\r
+ , m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))\r
+ {\r
+ if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))\r
+ detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_linear");\r
+ }\r
+\r
+ size_t get_max_elements() const { return m_max_elements; }\r
+ size_t get_min_elements() const { return m_min_elements; }\r
+\r
+private:\r
+ size_t m_max_elements;\r
+ size_t m_min_elements;\r
+};\r
+\r
+/*!\r
+\brief Quadratic r-tree creation algorithm parameters - run-time version.\r
+*/\r
+class dynamic_quadratic\r
+{\r
+public:\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ \param max_elements Maximum number of elements in nodes.\r
+ \param min_elements Minimum number of elements in nodes. Default: 0.3*Max.\r
+ */\r
+ dynamic_quadratic(size_t max_elements,\r
+ size_t min_elements = detail::default_min_elements_d())\r
+ : m_max_elements(max_elements)\r
+ , m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))\r
+ {\r
+ if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))\r
+ detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_quadratic");\r
+ }\r
+\r
+ size_t get_max_elements() const { return m_max_elements; }\r
+ size_t get_min_elements() const { return m_min_elements; }\r
+\r
+private:\r
+ size_t m_max_elements;\r
+ size_t m_min_elements;\r
+};\r
+\r
+/*!\r
+\brief R*-tree creation algorithm parameters - run-time version.\r
+*/\r
+class dynamic_rstar\r
+{\r
+public:\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ \param max_elements Maximum number of elements in nodes.\r
+ \param min_elements Minimum number of elements in nodes. Default: 0.3*Max.\r
+ \param reinserted_elements The number of elements reinserted by forced reinsertions algorithm.\r
+ If 0 forced reinsertions are disabled. Maximum value is Max-Min+1.\r
+ Greater values are truncated. Default: 0.3*Max.\r
+ \param overlap_cost_threshold The number of most suitable leafs taken into account while choosing\r
+ the leaf node to which currently inserted value will be added. If\r
+ value is in range (0, MaxElements) - the algorithm calculates\r
+ nearly minimum overlap cost, otherwise all leafs are analyzed\r
+ and true minimum overlap cost is calculated. Default: 32.\r
+ */\r
+ dynamic_rstar(size_t max_elements,\r
+ size_t min_elements = detail::default_min_elements_d(),\r
+ size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),\r
+ size_t overlap_cost_threshold = 32)\r
+ : m_max_elements(max_elements)\r
+ , m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))\r
+ , m_reinserted_elements(detail::default_rstar_reinserted_elements_d_calc(max_elements, reinserted_elements))\r
+ , m_overlap_cost_threshold(overlap_cost_threshold)\r
+ {\r
+ if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))\r
+ detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_rstar");\r
+ }\r
+\r
+ size_t get_max_elements() const { return m_max_elements; }\r
+ size_t get_min_elements() const { return m_min_elements; }\r
+ size_t get_reinserted_elements() const { return m_reinserted_elements; }\r
+ size_t get_overlap_cost_threshold() const { return m_overlap_cost_threshold; }\r
+\r
+private:\r
+ size_t m_max_elements;\r
+ size_t m_min_elements;\r
+ size_t m_reinserted_elements;\r
+ size_t m_overlap_cost_threshold;\r
+};\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_PARAMETERS_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// Spatial query predicates\r
+//\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_PREDICATES_HPP\r
+#define BOOST_GEOMETRY_INDEX_PREDICATES_HPP\r
+\r
+#include <utility>\r
+#include <boost/tuple/tuple.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/index/detail/predicates.hpp>\r
+#include <boost/geometry/index/detail/tuples.hpp>\r
+\r
+/*!\r
+\defgroup predicates Predicates (boost::geometry::index::)\r
+*/\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+/*!\r
+\brief Generate \c contains() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::within(Geometry, Indexable)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::contains(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::contains_tag, false>\r
+contains(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::contains_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+/*!\r
+\brief Generate \c covered_by() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::covered_by(Indexable, Geometry)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::covered_by(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::covered_by_tag, false>\r
+covered_by(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::covered_by_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+/*!\r
+\brief Generate \c covers() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::covered_by(Geometry, Indexable)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::covers(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::covers_tag, false>\r
+covers(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::covers_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+/*!\r
+\brief Generate \c disjoint() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::disjoint(Indexable, Geometry)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::disjoint(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::disjoint_tag, false>\r
+disjoint(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::disjoint_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+/*!\r
+\brief Generate \c intersects() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::intersects(Indexable, Geometry)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::intersects(box), std::back_inserter(result));\r
+bgi::query(spatial_index, bgi::intersects(ring), std::back_inserter(result));\r
+bgi::query(spatial_index, bgi::intersects(polygon), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::intersects_tag, false>\r
+intersects(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::intersects_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+/*!\r
+\brief Generate \c overlaps() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::overlaps(Indexable, Geometry)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::overlaps(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::overlaps_tag, false>\r
+overlaps(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::overlaps_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+\r
+/*!\r
+\brief Generate \c touches() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::touches(Indexable, Geometry)</tt>\r
+returns true.\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::touches_tag, false>\r
+touches(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::touches_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+\r
+/*!\r
+\brief Generate \c within() predicate.\r
+\r
+Generate a predicate defining Value and Geometry relationship.\r
+Value will be returned by the query if <tt>bg::within(Indexable, Geometry)</tt>\r
+returns true.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::within(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam Geometry The Geometry type.\r
+\r
+\param g The Geometry object.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::spatial_predicate<Geometry, detail::predicates::within_tag, false>\r
+within(Geometry const& g)\r
+{\r
+ return detail::predicates::spatial_predicate\r
+ <\r
+ Geometry,\r
+ detail::predicates::within_tag,\r
+ false\r
+ >(g);\r
+}\r
+\r
+/*!\r
+\brief Generate satisfies() predicate.\r
+\r
+A wrapper around user-defined UnaryPredicate checking if Value should be returned by spatial query.\r
+\r
+\par Example\r
+\verbatim\r
+bool is_red(Value const& v) { return v.is_red(); }\r
+\r
+struct is_red_o {\r
+template <typename Value> bool operator()(Value const& v) { return v.is_red(); }\r
+}\r
+\r
+// ...\r
+\r
+rt.query(index::intersects(box) && index::satisfies(is_red),\r
+std::back_inserter(result));\r
+\r
+rt.query(index::intersects(box) && index::satisfies(is_red_o()),\r
+std::back_inserter(result));\r
+\r
+#ifndef BOOST_NO_CXX11_LAMBDAS\r
+rt.query(index::intersects(box) && index::satisfies([](Value const& v) { return v.is_red(); }),\r
+std::back_inserter(result));\r
+#endif\r
+\endverbatim\r
+\r
+\ingroup predicates\r
+\r
+\tparam UnaryPredicate A type of unary predicate function or function object.\r
+\r
+\param pred The unary predicate function or function object.\r
+*/\r
+template <typename UnaryPredicate> inline\r
+detail::predicates::satisfies<UnaryPredicate, false>\r
+satisfies(UnaryPredicate const& pred)\r
+{\r
+ return detail::predicates::satisfies<UnaryPredicate, false>(pred);\r
+}\r
+\r
+/*!\r
+\brief Generate nearest() predicate.\r
+\r
+When nearest predicate is passed to the query, k-nearest neighbour search will be performed.\r
+\c nearest() predicate takes a \c Geometry from which distances to \c Values are calculated\r
+and the maximum number of \c Values that should be returned. Internally\r
+boost::geometry::comparable_distance() is used to perform the calculation.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::nearest(pt, 5), std::back_inserter(result));\r
+bgi::query(spatial_index, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));\r
+bgi::query(spatial_index, bgi::nearest(box, 5), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\warning\r
+Only one \c nearest() predicate may be used in a query.\r
+\r
+\ingroup predicates\r
+\r
+\param geometry The geometry from which distance is calculated.\r
+\param k The maximum number of values to return.\r
+*/\r
+template <typename Geometry> inline\r
+detail::predicates::nearest<Geometry>\r
+nearest(Geometry const& geometry, unsigned k)\r
+{\r
+ return detail::predicates::nearest<Geometry>(geometry, k);\r
+}\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+\r
+/*!\r
+\brief Generate path() predicate.\r
+\r
+When path predicate is passed to the query, the returned values are k values along the path closest to\r
+its begin. \c path() predicate takes a \c Segment or a \c Linestring defining the path and the maximum\r
+number of \c Values that should be returned.\r
+\r
+\par Example\r
+\verbatim\r
+bgi::query(spatial_index, bgi::path(segment, 5), std::back_inserter(result));\r
+bgi::query(spatial_index, bgi::path(linestring, 5) && bgi::intersects(box), std::back_inserter(result));\r
+\endverbatim\r
+\r
+\warning\r
+Only one distance predicate (\c nearest() or \c path()) may be used in a query.\r
+\r
+\ingroup predicates\r
+\r
+\param linestring The path along which distance is calculated.\r
+\param k The maximum number of values to return.\r
+*/\r
+template <typename SegmentOrLinestring> inline\r
+detail::predicates::path<SegmentOrLinestring>\r
+path(SegmentOrLinestring const& linestring, unsigned k)\r
+{\r
+ return detail::predicates::path<SegmentOrLinestring>(linestring, k);\r
+}\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+\r
+namespace detail { namespace predicates {\r
+\r
+// operator! generators\r
+\r
+template <typename Fun, bool Negated> inline\r
+satisfies<Fun, !Negated>\r
+operator!(satisfies<Fun, Negated> const& p)\r
+{\r
+ return satisfies<Fun, !Negated>(p);\r
+}\r
+\r
+template <typename Geometry, typename Tag, bool Negated> inline\r
+spatial_predicate<Geometry, Tag, !Negated>\r
+operator!(spatial_predicate<Geometry, Tag, Negated> const& p)\r
+{\r
+ return spatial_predicate<Geometry, Tag, !Negated>(p.geometry);\r
+}\r
+\r
+// operator&& generators\r
+\r
+template <typename Pred1, typename Pred2> inline\r
+boost::tuples::cons<\r
+ Pred1,\r
+ boost::tuples::cons<Pred2, boost::tuples::null_type>\r
+>\r
+operator&&(Pred1 const& p1, Pred2 const& p2)\r
+{\r
+ /*typedef typename boost::mpl::if_c<is_predicate<Pred1>::value, Pred1, Pred1 const&>::type stored1;\r
+ typedef typename boost::mpl::if_c<is_predicate<Pred2>::value, Pred2, Pred2 const&>::type stored2;*/\r
+ namespace bt = boost::tuples;\r
+\r
+ return\r
+ bt::cons< Pred1, bt::cons<Pred2, bt::null_type> >\r
+ ( p1, bt::cons<Pred2, bt::null_type>(p2, bt::null_type()) );\r
+}\r
+\r
+template <typename Head, typename Tail, typename Pred> inline\r
+typename tuples::push_back<\r
+ boost::tuples::cons<Head, Tail>, Pred\r
+>::type\r
+operator&&(boost::tuples::cons<Head, Tail> const& t, Pred const& p)\r
+{\r
+ //typedef typename boost::mpl::if_c<is_predicate<Pred>::value, Pred, Pred const&>::type stored;\r
+ namespace bt = boost::tuples;\r
+\r
+ return\r
+ tuples::push_back<\r
+ bt::cons<Head, Tail>, Pred\r
+ >::apply(t, p);\r
+}\r
+ \r
+}} // namespace detail::predicates\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_PREDICATES_HPP\r
--- /dev/null
+// Boost.Geometry Index\r
+//\r
+// R-tree implementation\r
+//\r
+// Copyright (c) 2008 Federico J. Fernandez.\r
+// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.\r
+//\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_RTREE_HPP\r
+#define BOOST_GEOMETRY_INDEX_RTREE_HPP\r
+\r
+// STD\r
+#include <algorithm>\r
+\r
+// Boost\r
+#include <boost/tuple/tuple.hpp>\r
+#include <boost/move/move.hpp>\r
+\r
+// Boost.Geometry\r
+#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>\r
+#include <boost/geometry/algorithms/centroid.hpp>\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+#include <boost/geometry/algorithms/intersects.hpp>\r
+#include <boost/geometry/algorithms/overlaps.hpp>\r
+#include <boost/geometry/algorithms/touches.hpp>\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#include <boost/geometry/geometries/point.hpp>\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/strategies/strategies.hpp>\r
+\r
+// Boost.Geometry.Index\r
+#include <boost/geometry/index/detail/config_begin.hpp>\r
+\r
+#include <boost/geometry/index/detail/assert.hpp>\r
+#include <boost/geometry/index/detail/exception.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/options.hpp>\r
+\r
+#include <boost/geometry/index/indexable.hpp>\r
+#include <boost/geometry/index/equal_to.hpp>\r
+\r
+#include <boost/geometry/index/detail/translator.hpp>\r
+\r
+#include <boost/geometry/index/predicates.hpp>\r
+#include <boost/geometry/index/distance_predicates.hpp>\r
+#include <boost/geometry/index/detail/rtree/adaptors.hpp>\r
+\r
+#include <boost/geometry/index/detail/meta.hpp>\r
+#include <boost/geometry/index/detail/utilities.hpp>\r
+#include <boost/geometry/index/detail/rtree/node/node.hpp>\r
+\r
+#include <boost/geometry/index/detail/algorithms/is_valid.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/iterator.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/remove.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/copy.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/spatial_query.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/distance_query.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/count.hpp>\r
+#include <boost/geometry/index/detail/rtree/visitors/children_box.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/linear/linear.hpp>\r
+#include <boost/geometry/index/detail/rtree/quadratic/quadratic.hpp>\r
+#include <boost/geometry/index/detail/rtree/rstar/rstar.hpp>\r
+//#include <boost/geometry/extensions/index/detail/rtree/kmeans/kmeans.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/pack_create.hpp>\r
+\r
+#include <boost/geometry/index/inserter.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/utilities/view.hpp>\r
+\r
+#include <boost/geometry/index/detail/rtree/iterators.hpp>\r
+#include <boost/geometry/index/detail/rtree/query_iterators.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+// serialization\r
+#include <boost/geometry/index/detail/serialization.hpp>\r
+#endif\r
+\r
+// TODO change the name to bounding_tree\r
+\r
+/*!\r
+\defgroup rtree_functions R-tree free functions (boost::geometry::index::)\r
+*/\r
+\r
+namespace boost { namespace geometry { namespace index {\r
+\r
+/*!\r
+\brief The R-tree spatial index.\r
+\r
+This is self-balancing spatial index capable to store various types of Values\r
+and balancing algorithms.\r
+\r
+\par Parameters\r
+The user must pass a type defining the Parameters which will\r
+be used in rtree creation process. This type is used e.g. to specify balancing\r
+algorithm with specific parameters like min and max number of elements in node.\r
+\r
+\par\r
+Predefined algorithms with compile-time parameters are:\r
+\li <tt>boost::geometry::index::linear</tt>,\r
+ \li <tt>boost::geometry::index::quadratic</tt>,\r
+ \li <tt>boost::geometry::index::rstar</tt>.\r
+\r
+\par\r
+Predefined algorithms with run-time parameters are:\r
+ \li \c boost::geometry::index::dynamic_linear,\r
+ \li \c boost::geometry::index::dynamic_quadratic,\r
+ \li \c boost::geometry::index::dynamic_rstar.\r
+\r
+\par IndexableGetter\r
+The object of IndexableGetter type translates from Value to Indexable each time\r
+r-tree requires it. This means that this operation is done for each Value\r
+access. Therefore the IndexableGetter should return the Indexable by\r
+a reference type. The Indexable should not be calculated since it could harm\r
+the performance. The default IndexableGetter can translate all types adapted\r
+to Point, Box or Segment concepts (called Indexables). Furthermore, it can\r
+handle <tt>std::pair<Indexable, T></tt>, <tt>boost::tuple<Indexable, ...></tt>\r
+and <tt>std::tuple<Indexable, ...></tt> when possible. For example, for Value\r
+of type <tt>std::pair<Box, int></tt>, the default IndexableGetter translates\r
+from <tt>std::pair<Box, int> const&</tt> to <tt>Box const&</tt>.\r
+\r
+\par EqualTo\r
+The object of EqualTo type compares Values and returns <tt>true</tt> if they\r
+are equal. It's similar to <tt>std::equal_to<></tt>. The default EqualTo\r
+returns the result of <tt>boost::geometry::equals()</tt> for types adapted to\r
+some Geometry concept defined in Boost.Geometry and the result of\r
+<tt>operator==</tt> for other types. Components of Pairs and Tuples are\r
+compared left-to-right.\r
+\r
+\tparam Value The type of objects stored in the container.\r
+\tparam Parameters Compile-time parameters.\r
+\tparam IndexableGetter The function object extracting Indexable from Value.\r
+\tparam EqualTo The function object comparing objects of type Value.\r
+\tparam Allocator The allocator used to allocate/deallocate memory,\r
+ construct/destroy nodes and Values.\r
+*/\r
+template <\r
+ typename Value,\r
+ typename Parameters,\r
+ typename IndexableGetter = index::indexable<Value>,\r
+ typename EqualTo = index::equal_to<Value>,\r
+ typename Allocator = std::allocator<Value>\r
+>\r
+class rtree\r
+{\r
+ BOOST_COPYABLE_AND_MOVABLE(rtree)\r
+\r
+public:\r
+ /*! \brief The type of Value stored in the container. */\r
+ typedef Value value_type;\r
+ /*! \brief R-tree parameters type. */\r
+ typedef Parameters parameters_type;\r
+ /*! \brief The function object extracting Indexable from Value. */\r
+ typedef IndexableGetter indexable_getter;\r
+ /*! \brief The function object comparing objects of type Value. */\r
+ typedef EqualTo value_equal;\r
+ /*! \brief The type of allocator used by the container. */\r
+ typedef Allocator allocator_type;\r
+\r
+ // TODO: SHOULD THIS TYPE BE REMOVED?\r
+ /*! \brief The Indexable type to which Value is translated. */\r
+ typedef typename index::detail::indexable_type<\r
+ detail::translator<IndexableGetter, EqualTo>\r
+ >::type indexable_type;\r
+\r
+ /*! \brief The Box type used by the R-tree. */\r
+ typedef geometry::model::box<\r
+ geometry::model::point<\r
+ typename coordinate_type<indexable_type>::type,\r
+ dimension<indexable_type>::value,\r
+ typename coordinate_system<indexable_type>::type\r
+ >\r
+ >\r
+ bounds_type;\r
+\r
+private:\r
+\r
+ typedef detail::translator<IndexableGetter, EqualTo> translator_type;\r
+\r
+ typedef bounds_type box_type;\r
+ typedef typename detail::rtree::options_type<Parameters>::type options_type;\r
+ typedef typename options_type::node_tag node_tag;\r
+ typedef detail::rtree::allocators<allocator_type, value_type, typename options_type::parameters_type, box_type, node_tag> allocators_type;\r
+\r
+ typedef typename detail::rtree::node<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type node;\r
+ typedef typename detail::rtree::internal_node<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type internal_node;\r
+ typedef typename detail::rtree::leaf<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type leaf;\r
+\r
+ typedef typename allocators_type::node_pointer node_pointer;\r
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;\r
+ typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;\r
+\r
+ friend class detail::rtree::utilities::view<rtree>;\r
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+ friend class detail::rtree::private_view<rtree>;\r
+ friend class detail::rtree::const_private_view<rtree>;\r
+#endif\r
+\r
+public:\r
+\r
+ /*! \brief Type of reference to Value. */\r
+ typedef typename allocators_type::reference reference;\r
+ /*! \brief Type of reference to const Value. */\r
+ typedef typename allocators_type::const_reference const_reference;\r
+ /*! \brief Type of pointer to Value. */\r
+ typedef typename allocators_type::pointer pointer;\r
+ /*! \brief Type of pointer to const Value. */\r
+ typedef typename allocators_type::const_pointer const_pointer;\r
+ /*! \brief Type of difference type. */\r
+ typedef typename allocators_type::difference_type difference_type;\r
+ /*! \brief Unsigned integral type used by the container. */\r
+ typedef typename allocators_type::size_type size_type;\r
+\r
+ /*! \brief Type of const iterator, category ForwardIterator. */\r
+ typedef index::detail::rtree::iterators::iterator\r
+ <\r
+ value_type, options_type, translator_type, box_type, allocators_type\r
+ > const_iterator;\r
+\r
+ /*! \brief Type of const query iterator, category ForwardIterator. */\r
+ typedef index::detail::rtree::iterators::query_iterator\r
+ <\r
+ value_type, allocators_type\r
+ > const_query_iterator;\r
+\r
+public:\r
+\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ \param parameters The parameters object.\r
+ \param getter The function object extracting Indexable from Value.\r
+ \param equal The function object comparing Values.\r
+\r
+ \par Throws\r
+ If allocator default constructor throws.\r
+ */\r
+ inline explicit rtree(parameters_type const& parameters = parameters_type(),\r
+ indexable_getter const& getter = indexable_getter(),\r
+ value_equal const& equal = value_equal())\r
+ : m_members(getter, equal, parameters)\r
+ {}\r
+\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ \param parameters The parameters object.\r
+ \param getter The function object extracting Indexable from Value.\r
+ \param equal The function object comparing Values.\r
+ \param allocator The allocator object.\r
+\r
+ \par Throws\r
+ If allocator copy constructor throws.\r
+ */\r
+ inline rtree(parameters_type const& parameters,\r
+ indexable_getter const& getter,\r
+ value_equal const& equal,\r
+ allocator_type const& allocator)\r
+ : m_members(getter, equal, parameters, allocator)\r
+ {}\r
+\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ The tree is created using packing algorithm.\r
+\r
+ \param first The beginning of the range of Values.\r
+ \param last The end of the range of Values.\r
+ \param parameters The parameters object.\r
+ \param getter The function object extracting Indexable from Value.\r
+ \param equal The function object comparing Values.\r
+ \param allocator The allocator object.\r
+\r
+ \par Throws\r
+ \li If allocator copy constructor throws.\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+ */\r
+ template<typename Iterator>\r
+ inline rtree(Iterator first, Iterator last,\r
+ parameters_type const& parameters = parameters_type(),\r
+ indexable_getter const& getter = indexable_getter(),\r
+ value_equal const& equal = value_equal(),\r
+ allocator_type const& allocator = allocator_type())\r
+ : m_members(getter, equal, parameters, allocator)\r
+ {\r
+ typedef detail::rtree::pack<value_type, options_type, translator_type, box_type, allocators_type> pack;\r
+ size_type vc = 0, ll = 0;\r
+ m_members.root = pack::apply(first, last, vc, ll,\r
+ m_members.parameters(), m_members.translator(), m_members.allocators());\r
+ m_members.values_count = vc;\r
+ m_members.leafs_level = ll;\r
+ }\r
+\r
+ /*!\r
+ \brief The constructor.\r
+\r
+ The tree is created using packing algorithm.\r
+\r
+ \param rng The range of Values.\r
+ \param parameters The parameters object.\r
+ \param getter The function object extracting Indexable from Value.\r
+ \param equal The function object comparing Values.\r
+ \param allocator The allocator object.\r
+\r
+ \par Throws\r
+ \li If allocator copy constructor throws.\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+ */\r
+ template<typename Range>\r
+ inline explicit rtree(Range const& rng,\r
+ parameters_type const& parameters = parameters_type(),\r
+ indexable_getter const& getter = indexable_getter(),\r
+ value_equal const& equal = value_equal(),\r
+ allocator_type const& allocator = allocator_type())\r
+ : m_members(getter, equal, parameters, allocator)\r
+ {\r
+ typedef detail::rtree::pack<value_type, options_type, translator_type, box_type, allocators_type> pack;\r
+ size_type vc = 0, ll = 0;\r
+ m_members.root = pack::apply(::boost::begin(rng), ::boost::end(rng), vc, ll,\r
+ m_members.parameters(), m_members.translator(), m_members.allocators());\r
+ m_members.values_count = vc;\r
+ m_members.leafs_level = ll;\r
+ }\r
+\r
+ /*!\r
+ \brief The destructor.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline ~rtree()\r
+ {\r
+ this->raw_destroy(*this);\r
+ }\r
+\r
+ /*!\r
+ \brief The copy constructor.\r
+\r
+ It uses parameters, translator and allocator from the source tree.\r
+\r
+ \param src The rtree which content will be copied.\r
+\r
+ \par Throws\r
+ \li If allocator copy constructor throws.\r
+ \li If Value copy constructor throws.\r
+ \li If allocation throws or returns invalid value.\r
+ */\r
+ inline rtree(rtree const& src)\r
+ : m_members(src.m_members.indexable_getter(),\r
+ src.m_members.equal_to(),\r
+ src.m_members.parameters(),\r
+ allocator_traits_type::select_on_container_copy_construction(src.get_allocator()))\r
+ {\r
+ this->raw_copy(src, *this, false);\r
+ }\r
+\r
+ /*!\r
+ \brief The copy constructor.\r
+\r
+ It uses Parameters and translator from the source tree.\r
+\r
+ \param src The rtree which content will be copied.\r
+ \param allocator The allocator which will be used.\r
+\r
+ \par Throws\r
+ \li If allocator copy constructor throws.\r
+ \li If Value copy constructor throws.\r
+ \li If allocation throws or returns invalid value.\r
+ */\r
+ inline rtree(rtree const& src, allocator_type const& allocator)\r
+ : m_members(src.m_members.indexable_getter(),\r
+ src.m_members.equal_to(),\r
+ src.m_members.parameters(), allocator)\r
+ {\r
+ this->raw_copy(src, *this, false);\r
+ }\r
+\r
+ /*!\r
+ \brief The moving constructor.\r
+\r
+ It uses parameters, translator and allocator from the source tree.\r
+\r
+ \param src The rtree which content will be moved.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline rtree(BOOST_RV_REF(rtree) src)\r
+ : m_members(src.m_members.indexable_getter(),\r
+ src.m_members.equal_to(),\r
+ src.m_members.parameters(),\r
+ boost::move(src.m_members.allocators()))\r
+ {\r
+ boost::swap(m_members.values_count, src.m_members.values_count);\r
+ boost::swap(m_members.leafs_level, src.m_members.leafs_level);\r
+ boost::swap(m_members.root, src.m_members.root);\r
+ }\r
+\r
+ /*!\r
+ \brief The moving constructor.\r
+\r
+ It uses parameters and translator from the source tree.\r
+\r
+ \param src The rtree which content will be moved.\r
+ \param allocator The allocator.\r
+\r
+ \par Throws\r
+ \li If allocator copy constructor throws.\r
+ \li If Value copy constructor throws (only if allocators aren't equal).\r
+ \li If allocation throws or returns invalid value (only if allocators aren't equal).\r
+ */\r
+ inline rtree(BOOST_RV_REF(rtree) src, allocator_type const& allocator)\r
+ : m_members(src.m_members.indexable_getter(),\r
+ src.m_members.equal_to(),\r
+ src.m_members.parameters(),\r
+ allocator)\r
+ {\r
+ if ( src.m_members.allocators() == allocator )\r
+ {\r
+ boost::swap(m_members.values_count, src.m_members.values_count);\r
+ boost::swap(m_members.leafs_level, src.m_members.leafs_level);\r
+ boost::swap(m_members.root, src.m_members.root);\r
+ }\r
+ else\r
+ {\r
+ this->raw_copy(src, *this, false);\r
+ }\r
+ }\r
+\r
+ /*!\r
+ \brief The assignment operator.\r
+\r
+ It uses parameters and translator from the source tree.\r
+\r
+ \param src The rtree which content will be copied.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor throws.\r
+ \li If allocation throws.\r
+ \li If allocation throws or returns invalid value.\r
+ */\r
+ inline rtree & operator=(BOOST_COPY_ASSIGN_REF(rtree) src)\r
+ {\r
+ if ( &src != this )\r
+ {\r
+ allocators_type & this_allocs = m_members.allocators();\r
+ allocators_type const& src_allocs = src.m_members.allocators();\r
+\r
+ // NOTE: if propagate is true for std allocators on darwin 4.2.1, glibc++\r
+ // (allocators stored as base classes of members_holder)\r
+ // copying them changes values_count, in this case it doesn't cause errors since data must be copied\r
+ \r
+ typedef boost::mpl::bool_<\r
+ allocator_traits_type::propagate_on_container_copy_assignment::value\r
+ > propagate;\r
+ \r
+ if ( propagate::value && !(this_allocs == src_allocs) )\r
+ this->raw_destroy(*this);\r
+ detail::assign_cond(this_allocs, src_allocs, propagate());\r
+\r
+ // It uses m_allocators\r
+ this->raw_copy(src, *this, true);\r
+ }\r
+\r
+ return *this;\r
+ }\r
+\r
+ /*!\r
+ \brief The moving assignment.\r
+\r
+ It uses parameters and translator from the source tree.\r
+\r
+ \param src The rtree which content will be moved.\r
+\r
+ \par Throws\r
+ Only if allocators aren't equal.\r
+ \li If Value copy constructor throws.\r
+ \li If allocation throws or returns invalid value.\r
+ */\r
+ inline rtree & operator=(BOOST_RV_REF(rtree) src)\r
+ {\r
+ if ( &src != this )\r
+ {\r
+ allocators_type & this_allocs = m_members.allocators();\r
+ allocators_type & src_allocs = src.m_members.allocators();\r
+ \r
+ if ( this_allocs == src_allocs )\r
+ {\r
+ this->raw_destroy(*this);\r
+\r
+ m_members.indexable_getter() = src.m_members.indexable_getter();\r
+ m_members.equal_to() = src.m_members.equal_to();\r
+ m_members.parameters() = src.m_members.parameters();\r
+\r
+ boost::swap(m_members.values_count, src.m_members.values_count);\r
+ boost::swap(m_members.leafs_level, src.m_members.leafs_level);\r
+ boost::swap(m_members.root, src.m_members.root);\r
+\r
+ // NOTE: if propagate is true for std allocators on darwin 4.2.1, glibc++\r
+ // (allocators stored as base classes of members_holder)\r
+ // moving them changes values_count\r
+ \r
+ typedef boost::mpl::bool_<\r
+ allocator_traits_type::propagate_on_container_move_assignment::value\r
+ > propagate;\r
+ detail::move_cond(this_allocs, src_allocs, propagate());\r
+ }\r
+ else\r
+ {\r
+// TODO - shouldn't here propagate_on_container_copy_assignment be checked like in operator=(const&)?\r
+\r
+ // It uses m_allocators\r
+ this->raw_copy(src, *this, true);\r
+ }\r
+ }\r
+\r
+ return *this;\r
+ }\r
+\r
+ /*!\r
+ \brief Swaps contents of two rtrees.\r
+\r
+ Parameters, translator and allocators are swapped as well.\r
+\r
+ \param other The rtree which content will be swapped with this rtree content.\r
+\r
+ \par Throws\r
+ If allocators swap throws.\r
+ */\r
+ void swap(rtree & other)\r
+ {\r
+ boost::swap(m_members.indexable_getter(), other.m_members.indexable_getter());\r
+ boost::swap(m_members.equal_to(), other.m_members.equal_to());\r
+ boost::swap(m_members.parameters(), other.m_members.parameters());\r
+ \r
+ // NOTE: if propagate is true for std allocators on darwin 4.2.1, glibc++\r
+ // (allocators stored as base classes of members_holder)\r
+ // swapping them changes values_count\r
+ \r
+ typedef boost::mpl::bool_<\r
+ allocator_traits_type::propagate_on_container_swap::value\r
+ > propagate;\r
+ detail::swap_cond(m_members.allocators(), other.m_members.allocators(), propagate());\r
+\r
+ boost::swap(m_members.values_count, other.m_members.values_count);\r
+ boost::swap(m_members.leafs_level, other.m_members.leafs_level);\r
+ boost::swap(m_members.root, other.m_members.root);\r
+ }\r
+\r
+ /*!\r
+ \brief Insert a value to the index.\r
+\r
+ \param value The value which will be stored in the container.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+\r
+ \warning\r
+ This operation only guarantees that there will be no memory leaks.\r
+ After an exception is thrown the R-tree may be left in an inconsistent state,\r
+ elements must not be inserted or removed. Other operations are allowed however\r
+ some of them may return invalid data.\r
+ */\r
+ inline void insert(value_type const& value)\r
+ {\r
+ if ( !m_members.root )\r
+ this->raw_create();\r
+\r
+ this->raw_insert(value);\r
+ }\r
+\r
+ /*!\r
+ \brief Insert a range of values to the index.\r
+\r
+ \param first The beginning of the range of values.\r
+ \param last The end of the range of values.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+\r
+ \warning\r
+ This operation only guarantees that there will be no memory leaks.\r
+ After an exception is thrown the R-tree may be left in an inconsistent state,\r
+ elements must not be inserted or removed. Other operations are allowed however\r
+ some of them may return invalid data.\r
+ */\r
+ template <typename Iterator>\r
+ inline void insert(Iterator first, Iterator last)\r
+ {\r
+ if ( !m_members.root )\r
+ this->raw_create();\r
+\r
+ for ( ; first != last ; ++first )\r
+ this->raw_insert(*first);\r
+ }\r
+\r
+ /*!\r
+ \brief Insert a value created using convertible object or a range of values to the index.\r
+\r
+ \param conv_or_rng An object of type convertible to value_type or a range of values.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+\r
+ \warning\r
+ This operation only guarantees that there will be no memory leaks.\r
+ After an exception is thrown the R-tree may be left in an inconsistent state,\r
+ elements must not be inserted or removed. Other operations are allowed however\r
+ some of them may return invalid data.\r
+ */\r
+ template <typename ConvertibleOrRange>\r
+ inline void insert(ConvertibleOrRange const& conv_or_rng)\r
+ {\r
+ if ( !m_members.root )\r
+ this->raw_create();\r
+\r
+ typedef boost::mpl::bool_\r
+ <\r
+ boost::is_convertible<ConvertibleOrRange, value_type>::value\r
+ > is_conv_t;\r
+\r
+ this->insert_dispatch(conv_or_rng, is_conv_t());\r
+ }\r
+\r
+ /*!\r
+ \brief Remove a value from the container.\r
+\r
+ In contrast to the \c std::set or <tt>std::map erase()</tt> method\r
+ this method removes only one value from the container.\r
+\r
+ \param value The value which will be removed from the container.\r
+\r
+ \return 1 if the value was removed, 0 otherwise.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+\r
+ \warning\r
+ This operation only guarantees that there will be no memory leaks.\r
+ After an exception is thrown the R-tree may be left in an inconsistent state,\r
+ elements must not be inserted or removed. Other operations are allowed however\r
+ some of them may return invalid data.\r
+ */\r
+ inline size_type remove(value_type const& value)\r
+ {\r
+ if ( !m_members.root )\r
+ return 0;\r
+\r
+ return this->raw_remove(value);\r
+ }\r
+\r
+ /*!\r
+ \brief Remove a range of values from the container.\r
+\r
+ In contrast to the \c std::set or <tt>std::map erase()</tt> method\r
+ it doesn't take iterators pointing to values stored in this container. It removes values equal\r
+ to these passed as a range. Furthermore this method removes only one value for each one passed\r
+ in the range, not all equal values.\r
+\r
+ \param first The beginning of the range of values.\r
+ \param last The end of the range of values.\r
+\r
+ \return The number of removed values.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+\r
+ \warning\r
+ This operation only guarantees that there will be no memory leaks.\r
+ After an exception is thrown the R-tree may be left in an inconsistent state,\r
+ elements must not be inserted or removed. Other operations are allowed however\r
+ some of them may return invalid data.\r
+ */\r
+ template <typename Iterator>\r
+ inline size_type remove(Iterator first, Iterator last)\r
+ {\r
+ size_type result = 0;\r
+\r
+ if ( !m_members.root )\r
+ return result;\r
+\r
+ for ( ; first != last ; ++first )\r
+ result += this->raw_remove(*first);\r
+ return result;\r
+ }\r
+\r
+ /*!\r
+ \brief Remove value corresponding to an object convertible to it or a range of values from the container.\r
+\r
+ In contrast to the \c std::set or <tt>std::map erase()</tt> method\r
+ it removes values equal to these passed as a range. Furthermore, this method removes only\r
+ one value for each one passed in the range, not all equal values.\r
+\r
+ \param conv_or_rng The object of type convertible to value_type or a range of values.\r
+\r
+ \return The number of removed values.\r
+\r
+ \par Throws\r
+ \li If Value copy constructor or copy assignment throws.\r
+ \li If allocation throws or returns invalid value.\r
+\r
+ \warning\r
+ This operation only guarantees that there will be no memory leaks.\r
+ After an exception is thrown the R-tree may be left in an inconsistent state,\r
+ elements must not be inserted or removed. Other operations are allowed however\r
+ some of them may return invalid data.\r
+ */\r
+ template <typename ConvertibleOrRange>\r
+ inline size_type remove(ConvertibleOrRange const& conv_or_rng)\r
+ {\r
+ if ( !m_members.root )\r
+ return 0;\r
+\r
+ typedef boost::mpl::bool_\r
+ <\r
+ boost::is_convertible<ConvertibleOrRange, value_type>::value\r
+ > is_conv_t;\r
+\r
+ return this->remove_dispatch(conv_or_rng, is_conv_t());\r
+ }\r
+\r
+ /*!\r
+ \brief Finds values meeting passed predicates e.g. nearest to some Point and/or intersecting some Box.\r
+\r
+ This query function performs spatial and k-nearest neighbor searches. It allows to pass a set of predicates.\r
+ Values will be returned only if all predicates are met.\r
+\r
+ <b>Spatial predicates</b>\r
+ \r
+ Spatial predicates may be generated by one of the functions listed below:\r
+ \li \c boost::geometry::index::contains(),\r
+ \li \c boost::geometry::index::covered_by(),\r
+ \li \c boost::geometry::index::covers(),\r
+ \li \c boost::geometry::index::disjoint(),\r
+ \li \c boost::geometry::index::intersects(),\r
+ \li \c boost::geometry::index::overlaps(),\r
+ \li \c boost::geometry::index::within(),\r
+\r
+ It is possible to negate spatial predicates:\r
+ \li <tt>! boost::geometry::index::contains()</tt>,\r
+ \li <tt>! boost::geometry::index::covered_by()</tt>,\r
+ \li <tt>! boost::geometry::index::covers()</tt>,\r
+ \li <tt>! boost::geometry::index::disjoint()</tt>,\r
+ \li <tt>! boost::geometry::index::intersects()</tt>,\r
+ \li <tt>! boost::geometry::index::overlaps()</tt>,\r
+ \li <tt>! boost::geometry::index::within()</tt>\r
+\r
+ <b>Satisfies predicate</b>\r
+ \r
+ This is a special kind of predicate which allows to pass a user-defined function or function object which checks\r
+ if Value should be returned by the query. It's generated by:\r
+ \li \c boost::geometry::index::satisfies().\r
+\r
+ <b>Nearest predicate</b>\r
+\r
+ If the nearest predicate is passed a k-nearest neighbor search will be performed. This query will result\r
+ in returning k values to the output iterator. Only one nearest predicate may be passed to the query.\r
+ It may be generated by:\r
+ \li \c boost::geometry::index::nearest().\r
+ \r
+ <b>Connecting predicates</b>\r
+\r
+ Predicates may be passed together connected with \c operator&&().\r
+\r
+ \par Example\r
+ \verbatim\r
+ // return elements intersecting box\r
+ tree.query(bgi::intersects(box), std::back_inserter(result));\r
+ // return elements intersecting poly but not within box\r
+ tree.query(bgi::intersects(poly) && !bgi::within(box), std::back_inserter(result));\r
+ // return elements overlapping box and meeting my_fun unary predicate\r
+ tree.query(bgi::overlaps(box) && bgi::satisfies(my_fun), std::back_inserter(result));\r
+ // return 5 elements nearest to pt and elements are intersecting box\r
+ tree.query(bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));\r
+\r
+ // For each found value do_something (it is a type of function object)\r
+ tree.query(bgi::intersects(box),\r
+ boost::make_function_output_iterator(do_something()));\r
+\r
+ // For each value stored in the rtree do_something\r
+ // always_true is a type of function object always returning true\r
+ tree.query(bgi::satisfies(always_true()),\r
+ boost::make_function_output_iterator(do_something()));\r
+\r
+ // C++11 (lambda expression)\r
+ tree.query(bgi::intersects(box),\r
+ boost::make_function_output_iterator([](value_type const& val){\r
+ // do something\r
+ }));\r
+\r
+ // C++14 (generic lambda expression)\r
+ tree.query(bgi::intersects(box),\r
+ boost::make_function_output_iterator([](auto const& val){\r
+ // do something\r
+ }));\r
+ \endverbatim\r
+\r
+ \par Throws\r
+ If Value copy constructor or copy assignment throws.\r
+ If predicates copy throws.\r
+\r
+ \warning\r
+ Only one \c nearest() perdicate may be passed to the query. Passing more of them results in compile-time error.\r
+\r
+ \param predicates Predicates.\r
+ \param out_it The output iterator, e.g. generated by std::back_inserter().\r
+\r
+ \return The number of values found.\r
+ */\r
+ template <typename Predicates, typename OutIter>\r
+ size_type query(Predicates const& predicates, OutIter out_it) const\r
+ {\r
+ if ( !m_members.root )\r
+ return 0;\r
+\r
+ static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::value;\r
+ static const bool is_distance_predicate = 0 < distance_predicates_count;\r
+ BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates));\r
+\r
+ return query_dispatch(predicates, out_it, boost::mpl::bool_<is_distance_predicate>());\r
+ }\r
+\r
+ /*!\r
+ \brief Returns a query iterator pointing at the begin of the query range.\r
+\r
+ This method returns an iterator which may be used to perform iterative queries.\r
+ For the information about predicates which may be passed to this method see query().\r
+\r
+ \par Example\r
+ \verbatim \r
+ for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;\r
+ it != tree.qend() ; ++it )\r
+ {\r
+ // do something with value\r
+ if ( has_enough_nearest_values() )\r
+ break;\r
+ }\r
+\r
+ // C++11 (auto)\r
+ for ( auto it = tree.qbegin(bgi::nearest(pt, 3)) ; it != tree.qend() ; ++it )\r
+ {\r
+ // do something with value\r
+ }\r
+\r
+ // C++14 (generic lambda expression)\r
+ std::for_each(tree.qbegin(bgi::nearest(pt, 3)), tree.qend(), [](auto const& val){\r
+ // do something with value\r
+ });\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ If predicates copy throws.\r
+ If allocation throws.\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+\r
+ \param predicates Predicates.\r
+ \r
+ \return The iterator pointing at the begin of the query range.\r
+ */\r
+ template <typename Predicates>\r
+ const_query_iterator qbegin(Predicates const& predicates) const\r
+ {\r
+ return const_query_iterator(qbegin_(predicates));\r
+ }\r
+\r
+ /*!\r
+ \brief Returns a query iterator pointing at the end of the query range.\r
+\r
+ This method returns an iterator which may be used to check if the query has ended.\r
+\r
+ \par Example\r
+ \verbatim \r
+ for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;\r
+ it != tree.qend() ; ++it )\r
+ {\r
+ // do something with value\r
+ if ( has_enough_nearest_values() )\r
+ break;\r
+ }\r
+\r
+ // C++11 (auto)\r
+ for ( auto it = tree.qbegin(bgi::nearest(pt, 3)) ; it != tree.qend() ; ++it )\r
+ {\r
+ // do something with value\r
+ }\r
+\r
+ // C++14 (generic lambda expression)\r
+ std::for_each(tree.qbegin(bgi::nearest(pt, 3)), tree.qend(), [](auto const& val){\r
+ // do something with value\r
+ });\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ Nothing\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+ \r
+ \return The iterator pointing at the end of the query range.\r
+ */\r
+ const_query_iterator qend() const\r
+ {\r
+ return const_query_iterator();\r
+ }\r
+\r
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL\r
+private:\r
+#endif\r
+ /*!\r
+ \brief Returns a query iterator pointing at the begin of the query range.\r
+\r
+ This method returns an iterator which may be used to perform iterative queries.\r
+ For the information about predicates which may be passed to this method see query().\r
+ \r
+ The type of the returned iterator depends on the type of passed Predicates but the iterator of this type\r
+ may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator\r
+ returned by this method you may get the type e.g. by using C++11 decltype or Boost.Typeof library.\r
+ This iterator may be compared with iterators returned by both versions of qend() method.\r
+\r
+ \par Example\r
+ \verbatim\r
+ // Store the result in the container using std::copy() - it requires both iterators of the same type\r
+ std::copy(tree.qbegin_(bgi::intersects(box)), tree.qend_(bgi::intersects(box)), std::back_inserter(result));\r
+\r
+ // Store the result in the container using std::copy() and type-erased iterators\r
+ Rtree::const_query_iterator first = tree.qbegin_(bgi::intersects(box));\r
+ Rtree::const_query_iterator last = tree.qend_();\r
+ std::copy(first, last, std::back_inserter(result));\r
+\r
+ // Boost.Typeof\r
+ typedef BOOST_TYPEOF(tree.qbegin(bgi::nearest(pt, 10000))) Iter;\r
+ for ( Iter it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )\r
+ {\r
+ // do something with value\r
+ if ( has_enough_nearest_values() )\r
+ break;\r
+ }\r
+\r
+ // C++11 (auto)\r
+ for ( auto it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )\r
+ {\r
+ // do something with value\r
+ if ( has_enough_nearest_values() )\r
+ break;\r
+ }\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ If predicates copy throws.\r
+ If allocation throws.\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+\r
+ \param predicates Predicates.\r
+ \r
+ \return The iterator pointing at the begin of the query range.\r
+ */\r
+ template <typename Predicates>\r
+ typename boost::mpl::if_c<\r
+ detail::predicates_count_distance<Predicates>::value == 0,\r
+ detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,\r
+ detail::rtree::iterators::distance_query_iterator<\r
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,\r
+ detail::predicates_find_distance<Predicates>::value\r
+ >\r
+ >::type\r
+ qbegin_(Predicates const& predicates) const\r
+ {\r
+ static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::value;\r
+ BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates));\r
+\r
+ typedef typename boost::mpl::if_c<\r
+ detail::predicates_count_distance<Predicates>::value == 0,\r
+ detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,\r
+ detail::rtree::iterators::distance_query_iterator<\r
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,\r
+ detail::predicates_find_distance<Predicates>::value\r
+ >\r
+ >::type iterator_type;\r
+\r
+ if ( !m_members.root )\r
+ return iterator_type(m_members.translator(), predicates);\r
+\r
+ return iterator_type(m_members.root, m_members.translator(), predicates);\r
+ }\r
+\r
+ /*!\r
+ \brief Returns the query iterator pointing at the end of the query range.\r
+\r
+ This method returns the iterator which may be used to perform iterative queries. For the information\r
+ about the predicates which may be passed to this method see query().\r
+ \r
+ The type of the returned iterator depends on the type of passed Predicates but the iterator of this type\r
+ may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator\r
+ returned by this method you may get the type e.g. by using C++11 decltype or Boost.Typeof library.\r
+\r
+ The type of the iterator returned by this method is the same as the one returned by qbegin() to which\r
+ the same predicates were passed.\r
+\r
+ \par Example\r
+ \verbatim\r
+ // Store the result in the container using std::copy() - it requires both iterators of the same type\r
+ std::copy(tree.qbegin_(bgi::intersects(box)), tree.qend_(bgi::intersects(box)), std::back_inserter(result));\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ If predicates copy throws.\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+\r
+ \param predicates Predicates.\r
+ \r
+ \return The iterator pointing at the end of the query range.\r
+ */\r
+ template <typename Predicates>\r
+ typename boost::mpl::if_c<\r
+ detail::predicates_count_distance<Predicates>::value == 0,\r
+ detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,\r
+ detail::rtree::iterators::distance_query_iterator<\r
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,\r
+ detail::predicates_find_distance<Predicates>::value\r
+ >\r
+ >::type\r
+ qend_(Predicates const& predicates) const\r
+ {\r
+ static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::value;\r
+ BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates));\r
+\r
+ typedef typename boost::mpl::if_c<\r
+ detail::predicates_count_distance<Predicates>::value == 0,\r
+ detail::rtree::iterators::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,\r
+ detail::rtree::iterators::distance_query_iterator<\r
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,\r
+ detail::predicates_find_distance<Predicates>::value\r
+ >\r
+ >::type iterator_type;\r
+\r
+ return iterator_type(m_members.translator(), predicates);\r
+ }\r
+\r
+ /*!\r
+ \brief Returns the query iterator pointing at the end of the query range.\r
+\r
+ This method returns the iterator which may be compared with the iterator returned by qbegin() in order to\r
+ check if the query has ended.\r
+ \r
+ The type of the returned iterator is different than the type returned by qbegin() but the iterator of this type\r
+ may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator returned by this\r
+ method, which most certainly will be faster than the type-erased iterator, you may get the type\r
+ e.g. by using C++11 decltype or Boost.Typeof library.\r
+\r
+ The type of the iterator returned by this method is dfferent than the type returned by qbegin().\r
+\r
+ \par Example\r
+ \verbatim\r
+ // Store the result in the container using std::copy() and type-erased iterators\r
+ Rtree::const_query_iterator first = tree.qbegin_(bgi::intersects(box));\r
+ Rtree::const_query_iterator last = tree.qend_();\r
+ std::copy(first, last, std::back_inserter(result));\r
+\r
+ // Boost.Typeof\r
+ typedef BOOST_TYPEOF(tree.qbegin(bgi::nearest(pt, 10000))) Iter;\r
+ for ( Iter it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )\r
+ {\r
+ // do something with value\r
+ if ( has_enough_nearest_values() )\r
+ break;\r
+ }\r
+\r
+ // C++11 (auto)\r
+ for ( auto it = tree.qbegin_(bgi::nearest(pt, 10000)) ; it != tree.qend_() ; ++it )\r
+ {\r
+ // do something with value\r
+ if ( has_enough_nearest_values() )\r
+ break;\r
+ }\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ Nothing\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+ \r
+ \return The iterator pointing at the end of the query range.\r
+ */\r
+ detail::rtree::iterators::end_query_iterator<value_type, allocators_type>\r
+ qend_() const\r
+ {\r
+ return detail::rtree::iterators::end_query_iterator<value_type, allocators_type>();\r
+ }\r
+\r
+public:\r
+\r
+ /*!\r
+ \brief Returns the iterator pointing at the begin of the rtree values range.\r
+\r
+ This method returns the iterator which may be used to iterate over all values\r
+ stored in the rtree.\r
+\r
+ \par Example\r
+ \verbatim\r
+ // Copy all values into the vector\r
+ std::copy(tree.begin(), tree.end(), std::back_inserter(vec));\r
+\r
+ for ( Rtree::const_iterator it = tree.begin() ; it != tree.end() ; ++it )\r
+ {\r
+ // do something with value\r
+ }\r
+\r
+ // C++11 (auto)\r
+ for ( auto it = tree.begin() ; it != tree.end() ; ++it )\r
+ {\r
+ // do something with value\r
+ }\r
+\r
+ // C++14 (generic lambda expression)\r
+ std::for_each(tree.begin(), tree.end(), [](auto const& val){\r
+ // do something with value\r
+ })\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ If allocation throws.\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+\r
+ \return The iterator pointing at the begin of the range.\r
+ */\r
+ const_iterator begin() const\r
+ {\r
+ if ( !m_members.root )\r
+ return const_iterator();\r
+\r
+ return const_iterator(m_members.root);\r
+ }\r
+\r
+ /*!\r
+ \brief Returns the iterator pointing at the end of the rtree values range.\r
+\r
+ This method returns the iterator which may be compared with the iterator returned by begin()\r
+ in order to check if the iteration has ended.\r
+\r
+ \par Example\r
+ \verbatim\r
+ for ( Rtree::const_iterator it = tree.begin() ; it != tree.end() ; ++it )\r
+ {\r
+ // do something with value\r
+ }\r
+\r
+ // C++11 (lambda expression)\r
+ std::for_each(tree.begin(), tree.end(), [](value_type const& val){\r
+ // do something with value\r
+ })\r
+ \endverbatim\r
+\r
+ \par Iterator category\r
+ ForwardIterator\r
+\r
+ \par Throws\r
+ Nothing.\r
+\r
+ \warning\r
+ The modification of the rtree may invalidate the iterators.\r
+\r
+ \return The iterator pointing at the end of the range.\r
+ */\r
+ const_iterator end() const\r
+ {\r
+ return const_iterator();\r
+ }\r
+\r
+ /*!\r
+ \brief Returns the number of stored values.\r
+\r
+ \return The number of stored values.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline size_type size() const\r
+ {\r
+ return m_members.values_count;\r
+ }\r
+\r
+ /*!\r
+ \brief Query if the container is empty.\r
+\r
+ \return true if the container is empty.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline bool empty() const\r
+ {\r
+ return 0 == m_members.values_count;\r
+ }\r
+\r
+ /*!\r
+ \brief Removes all values stored in the container.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline void clear()\r
+ {\r
+ this->raw_destroy(*this);\r
+ }\r
+\r
+ /*!\r
+ \brief Returns the box able to contain all values stored in the container.\r
+\r
+ Returns the box able to contain all values stored in the container.\r
+ If the container is empty the result of \c geometry::assign_inverse() is returned.\r
+\r
+ \return The box able to contain all values stored in the container or an invalid box if\r
+ there are no values in the container.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline bounds_type bounds() const\r
+ {\r
+ bounds_type result;\r
+ // in order to suppress the uninitialized variable warnings\r
+ geometry::assign_inverse(result);\r
+\r
+ if ( m_members.root )\r
+ {\r
+ detail::rtree::visitors::children_box<value_type, options_type, translator_type, box_type, allocators_type>\r
+ box_v(result, m_members.translator());\r
+ detail::rtree::apply_visitor(box_v, *m_members.root);\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ /*!\r
+ \brief Count Values or Indexables stored in the container.\r
+ \r
+ For indexable_type it returns the number of values which indexables equals the parameter.\r
+ For value_type it returns the number of values which equals the parameter.\r
+\r
+ \param vori The value or indexable which will be counted.\r
+\r
+ \return The number of values found.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ template <typename ValueOrIndexable>\r
+ size_type count(ValueOrIndexable const& vori) const\r
+ {\r
+ if ( !m_members.root )\r
+ return 0;\r
+\r
+ // the input should be convertible to Value or Indexable type\r
+\r
+ enum { as_val = 0, as_ind, dont_know };\r
+ typedef boost::mpl::int_\r
+ <\r
+ boost::is_same<ValueOrIndexable, value_type>::value ?\r
+ as_val :\r
+ boost::is_same<ValueOrIndexable, indexable_type>::value ?\r
+ as_ind :\r
+ boost::is_convertible<ValueOrIndexable, indexable_type>::value ?\r
+ as_ind :\r
+ boost::is_convertible<ValueOrIndexable, value_type>::value ?\r
+ as_val :\r
+ dont_know\r
+ > variant;\r
+\r
+ BOOST_MPL_ASSERT_MSG((variant::value != dont_know),\r
+ PASSED_OBJECT_NOT_CONVERTIBLE_TO_VALUE_NOR_INDEXABLE_TYPE,\r
+ (ValueOrIndexable));\r
+\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ variant::value == as_val,\r
+ value_type,\r
+ indexable_type\r
+ >::type value_or_indexable;\r
+\r
+ // NOTE: If an object of convertible but not the same type is passed\r
+ // into the function, here a temporary will be created.\r
+ return this->template raw_count<value_or_indexable>(vori);\r
+ }\r
+\r
+ /*!\r
+ \brief Returns parameters.\r
+\r
+ \return The parameters object.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline parameters_type parameters() const\r
+ {\r
+ return m_members.parameters();\r
+ }\r
+\r
+ /*!\r
+ \brief Returns function retrieving Indexable from Value.\r
+\r
+ \return The indexable_getter object.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ indexable_getter indexable_get() const\r
+ {\r
+ return m_members.indexable_getter();\r
+ }\r
+\r
+ /*!\r
+ \brief Returns function comparing Values\r
+\r
+ \return The value_equal function.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ value_equal value_eq() const\r
+ {\r
+ return m_members.equal_to();\r
+ }\r
+\r
+ /*!\r
+ \brief Returns allocator used by the rtree.\r
+\r
+ \return The allocator.\r
+\r
+ \par Throws\r
+ If allocator copy constructor throws.\r
+ */\r
+ allocator_type get_allocator() const\r
+ {\r
+ return m_members.allocators().allocator();\r
+ }\r
+\r
+private:\r
+\r
+ /*!\r
+ \brief Returns the translator object.\r
+\r
+ \return The translator object.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline translator_type translator() const\r
+ {\r
+ return m_members.translator();\r
+ }\r
+\r
+ /*!\r
+ \brief Apply a visitor to the nodes structure in order to perform some operator.\r
+\r
+ This function is not a part of the 'official' interface. However it makes\r
+ possible e.g. to pass a visitor drawing the tree structure.\r
+\r
+ \param visitor The visitor object.\r
+\r
+ \par Throws\r
+ If Visitor::operator() throws.\r
+ */\r
+ template <typename Visitor>\r
+ inline void apply_visitor(Visitor & visitor) const\r
+ {\r
+ if ( m_members.root )\r
+ detail::rtree::apply_visitor(visitor, *m_members.root);\r
+ }\r
+\r
+ /*!\r
+ \brief Returns the depth of the R-tree.\r
+\r
+ This function is not a part of the 'official' interface.\r
+\r
+ \return The depth of the R-tree.\r
+\r
+ \par Throws\r
+ Nothing.\r
+ */\r
+ inline size_type depth() const\r
+ {\r
+ return m_members.leafs_level;\r
+ }\r
+\r
+private:\r
+\r
+ /*!\r
+ \pre Root node must exist - m_root != 0.\r
+\r
+ \brief Insert a value to the index.\r
+\r
+ \param value The value which will be stored in the container.\r
+\r
+ \par Exception-safety\r
+ basic\r
+ */\r
+ inline void raw_insert(value_type const& value)\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");\r
+ // CONSIDER: alternative - ignore invalid indexable or throw an exception\r
+ BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(m_members.translator()(value)), "Indexable is invalid");\r
+\r
+ detail::rtree::visitors::insert<\r
+ value_type,\r
+ value_type, options_type, translator_type, box_type, allocators_type,\r
+ typename options_type::insert_tag\r
+ > insert_v(m_members.root, m_members.leafs_level, value,\r
+ m_members.parameters(), m_members.translator(), m_members.allocators());\r
+\r
+ detail::rtree::apply_visitor(insert_v, *m_members.root);\r
+\r
+// TODO\r
+// Think about this: If exception is thrown, may the root be removed?\r
+// Or it is just cleared?\r
+\r
+// TODO\r
+// If exception is thrown, m_values_count may be invalid\r
+ ++m_members.values_count;\r
+ }\r
+\r
+ /*!\r
+ \brief Remove the value from the container.\r
+\r
+ \param value The value which will be removed from the container.\r
+\r
+ \par Exception-safety\r
+ basic\r
+ */\r
+ inline size_type raw_remove(value_type const& value)\r
+ {\r
+ // TODO: awulkiew - assert for correct value (indexable) ?\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");\r
+\r
+ detail::rtree::visitors::remove<\r
+ value_type, options_type, translator_type, box_type, allocators_type\r
+ > remove_v(m_members.root, m_members.leafs_level, value,\r
+ m_members.parameters(), m_members.translator(), m_members.allocators());\r
+\r
+ detail::rtree::apply_visitor(remove_v, *m_members.root);\r
+\r
+ // If exception is thrown, m_values_count may be invalid\r
+\r
+ if ( remove_v.is_value_removed() )\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_members.values_count, "unexpected state");\r
+\r
+ --m_members.values_count;\r
+\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ /*!\r
+ \brief Create an empty R-tree i.e. new empty root node and clear other attributes.\r
+\r
+ \par Exception-safety\r
+ strong\r
+ */\r
+ inline void raw_create()\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(0 == m_members.root, "the tree is already created");\r
+\r
+ m_members.root = detail::rtree::create_node<allocators_type, leaf>::apply(m_members.allocators()); // MAY THROW (N: alloc)\r
+ m_members.values_count = 0;\r
+ m_members.leafs_level = 0;\r
+ }\r
+\r
+ /*!\r
+ \brief Destroy the R-tree i.e. all nodes and clear attributes.\r
+\r
+ \param t The container which is going to be destroyed.\r
+\r
+ \par Exception-safety\r
+ nothrow\r
+ */\r
+ inline void raw_destroy(rtree & t)\r
+ {\r
+ if ( t.m_members.root )\r
+ {\r
+ detail::rtree::visitors::destroy<value_type, options_type, translator_type, box_type, allocators_type>\r
+ del_v(t.m_members.root, t.m_members.allocators());\r
+ detail::rtree::apply_visitor(del_v, *t.m_members.root);\r
+\r
+ t.m_members.root = 0;\r
+ }\r
+ t.m_members.values_count = 0;\r
+ t.m_members.leafs_level = 0;\r
+ }\r
+\r
+ /*!\r
+ \brief Copy the R-tree i.e. whole nodes structure, values and other attributes.\r
+ It uses destination's allocators to create the new structure.\r
+\r
+ \param src The source R-tree.\r
+ \param dst The destination R-tree.\r
+ \param copy_tr_and_params If true, translator and parameters will also be copied.\r
+\r
+ \par Exception-safety\r
+ strong\r
+ */\r
+ inline void raw_copy(rtree const& src, rtree & dst, bool copy_tr_and_params) const\r
+ {\r
+ detail::rtree::visitors::copy<value_type, options_type, translator_type, box_type, allocators_type>\r
+ copy_v(dst.m_members.allocators());\r
+\r
+ if ( src.m_members.root )\r
+ detail::rtree::apply_visitor(copy_v, *src.m_members.root); // MAY THROW (V, E: alloc, copy, N: alloc)\r
+\r
+ if ( copy_tr_and_params )\r
+ {\r
+ dst.m_members.indexable_getter() = src.m_members.indexable_getter();\r
+ dst.m_members.equal_to() = src.m_members.equal_to();\r
+ dst.m_members.parameters() = src.m_members.parameters();\r
+ }\r
+\r
+ // TODO use subtree_destroyer\r
+ if ( dst.m_members.root )\r
+ {\r
+ detail::rtree::visitors::destroy<value_type, options_type, translator_type, box_type, allocators_type>\r
+ del_v(dst.m_members.root, dst.m_members.allocators());\r
+ detail::rtree::apply_visitor(del_v, *dst.m_members.root);\r
+ dst.m_members.root = 0;\r
+ }\r
+\r
+ dst.m_members.root = copy_v.result;\r
+ dst.m_members.values_count = src.m_members.values_count;\r
+ dst.m_members.leafs_level = src.m_members.leafs_level;\r
+ }\r
+\r
+ /*!\r
+ \brief Insert a value corresponding to convertible object into the index.\r
+\r
+ \param val_conv The object convertible to value.\r
+\r
+ \par Exception-safety\r
+ basic\r
+ */\r
+ template <typename ValueConvertible>\r
+ inline void insert_dispatch(ValueConvertible const& val_conv,\r
+ boost::mpl::bool_<true> const& /*is_convertible*/)\r
+ {\r
+ this->raw_insert(val_conv);\r
+ }\r
+\r
+ /*!\r
+ \brief Insert a range of values into the index.\r
+\r
+ \param rng The range of values.\r
+\r
+ \par Exception-safety\r
+ basic\r
+ */\r
+ template <typename Range>\r
+ inline void insert_dispatch(Range const& rng,\r
+ boost::mpl::bool_<false> const& /*is_convertible*/)\r
+ {\r
+ BOOST_MPL_ASSERT_MSG((detail::is_range<Range>::value),\r
+ PASSED_OBJECT_IS_NOT_CONVERTIBLE_TO_VALUE_NOR_A_RANGE,\r
+ (Range));\r
+\r
+ typedef typename boost::range_const_iterator<Range>::type It;\r
+ for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it )\r
+ this->raw_insert(*it);\r
+ }\r
+\r
+ /*!\r
+ \brief Remove a value corresponding to convertible object from the index.\r
+\r
+ \param val_conv The object convertible to value.\r
+\r
+ \par Exception-safety\r
+ basic\r
+ */\r
+ template <typename ValueConvertible>\r
+ inline size_type remove_dispatch(ValueConvertible const& val_conv,\r
+ boost::mpl::bool_<true> const& /*is_convertible*/)\r
+ {\r
+ return this->raw_remove(val_conv);\r
+ }\r
+\r
+ /*!\r
+ \brief Remove a range of values from the index.\r
+\r
+ \param rng The range of values which will be removed from the container.\r
+\r
+ \par Exception-safety\r
+ basic\r
+ */\r
+ template <typename Range>\r
+ inline size_type remove_dispatch(Range const& rng,\r
+ boost::mpl::bool_<false> const& /*is_convertible*/)\r
+ {\r
+ BOOST_MPL_ASSERT_MSG((detail::is_range<Range>::value),\r
+ PASSED_OBJECT_IS_NOT_CONVERTIBLE_TO_VALUE_NOR_A_RANGE,\r
+ (Range));\r
+\r
+ size_type result = 0;\r
+ typedef typename boost::range_const_iterator<Range>::type It;\r
+ for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it )\r
+ result += this->raw_remove(*it);\r
+ return result;\r
+ }\r
+\r
+ /*!\r
+ \brief Return values meeting predicates.\r
+\r
+ \par Exception-safety\r
+ strong\r
+ */\r
+ template <typename Predicates, typename OutIter>\r
+ size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<false> const& /*is_distance_predicate*/) const\r
+ {\r
+ detail::rtree::visitors::spatial_query<value_type, options_type, translator_type, box_type, allocators_type, Predicates, OutIter>\r
+ find_v(m_members.translator(), predicates, out_it);\r
+\r
+ detail::rtree::apply_visitor(find_v, *m_members.root);\r
+\r
+ return find_v.found_count;\r
+ }\r
+\r
+ /*!\r
+ \brief Perform nearest neighbour search.\r
+\r
+ \par Exception-safety\r
+ strong\r
+ */\r
+ template <typename Predicates, typename OutIter>\r
+ size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<true> const& /*is_distance_predicate*/) const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");\r
+\r
+ static const unsigned distance_predicate_index = detail::predicates_find_distance<Predicates>::value;\r
+ detail::rtree::visitors::distance_query<\r
+ value_type,\r
+ options_type,\r
+ translator_type,\r
+ box_type,\r
+ allocators_type,\r
+ Predicates,\r
+ distance_predicate_index,\r
+ OutIter\r
+ > distance_v(m_members.parameters(), m_members.translator(), predicates, out_it);\r
+\r
+ detail::rtree::apply_visitor(distance_v, *m_members.root);\r
+\r
+ return distance_v.finish();\r
+ }\r
+ \r
+ /*!\r
+ \brief Count elements corresponding to value or indexable.\r
+\r
+ \par Exception-safety\r
+ strong\r
+ */\r
+ template <typename ValueOrIndexable>\r
+ size_type raw_count(ValueOrIndexable const& vori) const\r
+ {\r
+ BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");\r
+\r
+ detail::rtree::visitors::count\r
+ <\r
+ ValueOrIndexable,\r
+ value_type,\r
+ options_type,\r
+ translator_type,\r
+ box_type,\r
+ allocators_type\r
+ > count_v(vori, m_members.translator());\r
+\r
+ detail::rtree::apply_visitor(count_v, *m_members.root);\r
+\r
+ return count_v.found_count;\r
+ }\r
+\r
+ struct members_holder\r
+ : public translator_type\r
+ , public Parameters\r
+ , public allocators_type\r
+ {\r
+ private:\r
+ members_holder(members_holder const&);\r
+ members_holder & operator=(members_holder const&);\r
+\r
+ public:\r
+ template <typename IndGet, typename ValEq, typename Alloc>\r
+ members_holder(IndGet const& ind_get,\r
+ ValEq const& val_eq,\r
+ Parameters const& parameters,\r
+ BOOST_FWD_REF(Alloc) alloc)\r
+ : translator_type(ind_get, val_eq)\r
+ , Parameters(parameters)\r
+ , allocators_type(boost::forward<Alloc>(alloc))\r
+ , values_count(0)\r
+ , leafs_level(0)\r
+ , root(0)\r
+ {}\r
+\r
+ template <typename IndGet, typename ValEq>\r
+ members_holder(IndGet const& ind_get,\r
+ ValEq const& val_eq,\r
+ Parameters const& parameters)\r
+ : translator_type(ind_get, val_eq)\r
+ , Parameters(parameters)\r
+ , allocators_type()\r
+ , values_count(0)\r
+ , leafs_level(0)\r
+ , root(0)\r
+ {}\r
+\r
+ translator_type const& translator() const { return *this; }\r
+\r
+ IndexableGetter const& indexable_getter() const { return *this; }\r
+ IndexableGetter & indexable_getter() { return *this; }\r
+ EqualTo const& equal_to() const { return *this; }\r
+ EqualTo & equal_to() { return *this; }\r
+ Parameters const& parameters() const { return *this; }\r
+ Parameters & parameters() { return *this; }\r
+ allocators_type const& allocators() const { return *this; }\r
+ allocators_type & allocators() { return *this; }\r
+\r
+ size_type values_count;\r
+ size_type leafs_level;\r
+ node_pointer root;\r
+ };\r
+\r
+ members_holder m_members;\r
+};\r
+\r
+/*!\r
+\brief Insert a value to the index.\r
+\r
+It calls <tt>rtree::insert(value_type const&)</tt>.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\param v The value which will be stored in the index.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline void insert(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree,\r
+ Value const& v)\r
+{\r
+ tree.insert(v);\r
+}\r
+\r
+/*!\r
+\brief Insert a range of values to the index.\r
+\r
+It calls <tt>rtree::insert(Iterator, Iterator)</tt>.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\param first The beginning of the range of values.\r
+\param last The end of the range of values.\r
+*/\r
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,\r
+ typename Iterator>\r
+inline void insert(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree,\r
+ Iterator first, Iterator last)\r
+{\r
+ tree.insert(first, last);\r
+}\r
+\r
+/*!\r
+\brief Insert a value created using convertible object or a range of values to the index.\r
+\r
+It calls <tt>rtree::insert(ConvertibleOrRange const&)</tt>.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\param conv_or_rng The object of type convertible to value_type or a range of values.\r
+*/\r
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,\r
+ typename ConvertibleOrRange>\r
+inline void insert(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree,\r
+ ConvertibleOrRange const& conv_or_rng)\r
+{\r
+ tree.insert(conv_or_rng);\r
+}\r
+\r
+/*!\r
+\brief Remove a value from the container.\r
+\r
+Remove a value from the container. In contrast to the \c std::set or <tt>std::map erase()</tt> method\r
+this function removes only one value from the container.\r
+\r
+It calls <tt>rtree::remove(value_type const&)</tt>.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\param v The value which will be removed from the index.\r
+\r
+\return 1 if value was removed, 0 otherwise.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type\r
+remove(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree,\r
+ Value const& v)\r
+{\r
+ return tree.remove(v);\r
+}\r
+\r
+/*!\r
+\brief Remove a range of values from the container.\r
+\r
+Remove a range of values from the container. In contrast to the \c std::set or <tt>std::map erase()</tt> method\r
+it doesn't take iterators pointing to values stored in this container. It removes values equal\r
+to these passed as a range. Furthermore this function removes only one value for each one passed\r
+in the range, not all equal values.\r
+\r
+It calls <tt>rtree::remove(Iterator, Iterator)</tt>.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\param first The beginning of the range of values.\r
+\param last The end of the range of values.\r
+\r
+\return The number of removed values.\r
+*/\r
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,\r
+ typename Iterator>\r
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type\r
+remove(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree,\r
+ Iterator first, Iterator last)\r
+{\r
+ return tree.remove(first, last);\r
+}\r
+\r
+/*!\r
+\brief Remove a value corresponding to an object convertible to it or a range of values from the container.\r
+\r
+Remove a value corresponding to an object convertible to it or a range of values from the container.\r
+In contrast to the \c std::set or <tt>std::map erase()</tt> method\r
+it removes values equal to these passed as a range. Furthermore this method removes only\r
+one value for each one passed in the range, not all equal values.\r
+\r
+It calls <tt>rtree::remove(ConvertibleOrRange const&)</tt>.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\param conv_or_rng The object of type convertible to value_type or the range of values.\r
+\r
+\return The number of removed values.\r
+*/\r
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,\r
+ typename ConvertibleOrRange>\r
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type\r
+remove(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree,\r
+ ConvertibleOrRange const& conv_or_rng)\r
+{\r
+ return tree.remove(conv_or_rng);\r
+}\r
+\r
+/*!\r
+\brief Finds values meeting passed predicates e.g. nearest to some Point and/or intersecting some Box.\r
+\r
+This query function performs spatial and k-nearest neighbor searches. It allows to pass a set of predicates.\r
+Values will be returned only if all predicates are met.\r
+\r
+<b>Spatial predicates</b>\r
+ \r
+Spatial predicates may be generated by one of the functions listed below:\r
+\li \c boost::geometry::index::contains(),\r
+\li \c boost::geometry::index::covered_by(),\r
+\li \c boost::geometry::index::covers(),\r
+\li \c boost::geometry::index::disjoint(),\r
+\li \c boost::geometry::index::intersects(),\r
+\li \c boost::geometry::index::overlaps(),\r
+\li \c boost::geometry::index::within(),\r
+\r
+It is possible to negate spatial predicates:\r
+\li <tt>! boost::geometry::index::contains()</tt>,\r
+\li <tt>! boost::geometry::index::covered_by()</tt>,\r
+\li <tt>! boost::geometry::index::covers()</tt>,\r
+\li <tt>! boost::geometry::index::disjoint()</tt>,\r
+\li <tt>! boost::geometry::index::intersects()</tt>,\r
+\li <tt>! boost::geometry::index::overlaps()</tt>,\r
+\li <tt>! boost::geometry::index::within()</tt>\r
+\r
+<b>Satisfies predicate</b>\r
+\r
+This is a special kind of predicate which allows to pass a user-defined function or function object which checks\r
+if Value should be returned by the query. It's generated by:\r
+\li \c boost::geometry::index::satisfies().\r
+\r
+<b>Nearest predicate</b>\r
+\r
+If the nearest predicate is passed a k-nearest neighbor search will be performed. This query will result\r
+in returning k values to the output iterator. Only one nearest predicate may be passed to the query.\r
+It may be generated by:\r
+\li \c boost::geometry::index::nearest().\r
+ \r
+<b>Connecting predicates</b>\r
+\r
+Predicates may be passed together connected with \c operator&&().\r
+\r
+\par Example\r
+\verbatim\r
+// return elements intersecting box\r
+bgi::query(tree, bgi::intersects(box), std::back_inserter(result));\r
+// return elements intersecting poly but not within box\r
+bgi::query(tree, bgi::intersects(poly) && !bgi::within(box), std::back_inserter(result));\r
+// return elements overlapping box and meeting my_fun value predicate\r
+bgi::query(tree, bgi::overlaps(box) && bgi::satisfies(my_fun), std::back_inserter(result));\r
+// return 5 elements nearest to pt and elements are intersecting box\r
+bgi::query(tree, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));\r
+\r
+// For each found value do_something (it is a type of function object)\r
+tree.query(bgi::intersects(box),\r
+ boost::make_function_output_iterator(do_something()));\r
+\endverbatim\r
+\r
+\par Throws\r
+If Value copy constructor or copy assignment throws.\r
+\r
+\warning\r
+Only one \c nearest() perdicate may be passed to the query. Passing more of them results in compile-time error.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The rtree.\r
+\param predicates Predicates.\r
+\param out_it The output iterator, e.g. generated by std::back_inserter().\r
+\r
+\return The number of values found.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,\r
+ typename Predicates, typename OutIter> inline\r
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type\r
+query(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree,\r
+ Predicates const& predicates,\r
+ OutIter out_it)\r
+{\r
+ return tree.query(predicates, out_it);\r
+}\r
+\r
+/*!\r
+\brief Returns the query iterator pointing at the begin of the query range.\r
+\r
+This method returns the iterator which may be used to perform iterative queries. For the information\r
+about the predicates which may be passed to this method see query().\r
+ \r
+\par Example\r
+\verbatim\r
+std::for_each(bgi::qbegin(tree, bgi::nearest(pt, 3)), bgi::qend(tree), do_something());\r
+\endverbatim\r
+\r
+\par Iterator category\r
+ForwardIterator\r
+\r
+\par Throws\r
+If predicates copy throws.\r
+If allocation throws.\r
+\r
+\warning\r
+The modification of the rtree may invalidate the iterators.\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The rtree.\r
+\param predicates Predicates.\r
+ \r
+\return The iterator pointing at the begin of the query range.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,\r
+ typename Predicates> inline\r
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::const_query_iterator\r
+qbegin(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree,\r
+ Predicates const& predicates)\r
+{\r
+ return tree.qbegin(predicates);\r
+}\r
+\r
+/*!\r
+\brief Returns the query iterator pointing at the end of the query range.\r
+\r
+This method returns the iterator which may be used to check if the query has ended.\r
+ \r
+\par Example\r
+\verbatim\r
+std::for_each(bgi::qbegin(tree, bgi::nearest(pt, 3)), bgi::qend(tree), do_something());\r
+\endverbatim\r
+\r
+\par Iterator category\r
+ForwardIterator\r
+\r
+\par Throws\r
+Nothing\r
+\r
+\warning\r
+The modification of the rtree may invalidate the iterators.\r
+\r
+\ingroup rtree_functions\r
+ \r
+\return The iterator pointing at the end of the query range.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator> inline\r
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::const_query_iterator\r
+qend(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)\r
+{\r
+ return tree.qend();\r
+}\r
+\r
+/*!\r
+\brief Returns the iterator pointing at the begin of the rtree values range.\r
+\r
+This method returns the iterator which may be used to iterate over all values\r
+stored in the rtree.\r
+\r
+\par Example\r
+\verbatim\r
+std::for_each(bgi::begin(tree), bgi::end(tree), do_something());\r
+// the same as\r
+std::for_each(boost::begin(tree), boost::end(tree), do_something());\r
+\endverbatim\r
+\r
+\par Iterator category\r
+ForwardIterator\r
+\r
+\par Throws\r
+If allocation throws.\r
+\r
+\warning\r
+The modification of the rtree may invalidate the iterators.\r
+\r
+\ingroup rtree_functions\r
+\r
+\return The iterator pointing at the begin of the range.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator> inline\r
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::const_iterator\r
+begin(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)\r
+{\r
+ return tree.begin();\r
+}\r
+\r
+/*!\r
+\brief Returns the iterator pointing at the end of the rtree values range.\r
+\r
+This method returns the iterator which may be compared with the iterator returned by begin()\r
+in order to check if the iteration has ended.\r
+\r
+\par Example\r
+\verbatim\r
+std::for_each(bgi::begin(tree), bgi::end(tree), do_something());\r
+// the same as\r
+std::for_each(boost::begin(tree), boost::end(tree), do_something());\r
+\endverbatim\r
+\r
+\par Iterator category\r
+ForwardIterator\r
+\r
+\par Throws\r
+Nothing.\r
+\r
+\warning\r
+The modification of the rtree may invalidate the iterators.\r
+\r
+\ingroup rtree_functions\r
+\r
+\return The iterator pointing at the end of the range.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator> inline\r
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::const_iterator\r
+end(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)\r
+{\r
+ return tree.end();\r
+}\r
+\r
+/*!\r
+\brief Remove all values from the index.\r
+\r
+It calls \c rtree::clear().\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline void clear(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree)\r
+{\r
+ return tree.clear();\r
+}\r
+\r
+/*!\r
+\brief Get the number of values stored in the index.\r
+\r
+It calls \c rtree::size().\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\r
+\return The number of values stored in the index.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline size_t size(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)\r
+{\r
+ return tree.size();\r
+}\r
+\r
+/*!\r
+\brief Query if there are no values stored in the index.\r
+\r
+It calls \c rtree::empty().\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\r
+\return true if there are no values in the index.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline bool empty(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)\r
+{\r
+ return tree.bounds();\r
+}\r
+\r
+/*!\r
+\brief Get the box containing all stored values or an invalid box if the index has no values.\r
+\r
+It calls \c rtree::envelope().\r
+\r
+\ingroup rtree_functions\r
+\r
+\param tree The spatial index.\r
+\r
+\return The box containing all stored values or an invalid box.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::bounds_type\r
+bounds(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)\r
+{\r
+ return tree.bounds();\r
+}\r
+\r
+/*!\r
+\brief Exchanges the contents of the container with those of other.\r
+\r
+It calls \c rtree::swap().\r
+\r
+\ingroup rtree_functions\r
+\r
+\param l The first rtree.\r
+\param r The second rtree.\r
+*/\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+inline void swap(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & l,\r
+ rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & r)\r
+{\r
+ return l.swap(r);\r
+}\r
+\r
+}}} // namespace boost::geometry::index\r
+\r
+// Boost.Range adaptation\r
+namespace boost {\r
+\r
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>\r
+struct range_mutable_iterator\r
+ <\r
+ boost::geometry::index::rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>\r
+ >\r
+{\r
+ typedef typename boost::geometry::index::rtree\r
+ <\r
+ Value, Parameters, IndexableGetter, EqualTo, Allocator\r
+ >::const_iterator type;\r
+};\r
+\r
+} // namespace boost\r
+\r
+// TODO: don't include the implementation at the end of the file\r
+#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>\r
+\r
+#include <boost/geometry/index/detail/config_end.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_INDEX_RTREE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP\r
+#define BOOST_GEOMETRY_IO_DSV_WRITE_HPP\r
+\r
+#include <cstddef>\r
+#include <ostream>\r
+#include <string>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace dsv\r
+{\r
+\r
+struct dsv_settings\r
+{\r
+ std::string coordinate_separator;\r
+ std::string point_open;\r
+ std::string point_close;\r
+ std::string point_separator;\r
+ std::string list_open;\r
+ std::string list_close;\r
+ std::string list_separator;\r
+\r
+ dsv_settings(std::string const& sep\r
+ , std::string const& open\r
+ , std::string const& close\r
+ , std::string const& psep\r
+ , std::string const& lopen\r
+ , std::string const& lclose\r
+ , std::string const& lsep\r
+ )\r
+ : coordinate_separator(sep)\r
+ , point_open(open)\r
+ , point_close(close)\r
+ , point_separator(psep)\r
+ , list_open(lopen)\r
+ , list_close(lclose)\r
+ , list_separator(lsep)\r
+ {}\r
+};\r
+\r
+/*!\r
+\brief Stream coordinate of a point as \ref DSV\r
+*/\r
+template <typename Point, std::size_t Dimension, std::size_t Count>\r
+struct stream_coordinate\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Point const& point,\r
+ dsv_settings const& settings)\r
+ {\r
+ os << (Dimension > 0 ? settings.coordinate_separator : "")\r
+ << get<Dimension>(point);\r
+\r
+ stream_coordinate\r
+ <\r
+ Point, Dimension + 1, Count\r
+ >::apply(os, point, settings);\r
+ }\r
+};\r
+\r
+template <typename Point, std::size_t Count>\r
+struct stream_coordinate<Point, Count, Count>\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>&,\r
+ Point const&,\r
+ dsv_settings const& )\r
+ {\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Stream indexed coordinate of a box/segment as \ref DSV\r
+*/\r
+template\r
+<\r
+ typename Geometry,\r
+ std::size_t Index,\r
+ std::size_t Dimension,\r
+ std::size_t Count\r
+>\r
+struct stream_indexed\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Geometry const& geometry,\r
+ dsv_settings const& settings)\r
+ {\r
+ os << (Dimension > 0 ? settings.coordinate_separator : "")\r
+ << get<Index, Dimension>(geometry);\r
+ stream_indexed\r
+ <\r
+ Geometry, Index, Dimension + 1, Count\r
+ >::apply(os, geometry, settings);\r
+ }\r
+};\r
+\r
+template <typename Geometry, std::size_t Index, std::size_t Count>\r
+struct stream_indexed<Geometry, Index, Count, Count>\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,\r
+ dsv_settings const& )\r
+ {\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Stream points as \ref DSV\r
+*/\r
+template <typename Point>\r
+struct dsv_point\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Point const& p,\r
+ dsv_settings const& settings)\r
+ {\r
+ os << settings.point_open;\r
+ stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);\r
+ os << settings.point_close;\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Stream ranges as DSV\r
+\note policy is used to stream prefix/postfix, enabling derived classes to override this\r
+*/\r
+template <typename Range>\r
+struct dsv_range\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Range const& range,\r
+ dsv_settings const& settings)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator_type;\r
+\r
+ bool first = true;\r
+\r
+ os << settings.list_open;\r
+\r
+ for (iterator_type it = boost::begin(range);\r
+ it != boost::end(range);\r
+ ++it)\r
+ {\r
+ os << (first ? "" : settings.point_separator)\r
+ << settings.point_open;\r
+\r
+ stream_coordinate\r
+ <\r
+ point_type, 0, dimension<point_type>::type::value\r
+ >::apply(os, *it, settings);\r
+ os << settings.point_close;\r
+\r
+ first = false;\r
+ }\r
+\r
+ os << settings.list_close;\r
+ }\r
+\r
+private:\r
+ typedef typename boost::range_value<Range>::type point_type;\r
+};\r
+\r
+/*!\r
+\brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)\r
+\note Used in polygon, all multi-geometries\r
+*/\r
+\r
+template <typename Polygon>\r
+struct dsv_poly\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Polygon const& poly,\r
+ dsv_settings const& settings)\r
+ {\r
+ typedef typename ring_type<Polygon>::type ring;\r
+\r
+ os << settings.list_open;\r
+\r
+ dsv_range<ring>::apply(os, exterior_ring(poly), settings);\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(poly);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ os << settings.list_separator;\r
+ dsv_range<ring>::apply(os, *it, settings);\r
+ }\r
+ os << settings.list_close;\r
+ }\r
+};\r
+\r
+template <typename Geometry, std::size_t Index>\r
+struct dsv_per_index\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Geometry const& geometry,\r
+ dsv_settings const& settings)\r
+ {\r
+ os << settings.point_open;\r
+ stream_indexed\r
+ <\r
+ Geometry, Index, 0, dimension<Geometry>::type::value\r
+ >::apply(os, geometry, settings);\r
+ os << settings.point_close;\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct dsv_indexed\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Geometry const& geometry,\r
+ dsv_settings const& settings)\r
+ {\r
+ os << settings.list_open;\r
+ dsv_per_index<Geometry, 0>::apply(os, geometry, settings);\r
+ os << settings.point_separator;\r
+ dsv_per_index<Geometry, 1>::apply(os, geometry, settings);\r
+ os << settings.list_close;\r
+ }\r
+};\r
+\r
+}} // namespace detail::dsv\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry>\r
+struct dsv {};\r
+\r
+template <typename Point>\r
+struct dsv<point_tag, Point>\r
+ : detail::dsv::dsv_point<Point>\r
+{};\r
+\r
+template <typename Linestring>\r
+struct dsv<linestring_tag, Linestring>\r
+ : detail::dsv::dsv_range<Linestring>\r
+{};\r
+\r
+template <typename Box>\r
+struct dsv<box_tag, Box>\r
+ : detail::dsv::dsv_indexed<Box>\r
+{};\r
+\r
+template <typename Segment>\r
+struct dsv<segment_tag, Segment>\r
+ : detail::dsv::dsv_indexed<Segment>\r
+{};\r
+\r
+template <typename Ring>\r
+struct dsv<ring_tag, Ring>\r
+ : detail::dsv::dsv_range<Ring>\r
+{};\r
+\r
+template <typename Polygon>\r
+struct dsv<polygon_tag, Polygon>\r
+ : detail::dsv::dsv_poly<Polygon>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace dsv\r
+{\r
+\r
+// FIXME: This class is not copyable/assignable but it is used as such --mloskot\r
+template <typename Geometry>\r
+class dsv_manipulator\r
+{\r
+public:\r
+\r
+ inline dsv_manipulator(Geometry const& g,\r
+ dsv_settings const& settings)\r
+ : m_geometry(g)\r
+ , m_settings(settings)\r
+ {}\r
+\r
+ template <typename Char, typename Traits>\r
+ inline friend std::basic_ostream<Char, Traits>& operator<<(\r
+ std::basic_ostream<Char, Traits>& os,\r
+ dsv_manipulator const& m)\r
+ {\r
+ dispatch::dsv\r
+ <\r
+ typename tag_cast\r
+ <\r
+ typename tag<Geometry>::type,\r
+ multi_tag\r
+ >::type,\r
+ Geometry\r
+ >::apply(os, m.m_geometry, m.m_settings);\r
+ os.flush();\r
+ return os;\r
+ }\r
+\r
+private:\r
+ Geometry const& m_geometry;\r
+ dsv_settings m_settings;\r
+};\r
+\r
+\r
+template <typename MultiGeometry>\r
+struct dsv_multi\r
+{\r
+ typedef dispatch::dsv\r
+ <\r
+ typename single_tag_of\r
+ <\r
+ typename tag<MultiGeometry>::type\r
+ >::type,\r
+ typename boost::range_value<MultiGeometry>::type\r
+ > dispatch_one;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ MultiGeometry const\r
+ >::type iterator;\r
+\r
+\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ MultiGeometry const& multi,\r
+ dsv_settings const& settings)\r
+ {\r
+ os << settings.list_open;\r
+\r
+ bool first = true;\r
+ for(iterator it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it, first = false)\r
+ {\r
+ os << (first ? "" : settings.list_separator);\r
+ dispatch_one::apply(os, *it, settings);\r
+ }\r
+ os << settings.list_close;\r
+ }\r
+};\r
+\r
+}} // namespace detail::dsv\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+// TODO: The alternative to this could be a forward declaration of dispatch::dsv<>\r
+// or braking the code into the interface and implementation part\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Geometry>\r
+struct dsv<multi_tag, Geometry>\r
+ : detail::dsv::dsv_multi<Geometry>\r
+{};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+/*!\r
+\brief Main DSV-streaming function\r
+\details DSV stands for Delimiter Separated Values. Geometries can be streamed\r
+ as DSV. There are defaults for all separators.\r
+\note Useful for examples and testing purposes\r
+\note With this function GeoJSON objects can be created, using the right\r
+ delimiters\r
+\ingroup utility\r
+*/\r
+template <typename Geometry>\r
+inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry\r
+ , std::string const& coordinate_separator = ", "\r
+ , std::string const& point_open = "("\r
+ , std::string const& point_close = ")"\r
+ , std::string const& point_separator = ", "\r
+ , std::string const& list_open = "("\r
+ , std::string const& list_close = ")"\r
+ , std::string const& list_separator = ", "\r
+ )\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ return detail::dsv::dsv_manipulator<Geometry>(geometry,\r
+ detail::dsv::dsv_settings(coordinate_separator,\r
+ point_open, point_close, point_separator,\r
+ list_open, list_close, list_separator));\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_HPP\r
+#define BOOST_GEOMETRY_IO_HPP\r
+\r
+#include <boost/geometry/io/wkt/read.hpp>\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+struct format_wkt {};\r
+struct format_wkb {}; // TODO\r
+struct format_dsv {}; // TODO\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+template <typename Tag, typename Geometry>\r
+struct read\r
+{\r
+};\r
+\r
+template <typename Geometry>\r
+struct read<format_wkt, Geometry>\r
+{\r
+ static inline void apply(Geometry& geometry, std::string const& wkt)\r
+ {\r
+ read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+template <typename Format, typename Geometry>\r
+inline void read(Geometry& geometry, std::string const& wkt)\r
+{\r
+ geometry::concepts::check<Geometry>();\r
+ dispatch::read<Format, Geometry>::apply(geometry, wkt);\r
+}\r
+\r
+// TODO: wriite\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_IO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015, 2016.\r
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_SVG_MAPPER_HPP\r
+#define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP\r
+\r
+#include <cstdio>\r
+\r
+#include <vector>\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/scoped_ptr.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/type_traits/remove_const.hpp>\r
+\r
+#include <boost/algorithm/string/split.hpp>\r
+#include <boost/algorithm/string/classification.hpp>\r
+\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+#include <boost/geometry/algorithms/transform.hpp>\r
+#include <boost/geometry/strategies/transform/map_transformer.hpp>\r
+#include <boost/geometry/views/segment_view.hpp>\r
+\r
+#include <boost/geometry/io/svg/write.hpp>\r
+\r
+// Helper geometries (all points are transformed to svg-points)\r
+#include <boost/geometry/geometries/geometries.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename GeometryTag, typename Geometry, typename SvgPoint>\r
+struct svg_map\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (Geometry)\r
+ );\r
+};\r
+\r
+\r
+template <typename Point, typename SvgPoint>\r
+struct svg_map<point_tag, Point, SvgPoint>\r
+{\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style, double size,\r
+ Point const& point, TransformStrategy const& strategy)\r
+ {\r
+ SvgPoint ipoint;\r
+ geometry::transform(point, ipoint, strategy);\r
+ stream << geometry::svg(ipoint, style, size) << std::endl;\r
+ }\r
+};\r
+\r
+template <typename BoxSeg1, typename BoxSeg2, typename SvgPoint>\r
+struct svg_map_box_seg\r
+{\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style, double size,\r
+ BoxSeg1 const& box_seg, TransformStrategy const& strategy)\r
+ {\r
+ BoxSeg2 ibox_seg;\r
+\r
+ // Fix bug in gcc compiler warning for possible uninitialization\r
+#if defined(BOOST_GCC)\r
+ geometry::assign_zero(ibox_seg);\r
+#endif\r
+ geometry::transform(box_seg, ibox_seg, strategy);\r
+\r
+ stream << geometry::svg(ibox_seg, style, size) << std::endl;\r
+ }\r
+};\r
+\r
+template <typename Box, typename SvgPoint>\r
+struct svg_map<box_tag, Box, SvgPoint>\r
+ : svg_map_box_seg<Box, model::box<SvgPoint>, SvgPoint>\r
+{};\r
+\r
+template <typename Segment, typename SvgPoint>\r
+struct svg_map<segment_tag, Segment, SvgPoint>\r
+ : svg_map_box_seg<Segment, model::segment<SvgPoint>, SvgPoint>\r
+{};\r
+\r
+\r
+template <typename Range1, typename Range2, typename SvgPoint>\r
+struct svg_map_range\r
+{\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style, double size,\r
+ Range1 const& range, TransformStrategy const& strategy)\r
+ {\r
+ Range2 irange;\r
+ geometry::transform(range, irange, strategy);\r
+ stream << geometry::svg(irange, style, size) << std::endl;\r
+ }\r
+};\r
+\r
+template <typename Ring, typename SvgPoint>\r
+struct svg_map<ring_tag, Ring, SvgPoint>\r
+ : svg_map_range<Ring, model::ring<SvgPoint>, SvgPoint>\r
+{};\r
+\r
+\r
+template <typename Linestring, typename SvgPoint>\r
+struct svg_map<linestring_tag, Linestring, SvgPoint>\r
+ : svg_map_range<Linestring, model::linestring<SvgPoint>, SvgPoint>\r
+{};\r
+\r
+\r
+template <typename Polygon, typename SvgPoint>\r
+struct svg_map<polygon_tag, Polygon, SvgPoint>\r
+{\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style, double size,\r
+ Polygon const& polygon, TransformStrategy const& strategy)\r
+ {\r
+ model::polygon<SvgPoint> ipoly;\r
+ geometry::transform(polygon, ipoly, strategy);\r
+ stream << geometry::svg(ipoly, style, size) << std::endl;\r
+ }\r
+};\r
+\r
+\r
+template <typename Multi, typename SvgPoint>\r
+struct svg_map<multi_tag, Multi, SvgPoint>\r
+{\r
+ typedef typename single_tag_of\r
+ <\r
+ typename geometry::tag<Multi>::type\r
+ >::type stag;\r
+\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style, double size,\r
+ Multi const& multi, TransformStrategy const& strategy)\r
+ {\r
+ for (typename boost::range_iterator<Multi const>::type it\r
+ = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ svg_map\r
+ <\r
+ stag,\r
+ typename boost::range_value<Multi>::type,\r
+ SvgPoint\r
+ >::apply(stream, style, size, *it, strategy);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename SvgPoint, typename Geometry>\r
+struct devarianted_svg_map\r
+{\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style,\r
+ double size,\r
+ Geometry const& geometry,\r
+ TransformStrategy const& strategy)\r
+ {\r
+ svg_map\r
+ <\r
+ typename tag_cast\r
+ <\r
+ typename tag<Geometry>::type,\r
+ multi_tag\r
+ >::type,\r
+ typename boost::remove_const<Geometry>::type,\r
+ SvgPoint\r
+ >::apply(stream, style, size, geometry, strategy);\r
+ }\r
+};\r
+\r
+template <typename SvgPoint, BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct devarianted_svg_map<SvgPoint, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename TransformStrategy>\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ std::ostream& m_os;\r
+ std::string const& m_style;\r
+ double m_size;\r
+ TransformStrategy const& m_strategy;\r
+\r
+ visitor(std::ostream& os,\r
+ std::string const& style,\r
+ double size,\r
+ TransformStrategy const& strategy)\r
+ : m_os(os)\r
+ , m_style(style)\r
+ , m_size(size)\r
+ , m_strategy(strategy)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ inline void operator()(Geometry const& geometry) const\r
+ {\r
+ devarianted_svg_map<SvgPoint, Geometry>::apply(m_os, m_style, m_size, geometry, m_strategy);\r
+ }\r
+ };\r
+\r
+ template <typename TransformStrategy>\r
+ static inline void apply(std::ostream& stream,\r
+ std::string const& style,\r
+ double size,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ TransformStrategy const& strategy)\r
+ {\r
+ boost::apply_visitor(visitor<TransformStrategy>(stream, style, size, strategy), geometry);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+template <typename SvgPoint, typename Geometry, typename TransformStrategy>\r
+inline void svg_map(std::ostream& stream,\r
+ std::string const& style, double size,\r
+ Geometry const& geometry, TransformStrategy const& strategy)\r
+{\r
+ dispatch::devarianted_svg_map<SvgPoint, Geometry>::apply(stream,\r
+ style, size, geometry, strategy);\r
+}\r
+\r
+\r
+/*!\r
+\brief Helper class to create SVG maps\r
+\tparam Point Point type, for input geometries.\r
+\tparam SameScale Boolean flag indicating if horizontal and vertical scale should\r
+ be the same. The default value is true\r
+\tparam SvgCoordinateType Coordinate type of SVG points. SVG is capable to\r
+ use floating point coordinates. Therefore the default value is double\r
+\ingroup svg\r
+\r
+\qbk{[include reference/io/svg.qbk]}\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ bool SameScale = true,\r
+ typename SvgCoordinateType = double\r
+>\r
+class svg_mapper : boost::noncopyable\r
+{\r
+ typedef model::point<SvgCoordinateType, 2, cs::cartesian> svg_point_type;\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ typename coordinate_type<Point>::type,\r
+ double\r
+ >::type calculation_type;\r
+\r
+ typedef strategy::transform::map_transformer\r
+ <\r
+ calculation_type,\r
+ geometry::dimension<Point>::type::value,\r
+ geometry::dimension<Point>::type::value,\r
+ true,\r
+ SameScale\r
+ > transformer_type;\r
+\r
+ model::box<Point> m_bounding_box;\r
+ boost::scoped_ptr<transformer_type> m_matrix;\r
+ std::ostream& m_stream;\r
+ SvgCoordinateType m_width, m_height;\r
+ std::string m_width_height; // for <svg> tag only, defaults to 2x 100%\r
+\r
+ void init_matrix()\r
+ {\r
+ if (! m_matrix)\r
+ {\r
+ m_matrix.reset(new transformer_type(m_bounding_box,\r
+ m_width, m_height));\r
+\r
+\r
+ m_stream << "<?xml version=\"1.0\" standalone=\"no\"?>"\r
+ << std::endl\r
+ << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""\r
+ << std::endl\r
+ << "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"\r
+ << std::endl\r
+ << "<svg " << m_width_height << " version=\"1.1\""\r
+ << std::endl\r
+ << "xmlns=\"http://www.w3.org/2000/svg\""\r
+ << std::endl\r
+ << "xmlns:xlink=\"http://www.w3.org/1999/xlink\""\r
+ << ">"\r
+ << std::endl;\r
+ }\r
+ }\r
+\r
+public :\r
+ \r
+ /*!\r
+ \brief Constructor, initializing the SVG map. Opens and initializes the SVG. \r
+ Should be called explicitly.\r
+ \param stream Output stream, should be a stream already open\r
+ \param width Width of the SVG map (in SVG pixels)\r
+ \param height Height of the SVG map (in SVG pixels)\r
+ \param width_height Optional information to increase width and/or height\r
+ */\r
+ svg_mapper(std::ostream& stream\r
+ , SvgCoordinateType width\r
+ , SvgCoordinateType height\r
+ , std::string const& width_height = "width=\"100%\" height=\"100%\"")\r
+ : m_stream(stream)\r
+ , m_width(width)\r
+ , m_height(height)\r
+ , m_width_height(width_height)\r
+ {\r
+ assign_inverse(m_bounding_box);\r
+ }\r
+\r
+ /*!\r
+ \brief Destructor, called automatically. Closes the SVG by streaming <\/svg>\r
+ */\r
+ virtual ~svg_mapper()\r
+ {\r
+ m_stream << "</svg>" << std::endl;\r
+ }\r
+\r
+ /*!\r
+ \brief Adds a geometry to the transformation matrix. After doing this,\r
+ the specified geometry can be mapped fully into the SVG map\r
+ \tparam Geometry \tparam_geometry\r
+ \param geometry \param_geometry\r
+ */\r
+ template <typename Geometry>\r
+ void add(Geometry const& geometry)\r
+ {\r
+ if (! geometry::is_empty(geometry))\r
+ {\r
+ expand(m_bounding_box,\r
+ return_envelope\r
+ <\r
+ model::box<Point>\r
+ >(geometry));\r
+ }\r
+ }\r
+\r
+ /*!\r
+ \brief Maps a geometry into the SVG map using the specified style\r
+ \tparam Geometry \tparam_geometry\r
+ \param geometry \param_geometry\r
+ \param style String containing verbatim SVG style information\r
+ \param size Optional size (used for SVG points) in SVG pixels. For linestrings,\r
+ specify linewidth in the SVG style information\r
+ */\r
+ template <typename Geometry>\r
+ void map(Geometry const& geometry, std::string const& style,\r
+ double size = -1.0)\r
+ {\r
+ init_matrix();\r
+ svg_map<svg_point_type>(m_stream, style, size, geometry, *m_matrix);\r
+ }\r
+\r
+ /*!\r
+ \brief Adds a text to the SVG map\r
+ \tparam TextPoint \tparam_point\r
+ \param point Location of the text (in map units)\r
+ \param s The text itself\r
+ \param style String containing verbatim SVG style information, of the text\r
+ \param offset_x Offset in SVG pixels, defaults to 0\r
+ \param offset_y Offset in SVG pixels, defaults to 0\r
+ \param lineheight Line height in SVG pixels, in case the text contains \n\r
+ */\r
+ template <typename TextPoint>\r
+ void text(TextPoint const& point, std::string const& s,\r
+ std::string const& style,\r
+ double offset_x = 0.0, double offset_y = 0.0,\r
+ double lineheight = 10.0)\r
+ {\r
+ init_matrix();\r
+ svg_point_type map_point;\r
+ transform(point, map_point, *m_matrix);\r
+ m_stream\r
+ << "<text style=\"" << style << "\""\r
+ << " x=\"" << get<0>(map_point) + offset_x << "\""\r
+ << " y=\"" << get<1>(map_point) + offset_y << "\""\r
+ << ">";\r
+ if (s.find("\n") == std::string::npos)\r
+ {\r
+ m_stream << s;\r
+ }\r
+ else\r
+ {\r
+ // Multi-line modus\r
+\r
+ std::vector<std::string> splitted;\r
+ boost::split(splitted, s, boost::is_any_of("\n"));\r
+ for (std::vector<std::string>::const_iterator it\r
+ = splitted.begin();\r
+ it != splitted.end();\r
+ ++it, offset_y += lineheight)\r
+ {\r
+ m_stream\r
+ << "<tspan x=\"" << get<0>(map_point) + offset_x\r
+ << "\""\r
+ << " y=\"" << get<1>(map_point) + offset_y\r
+ << "\""\r
+ << ">" << *it << "</tspan>";\r
+ }\r
+ }\r
+ m_stream << "</text>" << std::endl;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_IO_SVG_MAPPER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_HPP\r
+#define BOOST_GEOMETRY_IO_SVG_WRITE_HPP\r
+\r
+#include <ostream>\r
+#include <string>\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace svg\r
+{\r
+\r
+\r
+template <typename Point>\r
+struct svg_point\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Point const& p, std::string const& style, double size)\r
+ {\r
+ os << "<circle cx=\"" << geometry::get<0>(p)\r
+ << "\" cy=\"" << geometry::get<1>(p)\r
+ << "\" r=\"" << (size < 0 ? 5 : size)\r
+ << "\" style=\"" << style << "\"/>";\r
+ }\r
+};\r
+\r
+\r
+template <typename Box>\r
+struct svg_box\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Box const& box, std::string const& style, double)\r
+ {\r
+ // Prevent invisible boxes, making them >=1, using "max"\r
+ BOOST_USING_STD_MAX();\r
+\r
+ typedef typename coordinate_type<Box>::type ct;\r
+ ct x = geometry::get<geometry::min_corner, 0>(box);\r
+ ct y = geometry::get<geometry::min_corner, 1>(box);\r
+ ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),\r
+ geometry::get<geometry::max_corner, 0>(box) - x);\r
+ ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),\r
+ geometry::get<geometry::max_corner, 1>(box) - y);\r
+\r
+ os << "<rect x=\"" << x << "\" y=\"" << y\r
+ << "\" width=\"" << width << "\" height=\"" << height\r
+ << "\" style=\"" << style << "\"/>";\r
+ }\r
+};\r
+\r
+template <typename Segment>\r
+struct svg_segment\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Segment const& segment, std::string const& style, double)\r
+ {\r
+ typedef typename coordinate_type<Segment>::type ct;\r
+ ct x1 = geometry::get<0, 0>(segment);\r
+ ct y1 = geometry::get<0, 1>(segment);\r
+ ct x2 = geometry::get<1, 0>(segment);\r
+ ct y2 = geometry::get<1, 1>(segment);\r
+ \r
+ os << "<line x1=\"" << x1 << "\" y1=\"" << y1\r
+ << "\" x2=\"" << x2 << "\" y2=\"" << y2\r
+ << "\" style=\"" << style << "\"/>";\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Stream ranges as SVG\r
+\note policy is used to select type (polyline/polygon)\r
+*/\r
+template <typename Range, typename Policy>\r
+struct svg_range\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Range const& range, std::string const& style, double)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator;\r
+\r
+ bool first = true;\r
+\r
+ os << "<" << Policy::prefix() << " points=\"";\r
+\r
+ for (iterator it = boost::begin(range);\r
+ it != boost::end(range);\r
+ ++it, first = false)\r
+ {\r
+ os << (first ? "" : " " )\r
+ << geometry::get<0>(*it)\r
+ << ","\r
+ << geometry::get<1>(*it);\r
+ }\r
+ os << "\" style=\"" << style << Policy::style() << "\"/>";\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename Polygon>\r
+struct svg_poly\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Polygon const& polygon, std::string const& style, double)\r
+ {\r
+ typedef typename geometry::ring_type<Polygon>::type ring_type;\r
+ typedef typename boost::range_iterator<ring_type const>::type iterator_type;\r
+\r
+ bool first = true;\r
+ os << "<g fill-rule=\"evenodd\"><path d=\"";\r
+\r
+ ring_type const& ring = geometry::exterior_ring(polygon);\r
+ for (iterator_type it = boost::begin(ring);\r
+ it != boost::end(ring);\r
+ ++it, first = false)\r
+ {\r
+ os << (first ? "M" : " L") << " "\r
+ << geometry::get<0>(*it)\r
+ << ","\r
+ << geometry::get<1>(*it);\r
+ }\r
+\r
+ // Inner rings:\r
+ {\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(polygon);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ rit = boost::begin(rings); rit != boost::end(rings); ++rit)\r
+ {\r
+ first = true;\r
+ for (typename detail::interior_ring_iterator<Polygon const>::type\r
+ it = boost::begin(*rit); it != boost::end(*rit);\r
+ ++it, first = false)\r
+ {\r
+ os << (first ? "M" : " L") << " "\r
+ << geometry::get<0>(*it)\r
+ << ","\r
+ << geometry::get<1>(*it);\r
+ }\r
+ }\r
+ }\r
+ os << " z \" style=\"" << style << "\"/></g>";\r
+\r
+ }\r
+};\r
+\r
+\r
+\r
+struct prefix_linestring\r
+{\r
+ static inline const char* prefix() { return "polyline"; }\r
+ static inline const char* style() { return ";fill:none"; }\r
+};\r
+\r
+\r
+struct prefix_ring\r
+{\r
+ static inline const char* prefix() { return "polygon"; }\r
+ static inline const char* style() { return ""; }\r
+};\r
+\r
+\r
+template <typename MultiGeometry, typename Policy>\r
+struct svg_multi\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ MultiGeometry const& multi, std::string const& style, double size)\r
+ {\r
+ for (typename boost::range_iterator<MultiGeometry const>::type\r
+ it = boost::begin(multi);\r
+ it != boost::end(multi);\r
+ ++it)\r
+ {\r
+ Policy::apply(os, *it, style, size);\r
+ }\r
+\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace detail::svg\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+/*!\r
+\brief Dispatching base struct for SVG streaming, specialized below per geometry type\r
+\details Specializations should implement a static method "stream" to stream a geometry\r
+The static method should have the signature:\r
+\r
+template <typename Char, typename Traits>\r
+static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)\r
+*/\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct svg\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (Geometry)\r
+ );\r
+};\r
+\r
+template <typename Point>\r
+struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};\r
+\r
+template <typename Segment>\r
+struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};\r
+\r
+template <typename Box>\r
+struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};\r
+\r
+template <typename Linestring>\r
+struct svg<Linestring, linestring_tag>\r
+ : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};\r
+\r
+template <typename Ring>\r
+struct svg<Ring, ring_tag>\r
+ : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};\r
+\r
+template <typename Polygon>\r
+struct svg<Polygon, polygon_tag>\r
+ : detail::svg::svg_poly<Polygon> {};\r
+\r
+template <typename MultiPoint>\r
+struct svg<MultiPoint, multi_point_tag>\r
+ : detail::svg::svg_multi\r
+ <\r
+ MultiPoint,\r
+ detail::svg::svg_point\r
+ <\r
+ typename boost::range_value<MultiPoint>::type\r
+ >\r
+\r
+ >\r
+{};\r
+\r
+template <typename MultiLinestring>\r
+struct svg<MultiLinestring, multi_linestring_tag>\r
+ : detail::svg::svg_multi\r
+ <\r
+ MultiLinestring,\r
+ detail::svg::svg_range\r
+ <\r
+ typename boost::range_value<MultiLinestring>::type,\r
+ detail::svg::prefix_linestring\r
+ >\r
+\r
+ >\r
+{};\r
+\r
+template <typename MultiPolygon>\r
+struct svg<MultiPolygon, multi_polygon_tag>\r
+ : detail::svg::svg_multi\r
+ <\r
+ MultiPolygon,\r
+ detail::svg::svg_poly\r
+ <\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >\r
+\r
+ >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct devarianted_svg\r
+{\r
+ template <typename OutputStream>\r
+ static inline void apply(OutputStream& os,\r
+ Geometry const& geometry,\r
+ std::string const& style,\r
+ double size)\r
+ {\r
+ svg<Geometry>::apply(os, geometry, style, size);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct devarianted_svg<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename OutputStream>\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ OutputStream& m_os;\r
+ std::string const& m_style;\r
+ double m_size;\r
+\r
+ visitor(OutputStream& os, std::string const& style, double size)\r
+ : m_os(os)\r
+ , m_style(style)\r
+ , m_size(size)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ inline void operator()(Geometry const& geometry) const\r
+ {\r
+ devarianted_svg<Geometry>::apply(m_os, geometry, m_style, m_size);\r
+ }\r
+ };\r
+\r
+ template <typename OutputStream>\r
+ static inline void apply(\r
+ OutputStream& os,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,\r
+ std::string const& style,\r
+ double size\r
+ )\r
+ {\r
+ boost::apply_visitor(visitor<OutputStream>(os, style, size), geometry);\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief Generic geometry template manipulator class, takes corresponding output class from traits class\r
+\ingroup svg\r
+\details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics)\r
+*/\r
+template <typename Geometry>\r
+class svg_manipulator\r
+{\r
+public:\r
+\r
+ inline svg_manipulator(Geometry const& g, std::string const& style, double size)\r
+ : m_geometry(g)\r
+ , m_style(style)\r
+ , m_size(size)\r
+ {}\r
+\r
+ template <typename Char, typename Traits>\r
+ inline friend std::basic_ostream<Char, Traits>& operator<<(\r
+ std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)\r
+ {\r
+ dispatch::devarianted_svg<Geometry>::apply(os,\r
+ m.m_geometry,\r
+ m.m_style,\r
+ m.m_size);\r
+ os.flush();\r
+ return os;\r
+ }\r
+\r
+private:\r
+ Geometry const& m_geometry;\r
+ std::string const& m_style;\r
+ double m_size;\r
+};\r
+\r
+/*!\r
+\brief Manipulator to stream geometries as SVG\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\param style String containing verbatim SVG style information\r
+\param size Optional size (used for SVG points) in SVG pixels. For linestrings,\r
+ specify linewidth in the SVG style information\r
+\ingroup svg\r
+*/\r
+template <typename Geometry>\r
+inline svg_manipulator<Geometry> svg(Geometry const& geometry,\r
+ std::string const& style, double size = -1.0)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ return svg_manipulator<Geometry>(geometry, style, size);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP\r
+#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP\r
+\r
+\r
+// THIS FILE WAS LEFT HERE FOR BACKWARD COMPATIBILITY\r
+\r
+\r
+#include <boost/geometry/io/svg/write.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP\r
+#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP\r
+\r
+\r
+// THIS FILE WAS LEFT HERE FOR BACKWARD COMPATIBILITY\r
+\r
+\r
+#include <boost/geometry/io/svg/write.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP\r
+#define BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace wkt\r
+{\r
+\r
+struct prefix_null\r
+{\r
+ static inline const char* apply() { return ""; }\r
+};\r
+\r
+struct prefix_point\r
+{\r
+ static inline const char* apply() { return "POINT"; }\r
+};\r
+\r
+struct prefix_polygon\r
+{\r
+ static inline const char* apply() { return "POLYGON"; }\r
+};\r
+\r
+struct prefix_linestring\r
+{\r
+ static inline const char* apply() { return "LINESTRING"; }\r
+};\r
+\r
+struct prefix_multipoint\r
+{\r
+ static inline const char* apply() { return "MULTIPOINT"; }\r
+};\r
+\r
+struct prefix_multilinestring\r
+{\r
+ static inline const char* apply() { return "MULTILINESTRING"; }\r
+};\r
+\r
+struct prefix_multipolygon\r
+{\r
+ static inline const char* apply() { return "MULTIPOLYGON"; }\r
+};\r
+\r
+}} // namespace wkt::impl\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP\r
+#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/domains/gis/io/wkt/write.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace wkt\r
+{\r
+\r
+struct prefix_null\r
+{\r
+ static inline const char* apply() { return ""; }\r
+};\r
+\r
+struct prefix_multipoint\r
+{\r
+ static inline const char* apply() { return "MULTIPOINT"; }\r
+};\r
+\r
+struct prefix_multilinestring\r
+{\r
+ static inline const char* apply() { return "MULTILINESTRING"; }\r
+};\r
+\r
+struct prefix_multipolygon\r
+{\r
+ static inline const char* apply() { return "MULTIPOLYGON"; }\r
+};\r
+\r
+\r
+\r
+}} // namespace wkt::impl\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_WKT_READ_HPP\r
+#define BOOST_GEOMETRY_IO_WKT_READ_HPP\r
+\r
+#include <cstddef>\r
+#include <string>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/tokenizer.hpp>\r
+\r
+#include <boost/algorithm/string.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/range/begin.hpp>\r
+#include <boost/range/end.hpp>\r
+#include <boost/range/size.hpp>\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/append.hpp>\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/exception.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/geometry_id.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+#include <boost/geometry/util/coordinate_cast.hpp>\r
+\r
+#include <boost/geometry/io/wkt/detail/prefix.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Exception showing things wrong with WKT parsing\r
+\ingroup wkt\r
+*/\r
+struct read_wkt_exception : public geometry::exception\r
+{\r
+ template <typename Iterator>\r
+ read_wkt_exception(std::string const& msg,\r
+ Iterator const& it,\r
+ Iterator const& end,\r
+ std::string const& wkt)\r
+ : message(msg)\r
+ , wkt(wkt)\r
+ {\r
+ if (it != end)\r
+ {\r
+ source = " at '";\r
+ source += it->c_str();\r
+ source += "'";\r
+ }\r
+ complete = message + source + " in '" + wkt.substr(0, 100) + "'";\r
+ }\r
+\r
+ read_wkt_exception(std::string const& msg, std::string const& wkt)\r
+ : message(msg)\r
+ , wkt(wkt)\r
+ {\r
+ complete = message + "' in (" + wkt.substr(0, 100) + ")";\r
+ }\r
+\r
+ virtual ~read_wkt_exception() throw() {}\r
+\r
+ virtual const char* what() const throw()\r
+ {\r
+ return complete.c_str();\r
+ }\r
+private :\r
+ std::string source;\r
+ std::string message;\r
+ std::string wkt;\r
+ std::string complete;\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+// (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS))\r
+namespace detail { namespace wkt\r
+{\r
+\r
+typedef boost::tokenizer<boost::char_separator<char> > tokenizer;\r
+\r
+template <typename Point,\r
+ std::size_t Dimension = 0,\r
+ std::size_t DimensionCount = geometry::dimension<Point>::value>\r
+struct parsing_assigner\r
+{\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ Point& point,\r
+ std::string const& wkt)\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ // Stop at end of tokens, or at "," ot ")"\r
+ bool finished = (it == end || *it == "," || *it == ")");\r
+\r
+ try\r
+ {\r
+ // Initialize missing coordinates to default constructor (zero)\r
+ // OR\r
+ // Use lexical_cast for conversion to double/int\r
+ // Note that it is much slower than atof. However, it is more standard\r
+ // and in parsing the change in performance falls probably away against\r
+ // the tokenizing\r
+ set<Dimension>(point, finished\r
+ ? coordinate_type()\r
+ : coordinate_cast<coordinate_type>::apply(*it));\r
+ }\r
+ catch(boost::bad_lexical_cast const& blc)\r
+ {\r
+ throw read_wkt_exception(blc.what(), it, end, wkt);\r
+ }\r
+ catch(std::exception const& e)\r
+ {\r
+ throw read_wkt_exception(e.what(), it, end, wkt);\r
+ }\r
+ catch(...)\r
+ {\r
+ throw read_wkt_exception("", it, end, wkt);\r
+ }\r
+\r
+ parsing_assigner<Point, Dimension + 1, DimensionCount>::apply(\r
+ (finished ? it : ++it), end, point, wkt);\r
+ }\r
+};\r
+\r
+template <typename Point, std::size_t DimensionCount>\r
+struct parsing_assigner<Point, DimensionCount, DimensionCount>\r
+{\r
+ static inline void apply(tokenizer::iterator&,\r
+ tokenizer::iterator const&,\r
+ Point&,\r
+ std::string const&)\r
+ {\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename Iterator>\r
+inline void handle_open_parenthesis(Iterator& it,\r
+ Iterator const& end,\r
+ std::string const& wkt)\r
+{\r
+ if (it == end || *it != "(")\r
+ {\r
+ throw read_wkt_exception("Expected '('", it, end, wkt);\r
+ }\r
+ ++it;\r
+}\r
+\r
+\r
+template <typename Iterator>\r
+inline void handle_close_parenthesis(Iterator& it,\r
+ Iterator const& end,\r
+ std::string const& wkt)\r
+{\r
+ if (it != end && *it == ")")\r
+ {\r
+ ++it;\r
+ }\r
+ else\r
+ {\r
+ throw read_wkt_exception("Expected ')'", it, end, wkt);\r
+ }\r
+}\r
+\r
+template <typename Iterator>\r
+inline void check_end(Iterator& it,\r
+ Iterator const& end,\r
+ std::string const& wkt)\r
+{\r
+ if (it != end)\r
+ {\r
+ throw read_wkt_exception("Too much tokens", it, end, wkt);\r
+ }\r
+}\r
+\r
+/*!\r
+\brief Internal, parses coordinate sequences, strings are formated like "(1 2,3 4,...)"\r
+\param it token-iterator, should be pre-positioned at "(", is post-positions after last ")"\r
+\param end end-token-iterator\r
+\param out Output itererator receiving coordinates\r
+*/\r
+template <typename Point>\r
+struct container_inserter\r
+{\r
+ // Version with output iterator\r
+ template <typename OutputIterator>\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ OutputIterator out)\r
+ {\r
+ handle_open_parenthesis(it, end, wkt);\r
+\r
+ Point point;\r
+\r
+ // Parse points until closing parenthesis\r
+\r
+ while (it != end && *it != ")")\r
+ {\r
+ parsing_assigner<Point>::apply(it, end, point, wkt);\r
+ out = point;\r
+ ++out;\r
+ if (it != end && *it == ",")\r
+ {\r
+ ++it;\r
+ }\r
+ }\r
+\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry,\r
+ closure_selector Closure = closure<Geometry>::value>\r
+struct stateful_range_appender\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+\r
+ // NOTE: Geometry is a reference\r
+ inline void append(Geometry geom, point_type const& point, bool)\r
+ {\r
+ geometry::append(geom, point);\r
+ }\r
+};\r
+\r
+template <typename Geometry>\r
+struct stateful_range_appender<Geometry, open>\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef typename boost::range_size\r
+ <\r
+ typename util::bare_type<Geometry>::type\r
+ >::type size_type;\r
+\r
+ BOOST_STATIC_ASSERT(( boost::is_same\r
+ <\r
+ typename tag<Geometry>::type,\r
+ ring_tag\r
+ >::value ));\r
+\r
+ inline stateful_range_appender()\r
+ : pt_index(0)\r
+ {}\r
+\r
+ // NOTE: Geometry is a reference\r
+ inline void append(Geometry geom, point_type const& point, bool is_next_expected)\r
+ {\r
+ bool should_append = true;\r
+\r
+ if (pt_index == 0)\r
+ {\r
+ first_point = point;\r
+ //should_append = true;\r
+ }\r
+ else\r
+ {\r
+ // NOTE: if there is not enough Points, they're always appended\r
+ should_append\r
+ = is_next_expected\r
+ || pt_index < core_detail::closure::minimum_ring_size<open>::value\r
+ || !detail::equals::equals_point_point(point, first_point);\r
+ }\r
+ ++pt_index;\r
+\r
+ if (should_append)\r
+ {\r
+ geometry::append(geom, point);\r
+ }\r
+ }\r
+\r
+private:\r
+ size_type pt_index;\r
+ point_type first_point;\r
+};\r
+\r
+// Geometry is a value-type or reference-type\r
+template <typename Geometry>\r
+struct container_appender\r
+{\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ Geometry out)\r
+ {\r
+ handle_open_parenthesis(it, end, wkt);\r
+\r
+ stateful_range_appender<Geometry> appender;\r
+\r
+ // Parse points until closing parenthesis\r
+ while (it != end && *it != ")")\r
+ {\r
+ point_type point;\r
+\r
+ parsing_assigner<point_type>::apply(it, end, point, wkt);\r
+\r
+ bool const is_next_expected = it != end && *it == ",";\r
+\r
+ appender.append(out, point, is_next_expected);\r
+\r
+ if (is_next_expected)\r
+ {\r
+ ++it;\r
+ }\r
+ }\r
+\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Internal, parses a point from a string like this "(x y)"\r
+\note used for parsing points and multi-points\r
+*/\r
+template <typename P>\r
+struct point_parser\r
+{\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ P& point)\r
+ {\r
+ handle_open_parenthesis(it, end, wkt);\r
+ parsing_assigner<P>::apply(it, end, point, wkt);\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct linestring_parser\r
+{\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ Geometry& geometry)\r
+ {\r
+ container_appender<Geometry&>::apply(it, end, wkt, geometry);\r
+ }\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct ring_parser\r
+{\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ Ring& ring)\r
+ {\r
+ // A ring should look like polygon((x y,x y,x y...))\r
+ // So handle the extra opening/closing parentheses\r
+ // and in between parse using the container-inserter\r
+ handle_open_parenthesis(it, end, wkt);\r
+ container_appender<Ring&>::apply(it, end, wkt, ring);\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))"\r
+\note used for parsing polygons and multi-polygons\r
+*/\r
+template <typename Polygon>\r
+struct polygon_parser\r
+{\r
+ typedef typename ring_return_type<Polygon>::type ring_return_type;\r
+ typedef container_appender<ring_return_type> appender;\r
+\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ Polygon& poly)\r
+ {\r
+\r
+ handle_open_parenthesis(it, end, wkt);\r
+\r
+ int n = -1;\r
+\r
+ // Stop at ")"\r
+ while (it != end && *it != ")")\r
+ {\r
+ // Parse ring\r
+ if (++n == 0)\r
+ {\r
+ appender::apply(it, end, wkt, exterior_ring(poly));\r
+ }\r
+ else\r
+ {\r
+ typename ring_type<Polygon>::type ring;\r
+ appender::apply(it, end, wkt, ring);\r
+ traits::push_back\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename traits::interior_mutable_type<Polygon>::type\r
+ >::type\r
+ >::apply(interior_rings(poly), ring);\r
+ }\r
+\r
+ if (it != end && *it == ",")\r
+ {\r
+ // Skip "," after ring is parsed\r
+ ++it;\r
+ }\r
+ }\r
+\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+};\r
+\r
+\r
+inline bool one_of(tokenizer::iterator const& it,\r
+ std::string const& value,\r
+ bool& is_present)\r
+{\r
+ if (boost::iequals(*it, value))\r
+ {\r
+ is_present = true;\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+inline bool one_of(tokenizer::iterator const& it,\r
+ std::string const& value,\r
+ bool& present1,\r
+ bool& present2)\r
+{\r
+ if (boost::iequals(*it, value))\r
+ {\r
+ present1 = true;\r
+ present2 = true;\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+\r
+inline void handle_empty_z_m(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ bool& has_empty,\r
+ bool& has_z,\r
+ bool& has_m)\r
+{\r
+ has_empty = false;\r
+ has_z = false;\r
+ has_m = false;\r
+\r
+ // WKT can optionally have Z and M (measured) values as in\r
+ // POINT ZM (1 1 5 60), POINT M (1 1 80), POINT Z (1 1 5)\r
+ // GGL supports any of them as coordinate values, but is not aware\r
+ // of any Measured value.\r
+ while (it != end\r
+ && (one_of(it, "M", has_m)\r
+ || one_of(it, "Z", has_z)\r
+ || one_of(it, "EMPTY", has_empty)\r
+ || one_of(it, "MZ", has_m, has_z)\r
+ || one_of(it, "ZM", has_z, has_m)\r
+ )\r
+ )\r
+ {\r
+ ++it;\r
+ }\r
+}\r
+\r
+/*!\r
+\brief Internal, starts parsing\r
+\param tokens boost tokens, parsed with separator " " and keeping separator "()"\r
+\param geometry string to compare with first token\r
+*/\r
+template <typename Geometry>\r
+inline bool initialize(tokenizer const& tokens,\r
+ std::string const& geometry_name,\r
+ std::string const& wkt,\r
+ tokenizer::iterator& it,\r
+ tokenizer::iterator& end)\r
+{\r
+ it = tokens.begin();\r
+ end = tokens.end();\r
+ if (it != end && boost::iequals(*it++, geometry_name))\r
+ {\r
+ bool has_empty, has_z, has_m;\r
+\r
+ handle_empty_z_m(it, end, has_empty, has_z, has_m);\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push) \r
+#pragma warning(disable : 4127) \r
+#endif\r
+\r
+ if (has_z && dimension<Geometry>::type::value < 3)\r
+ {\r
+ throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt);\r
+ }\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+ if (has_empty)\r
+ {\r
+ check_end(it, end, wkt);\r
+ return false;\r
+ }\r
+ // M is ignored at all.\r
+\r
+ return true;\r
+ }\r
+ throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt);\r
+}\r
+\r
+\r
+template <typename Geometry, template<typename> class Parser, typename PrefixPolicy>\r
+struct geometry_parser\r
+{\r
+ static inline void apply(std::string const& wkt, Geometry& geometry)\r
+ {\r
+ geometry::clear(geometry);\r
+\r
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));\r
+ tokenizer::iterator it, end;\r
+ if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it, end))\r
+ {\r
+ Parser<Geometry>::apply(it, end, wkt, geometry);\r
+ check_end(it, end, wkt);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiGeometry, template<typename> class Parser, typename PrefixPolicy>\r
+struct multi_parser\r
+{\r
+ static inline void apply(std::string const& wkt, MultiGeometry& geometry)\r
+ {\r
+ traits::clear<MultiGeometry>::apply(geometry);\r
+\r
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));\r
+ tokenizer::iterator it, end;\r
+ if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))\r
+ {\r
+ handle_open_parenthesis(it, end, wkt);\r
+\r
+ // Parse sub-geometries\r
+ while(it != end && *it != ")")\r
+ {\r
+ traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);\r
+ Parser\r
+ <\r
+ typename boost::range_value<MultiGeometry>::type\r
+ >::apply(it, end, wkt, *(boost::end(geometry) - 1));\r
+ if (it != end && *it == ",")\r
+ {\r
+ // Skip "," after multi-element is parsed\r
+ ++it;\r
+ }\r
+ }\r
+\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+\r
+ check_end(it, end, wkt);\r
+ }\r
+};\r
+\r
+template <typename P>\r
+struct noparenthesis_point_parser\r
+{\r
+ static inline void apply(tokenizer::iterator& it,\r
+ tokenizer::iterator const& end,\r
+ std::string const& wkt,\r
+ P& point)\r
+ {\r
+ parsing_assigner<P>::apply(it, end, point, wkt);\r
+ }\r
+};\r
+\r
+template <typename MultiGeometry, typename PrefixPolicy>\r
+struct multi_point_parser\r
+{\r
+ static inline void apply(std::string const& wkt, MultiGeometry& geometry)\r
+ {\r
+ traits::clear<MultiGeometry>::apply(geometry);\r
+\r
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));\r
+ tokenizer::iterator it, end;\r
+\r
+ if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it, end))\r
+ {\r
+ handle_open_parenthesis(it, end, wkt);\r
+\r
+ // If first point definition starts with "(" then parse points as (x y)\r
+ // otherwise as "x y"\r
+ bool using_brackets = (it != end && *it == "(");\r
+\r
+ while(it != end && *it != ")")\r
+ {\r
+ traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);\r
+\r
+ if (using_brackets)\r
+ {\r
+ point_parser\r
+ <\r
+ typename boost::range_value<MultiGeometry>::type\r
+ >::apply(it, end, wkt, *(boost::end(geometry) - 1));\r
+ }\r
+ else\r
+ {\r
+ noparenthesis_point_parser\r
+ <\r
+ typename boost::range_value<MultiGeometry>::type\r
+ >::apply(it, end, wkt, *(boost::end(geometry) - 1));\r
+ }\r
+\r
+ if (it != end && *it == ",")\r
+ {\r
+ // Skip "," after point is parsed\r
+ ++it;\r
+ }\r
+ }\r
+\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+\r
+ check_end(it, end, wkt);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Supports box parsing\r
+\note OGC does not define the box geometry, and WKT does not support boxes.\r
+ However, to be generic GGL supports reading and writing from and to boxes.\r
+ Boxes are outputted as a standard POLYGON. GGL can read boxes from\r
+ a standard POLYGON, from a POLYGON with 2 points of from a BOX\r
+\tparam Box the box\r
+*/\r
+template <typename Box>\r
+struct box_parser\r
+{\r
+ static inline void apply(std::string const& wkt, Box& box)\r
+ {\r
+ bool should_close = false;\r
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));\r
+ tokenizer::iterator it = tokens.begin();\r
+ tokenizer::iterator end = tokens.end();\r
+ if (it != end && boost::iequals(*it, "POLYGON"))\r
+ {\r
+ ++it;\r
+ bool has_empty, has_z, has_m;\r
+ handle_empty_z_m(it, end, has_empty, has_z, has_m);\r
+ if (has_empty)\r
+ {\r
+ assign_zero(box);\r
+ return;\r
+ }\r
+ handle_open_parenthesis(it, end, wkt);\r
+ should_close = true;\r
+ }\r
+ else if (it != end && boost::iequals(*it, "BOX"))\r
+ {\r
+ ++it;\r
+ }\r
+ else\r
+ {\r
+ throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt);\r
+ }\r
+\r
+ typedef typename point_type<Box>::type point_type;\r
+ std::vector<point_type> points;\r
+ container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));\r
+\r
+ if (should_close)\r
+ {\r
+ handle_close_parenthesis(it, end, wkt);\r
+ }\r
+ check_end(it, end, wkt);\r
+\r
+ unsigned int index = 0;\r
+ std::size_t n = boost::size(points);\r
+ if (n == 2)\r
+ {\r
+ index = 1;\r
+ }\r
+ else if (n == 4 || n == 5)\r
+ {\r
+ // In case of 4 or 5 points, we do not check the other ones, just\r
+ // take the opposite corner which is always 2\r
+ index = 2;\r
+ }\r
+ else\r
+ {\r
+ throw read_wkt_exception("Box should have 2,4 or 5 points", wkt);\r
+ }\r
+\r
+ geometry::detail::assign_point_to_index<min_corner>(points.front(), box);\r
+ geometry::detail::assign_point_to_index<max_corner>(points[index], box);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Supports segment parsing\r
+\note OGC does not define the segment, and WKT does not support segmentes.\r
+ However, it is useful to implement it, also for testing purposes\r
+\tparam Segment the segment\r
+*/\r
+template <typename Segment>\r
+struct segment_parser\r
+{\r
+ static inline void apply(std::string const& wkt, Segment& segment)\r
+ {\r
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));\r
+ tokenizer::iterator it = tokens.begin();\r
+ tokenizer::iterator end = tokens.end();\r
+ if (it != end &&\r
+ (boost::iequals(*it, "SEGMENT")\r
+ || boost::iequals(*it, "LINESTRING") ))\r
+ {\r
+ ++it;\r
+ }\r
+ else\r
+ {\r
+ throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt);\r
+ }\r
+\r
+ typedef typename point_type<Segment>::type point_type;\r
+ std::vector<point_type> points;\r
+ container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));\r
+\r
+ check_end(it, end, wkt);\r
+\r
+ if (boost::size(points) == 2)\r
+ {\r
+ geometry::detail::assign_point_to_index<0>(points.front(), segment);\r
+ geometry::detail::assign_point_to_index<1>(points.back(), segment);\r
+ }\r
+ else\r
+ {\r
+ throw read_wkt_exception("Segment should have 2 points", wkt);\r
+ }\r
+\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::wkt\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Tag, typename Geometry>\r
+struct read_wkt {};\r
+\r
+\r
+template <typename Point>\r
+struct read_wkt<point_tag, Point>\r
+ : detail::wkt::geometry_parser\r
+ <\r
+ Point,\r
+ detail::wkt::point_parser,\r
+ detail::wkt::prefix_point\r
+ >\r
+{};\r
+\r
+\r
+template <typename L>\r
+struct read_wkt<linestring_tag, L>\r
+ : detail::wkt::geometry_parser\r
+ <\r
+ L,\r
+ detail::wkt::linestring_parser,\r
+ detail::wkt::prefix_linestring\r
+ >\r
+{};\r
+\r
+template <typename Ring>\r
+struct read_wkt<ring_tag, Ring>\r
+ : detail::wkt::geometry_parser\r
+ <\r
+ Ring,\r
+ detail::wkt::ring_parser,\r
+ detail::wkt::prefix_polygon\r
+ >\r
+{};\r
+\r
+template <typename Geometry>\r
+struct read_wkt<polygon_tag, Geometry>\r
+ : detail::wkt::geometry_parser\r
+ <\r
+ Geometry,\r
+ detail::wkt::polygon_parser,\r
+ detail::wkt::prefix_polygon\r
+ >\r
+{};\r
+\r
+\r
+template <typename MultiGeometry>\r
+struct read_wkt<multi_point_tag, MultiGeometry>\r
+ : detail::wkt::multi_point_parser\r
+ <\r
+ MultiGeometry,\r
+ detail::wkt::prefix_multipoint\r
+ >\r
+{};\r
+\r
+template <typename MultiGeometry>\r
+struct read_wkt<multi_linestring_tag, MultiGeometry>\r
+ : detail::wkt::multi_parser\r
+ <\r
+ MultiGeometry,\r
+ detail::wkt::linestring_parser,\r
+ detail::wkt::prefix_multilinestring\r
+ >\r
+{};\r
+\r
+template <typename MultiGeometry>\r
+struct read_wkt<multi_polygon_tag, MultiGeometry>\r
+ : detail::wkt::multi_parser\r
+ <\r
+ MultiGeometry,\r
+ detail::wkt::polygon_parser,\r
+ detail::wkt::prefix_multipolygon\r
+ >\r
+{};\r
+\r
+\r
+// Box (Non-OGC)\r
+template <typename Box>\r
+struct read_wkt<box_tag, Box>\r
+ : detail::wkt::box_parser<Box>\r
+{};\r
+\r
+// Segment (Non-OGC)\r
+template <typename Segment>\r
+struct read_wkt<segment_tag, Segment>\r
+ : detail::wkt::segment_parser<Segment>\r
+{};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+/*!\r
+\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)\r
+\ingroup wkt\r
+\tparam Geometry \tparam_geometry\r
+\param wkt string containing \ref WKT\r
+\param geometry \param_geometry output geometry\r
+\ingroup wkt\r
+\qbk{[include reference/io/read_wkt.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline void read_wkt(std::string const& wkt, Geometry& geometry)\r
+{\r
+ geometry::concepts::check<Geometry>();\r
+ dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_IO_WKT_READ_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_WKT_STREAM_HPP\r
+#define BOOST_GEOMETRY_IO_WKT_STREAM_HPP\r
+\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+\r
+// This short file contains only one manipulator, streaming as WKT\r
+// Don't include this in any standard-included header file.\r
+\r
+// Don't use namespace boost::geometry, to enable the library to stream custom\r
+// geometries which are living outside the namespace boost::geometry\r
+\r
+// This is currently not documented on purpose: the Doxygen 2 QBK generator\r
+// should be updated w.r.t. << which in the end ruins the DocBook XML\r
+template<typename Char, typename Traits, typename Geometry>\r
+inline std::basic_ostream<Char, Traits>& operator<<\r
+ (\r
+ std::basic_ostream<Char, Traits> &os,\r
+ Geometry const& geom\r
+ )\r
+{\r
+ os << boost::geometry::wkt(geom);\r
+ return os;\r
+}\r
+\r
+#endif // BOOST_GEOMETRY_IO_WKT_STREAM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_WKT_WKT_HPP\r
+#define BOOST_GEOMETRY_IO_WKT_WKT_HPP\r
+\r
+#include <boost/geometry/io/wkt/read.hpp>\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+\r
+// BSG 2011-02-03\r
+// We don't include stream.hpp by default. That tries to stream anything not known\r
+// by default (such as ttmath) and reports errors.\r
+// Users can include stream.hpp themselves (if they want to)\r
+\r
+#endif // BOOST_GEOMETRY_IO_WKT_WKT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP\r
+#define BOOST_GEOMETRY_IO_WKT_WRITE_HPP\r
+\r
+#include <ostream>\r
+#include <string>\r
+\r
+#include <boost/array.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/variant/apply_visitor.hpp>\r
+#include <boost/variant/static_visitor.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/interior_iterator.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+#include <boost/geometry/geometries/ring.hpp>\r
+\r
+#include <boost/geometry/io/wkt/detail/prefix.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4512: 'boost::geometry::wkt_manipulator<Geometry>' : assignment operator could not be generated\r
+#if defined(_MSC_VER)\r
+#pragma warning(push) \r
+#pragma warning(disable : 4512) \r
+#endif\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace wkt\r
+{\r
+\r
+template <typename P, int I, int Count>\r
+struct stream_coordinate\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p)\r
+ {\r
+ os << (I > 0 ? " " : "") << get<I>(p);\r
+ stream_coordinate<P, I + 1, Count>::apply(os, p);\r
+ }\r
+};\r
+\r
+template <typename P, int Count>\r
+struct stream_coordinate<P, Count, Count>\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>&, P const&)\r
+ {}\r
+};\r
+\r
+struct prefix_linestring_par\r
+{\r
+ static inline const char* apply() { return "LINESTRING("; }\r
+};\r
+\r
+struct prefix_ring_par_par\r
+{\r
+ // Note, double parentheses are intentional, indicating WKT ring begin/end\r
+ static inline const char* apply() { return "POLYGON(("; }\r
+};\r
+\r
+struct opening_parenthesis\r
+{\r
+ static inline const char* apply() { return "("; }\r
+};\r
+\r
+struct closing_parenthesis\r
+{\r
+ static inline const char* apply() { return ")"; }\r
+};\r
+\r
+struct double_closing_parenthesis\r
+{\r
+ static inline const char* apply() { return "))"; }\r
+};\r
+\r
+/*!\r
+\brief Stream points as \ref WKT\r
+*/\r
+template <typename Point, typename Policy>\r
+struct wkt_point\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p)\r
+ {\r
+ os << Policy::apply() << "(";\r
+ stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p);\r
+ os << ")";\r
+ }\r
+};\r
+\r
+/*!\r
+\brief Stream ranges as WKT\r
+\note policy is used to stream prefix/postfix, enabling derived classes to override this\r
+*/\r
+template <typename Range, typename PrefixPolicy, typename SuffixPolicy>\r
+struct wkt_range\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Range const& range, bool force_closed)\r
+ {\r
+ typedef typename boost::range_iterator<Range const>::type iterator_type;\r
+\r
+ typedef stream_coordinate\r
+ <\r
+ point_type, 0, dimension<point_type>::type::value\r
+ > stream_type;\r
+\r
+ bool first = true;\r
+\r
+ os << PrefixPolicy::apply();\r
+\r
+ // TODO: check EMPTY here\r
+\r
+ iterator_type begin = boost::begin(range);\r
+ iterator_type end = boost::end(range);\r
+ for (iterator_type it = begin; it != end; ++it)\r
+ {\r
+ os << (first ? "" : ",");\r
+ stream_type::apply(os, *it);\r
+ first = false;\r
+ }\r
+\r
+ // optionally, close range to ring by repeating the first point\r
+ if (force_closed \r
+ && boost::size(range) > 1\r
+ && detail::disjoint::disjoint_point_point(*begin, *(end - 1)))\r
+ {\r
+ os << ",";\r
+ stream_type::apply(os, *begin);\r
+ }\r
+\r
+ os << SuffixPolicy::apply();\r
+ }\r
+\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Range const& range)\r
+ {\r
+ apply(os, range, false);\r
+ }\r
+\r
+private:\r
+ typedef typename boost::range_value<Range>::type point_type;\r
+};\r
+\r
+/*!\r
+\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)\r
+\note Used in polygon, all multi-geometries\r
+*/\r
+template <typename Range>\r
+struct wkt_sequence\r
+ : wkt_range\r
+ <\r
+ Range,\r
+ opening_parenthesis,\r
+ closing_parenthesis\r
+ >\r
+{};\r
+\r
+template <typename Polygon, typename PrefixPolicy>\r
+struct wkt_poly\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Polygon const& poly)\r
+ {\r
+ typedef typename ring_type<Polygon const>::type ring;\r
+ bool const force_closed = true;\r
+\r
+ os << PrefixPolicy::apply();\r
+ // TODO: check EMPTY here\r
+ os << "(";\r
+ wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closed);\r
+\r
+ typename interior_return_type<Polygon const>::type\r
+ rings = interior_rings(poly);\r
+ for (typename detail::interior_iterator<Polygon const>::type\r
+ it = boost::begin(rings); it != boost::end(rings); ++it)\r
+ {\r
+ os << ",";\r
+ wkt_sequence<ring>::apply(os, *it, force_closed);\r
+ }\r
+ os << ")";\r
+ }\r
+};\r
+\r
+template <typename Multi, typename StreamPolicy, typename PrefixPolicy>\r
+struct wkt_multi\r
+{\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Multi const& geometry)\r
+ {\r
+ os << PrefixPolicy::apply();\r
+ // TODO: check EMPTY here\r
+ os << "(";\r
+\r
+ for (typename boost::range_iterator<Multi const>::type\r
+ it = boost::begin(geometry);\r
+ it != boost::end(geometry);\r
+ ++it)\r
+ {\r
+ if (it != boost::begin(geometry))\r
+ {\r
+ os << ",";\r
+ }\r
+ StreamPolicy::apply(os, *it);\r
+ }\r
+\r
+ os << ")";\r
+ }\r
+};\r
+\r
+template <typename Box>\r
+struct wkt_box\r
+{\r
+ typedef typename point_type<Box>::type point_type;\r
+\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Box const& box)\r
+ {\r
+ // Convert to ring, then stream\r
+ typedef model::ring<point_type> ring_type;\r
+ ring_type ring;\r
+ geometry::convert(box, ring);\r
+ os << "POLYGON(";\r
+ wkt_sequence<ring_type>::apply(os, ring);\r
+ os << ")";\r
+ }\r
+\r
+ private:\r
+\r
+ inline wkt_box()\r
+ {\r
+ // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!\r
+ //assert_dimension<B, 2>();\r
+ }\r
+};\r
+\r
+\r
+template <typename Segment>\r
+struct wkt_segment\r
+{\r
+ typedef typename point_type<Segment>::type point_type;\r
+\r
+ template <typename Char, typename Traits>\r
+ static inline void apply(std::basic_ostream<Char, Traits>& os,\r
+ Segment const& segment)\r
+ {\r
+ // Convert to two points, then stream\r
+ typedef boost::array<point_type, 2> sequence;\r
+\r
+ sequence points;\r
+ geometry::detail::assign_point_from_index<0>(segment, points[0]);\r
+ geometry::detail::assign_point_from_index<1>(segment, points[1]);\r
+\r
+ // In Boost.Geometry a segment is represented\r
+ // in WKT-format like (for 2D): LINESTRING(x y,x y)\r
+ os << "LINESTRING";\r
+ wkt_sequence<sequence>::apply(os, points);\r
+ }\r
+\r
+ private:\r
+\r
+ inline wkt_segment()\r
+ {}\r
+};\r
+\r
+}} // namespace detail::wkt\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct wkt: not_implemented<Tag>\r
+{};\r
+\r
+template <typename Point>\r
+struct wkt<Point, point_tag>\r
+ : detail::wkt::wkt_point\r
+ <\r
+ Point,\r
+ detail::wkt::prefix_point\r
+ >\r
+{};\r
+\r
+template <typename Linestring>\r
+struct wkt<Linestring, linestring_tag>\r
+ : detail::wkt::wkt_range\r
+ <\r
+ Linestring,\r
+ detail::wkt::prefix_linestring_par,\r
+ detail::wkt::closing_parenthesis\r
+ >\r
+{};\r
+\r
+/*!\r
+\brief Specialization to stream a box as WKT\r
+\details A "box" does not exist in WKT.\r
+It is therefore streamed as a polygon\r
+*/\r
+template <typename Box>\r
+struct wkt<Box, box_tag>\r
+ : detail::wkt::wkt_box<Box>\r
+{};\r
+\r
+template <typename Segment>\r
+struct wkt<Segment, segment_tag>\r
+ : detail::wkt::wkt_segment<Segment>\r
+{};\r
+\r
+/*!\r
+\brief Specialization to stream a ring as WKT\r
+\details A ring or "linear_ring" does not exist in WKT.\r
+A ring is equivalent to a polygon without inner rings\r
+It is therefore streamed as a polygon\r
+*/\r
+template <typename Ring>\r
+struct wkt<Ring, ring_tag>\r
+ : detail::wkt::wkt_range\r
+ <\r
+ Ring,\r
+ detail::wkt::prefix_ring_par_par,\r
+ detail::wkt::double_closing_parenthesis\r
+ >\r
+{};\r
+\r
+/*!\r
+\brief Specialization to stream polygon as WKT\r
+*/\r
+template <typename Polygon>\r
+struct wkt<Polygon, polygon_tag>\r
+ : detail::wkt::wkt_poly\r
+ <\r
+ Polygon,\r
+ detail::wkt::prefix_polygon\r
+ >\r
+{};\r
+\r
+template <typename Multi>\r
+struct wkt<Multi, multi_point_tag>\r
+ : detail::wkt::wkt_multi\r
+ <\r
+ Multi,\r
+ detail::wkt::wkt_point\r
+ <\r
+ typename boost::range_value<Multi>::type,\r
+ detail::wkt::prefix_null\r
+ >,\r
+ detail::wkt::prefix_multipoint\r
+ >\r
+{};\r
+\r
+template <typename Multi>\r
+struct wkt<Multi, multi_linestring_tag>\r
+ : detail::wkt::wkt_multi\r
+ <\r
+ Multi,\r
+ detail::wkt::wkt_sequence\r
+ <\r
+ typename boost::range_value<Multi>::type\r
+ >,\r
+ detail::wkt::prefix_multilinestring\r
+ >\r
+{};\r
+\r
+template <typename Multi>\r
+struct wkt<Multi, multi_polygon_tag>\r
+ : detail::wkt::wkt_multi\r
+ <\r
+ Multi,\r
+ detail::wkt::wkt_poly\r
+ <\r
+ typename boost::range_value<Multi>::type,\r
+ detail::wkt::prefix_null\r
+ >,\r
+ detail::wkt::prefix_multipolygon\r
+ >\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct devarianted_wkt\r
+{\r
+ template <typename OutputStream>\r
+ static inline void apply(OutputStream& os, Geometry const& geometry)\r
+ {\r
+ wkt<Geometry>::apply(os, geometry);\r
+ }\r
+};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ template <typename OutputStream>\r
+ struct visitor: static_visitor<void>\r
+ {\r
+ OutputStream& m_os;\r
+\r
+ visitor(OutputStream& os)\r
+ : m_os(os)\r
+ {}\r
+\r
+ template <typename Geometry>\r
+ inline void operator()(Geometry const& geometry) const\r
+ {\r
+ devarianted_wkt<Geometry>::apply(m_os, geometry);\r
+ }\r
+ };\r
+\r
+ template <typename OutputStream>\r
+ static inline void apply(\r
+ OutputStream& os,\r
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry\r
+ )\r
+ {\r
+ boost::apply_visitor(visitor<OutputStream>(os), geometry);\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+/*!\r
+\brief Generic geometry template manipulator class, takes corresponding output class from traits class\r
+\ingroup wkt\r
+\details Stream manipulator, streams geometry classes as \ref WKT streams\r
+\par Example:\r
+Small example showing how to use the wkt class\r
+\dontinclude doxygen_1.cpp\r
+\skip example_as_wkt_point\r
+\line {\r
+\until }\r
+*/\r
+template <typename Geometry>\r
+class wkt_manipulator\r
+{\r
+public:\r
+\r
+ inline wkt_manipulator(Geometry const& g)\r
+ : m_geometry(g)\r
+ {}\r
+\r
+ template <typename Char, typename Traits>\r
+ inline friend std::basic_ostream<Char, Traits>& operator<<(\r
+ std::basic_ostream<Char, Traits>& os,\r
+ wkt_manipulator const& m)\r
+ {\r
+ dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry);\r
+ os.flush();\r
+ return os;\r
+ }\r
+\r
+private:\r
+ Geometry const& m_geometry;\r
+};\r
+\r
+/*!\r
+\brief Main WKT-streaming function\r
+\tparam Geometry \tparam_geometry\r
+\param geometry \param_geometry\r
+\ingroup wkt\r
+\qbk{[include reference/io/wkt.qbk]}\r
+*/\r
+template <typename Geometry>\r
+inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)\r
+{\r
+ concepts::check<Geometry const>();\r
+\r
+ return wkt_manipulator<Geometry>(geometry);\r
+}\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop) \r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_BASE_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_BASE_HPP\r
+\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_adaptor.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+#include <boost/mpl/if.hpp>\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace boost { namespace geometry { namespace detail { namespace iterators\r
+{\r
+\r
+template\r
+<\r
+ typename DerivedClass,\r
+ typename Iterator,\r
+ typename TraversalFlag = boost::bidirectional_traversal_tag\r
+>\r
+struct iterator_base\r
+ : public boost::iterator_adaptor\r
+ <\r
+ DerivedClass,\r
+ Iterator,\r
+ boost::use_default,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_convertible\r
+ <\r
+ typename boost::iterator_traversal<Iterator>::type,\r
+ boost::random_access_traversal_tag\r
+ >,\r
+ TraversalFlag,\r
+ boost::use_default\r
+ >::type\r
+ >\r
+{\r
+ // Define operator cast to Iterator to be able to write things like Iterator it = myit++\r
+ inline operator Iterator() const\r
+ {\r
+ return this->base();\r
+ }\r
+\r
+ /*inline bool operator==(Iterator const& other) const\r
+ {\r
+ return this->base() == other;\r
+ }\r
+ inline bool operator!=(Iterator const& other) const\r
+ {\r
+ return ! operator==(other);\r
+ }*/\r
+};\r
+\r
+}}}} // namespace boost::geometry::detail::iterators\r
+#endif\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_BASE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Iterator which iterates through a range, but adds first element at end of the range\r
+\tparam Range range on which this class is based on\r
+\ingroup iterators\r
+\note It's const iterator treating the Range as one containing non-mutable elements.\r
+ For both "closing_iterator<Range> and "closing_iterator<Range const>\r
+ const reference is always returned when dereferenced.\r
+\note This class is normally used from "closeable_view" if Close==true\r
+*/\r
+template <typename Range>\r
+struct closing_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ closing_iterator<Range>,\r
+ typename boost::range_value<Range>::type const,\r
+ boost::random_access_traversal_tag\r
+ >\r
+{\r
+ typedef typename boost::range_difference<Range>::type difference_type;\r
+\r
+ /// Constructor including the range it is based on\r
+ explicit inline closing_iterator(Range& range)\r
+ : m_range(&range)\r
+ , m_iterator(boost::begin(range))\r
+ , m_end(boost::end(range))\r
+ , m_size(static_cast<difference_type>(boost::size(range)))\r
+ , m_index(0)\r
+ {}\r
+\r
+ /// Constructor to indicate the end of a range\r
+ explicit inline closing_iterator(Range& range, bool)\r
+ : m_range(&range)\r
+ , m_iterator(boost::end(range))\r
+ , m_end(boost::end(range))\r
+ , m_size(static_cast<difference_type>(boost::size(range)))\r
+ , m_index((m_size == 0) ? 0 : m_size + 1)\r
+ {}\r
+\r
+ /// Default constructor\r
+ explicit inline closing_iterator()\r
+ : m_range(NULL)\r
+ , m_size(0)\r
+ , m_index(0)\r
+ {}\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ inline typename boost::range_value<Range>::type const& dereference() const\r
+ {\r
+ return *m_iterator;\r
+ }\r
+\r
+ inline difference_type distance_to(closing_iterator<Range> const& other) const\r
+ {\r
+ return other.m_index - this->m_index;\r
+ }\r
+\r
+ inline bool equal(closing_iterator<Range> const& other) const\r
+ {\r
+ return this->m_range == other.m_range\r
+ && this->m_index == other.m_index;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ if (++m_index < m_size)\r
+ {\r
+ ++m_iterator;\r
+ }\r
+ else\r
+ {\r
+ update_iterator();\r
+ }\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ if (m_index-- < m_size)\r
+ {\r
+ --m_iterator;\r
+ }\r
+ else\r
+ {\r
+ update_iterator();\r
+ }\r
+ }\r
+\r
+ inline void advance(difference_type n)\r
+ {\r
+ if (m_index < m_size && m_index + n < m_size)\r
+ {\r
+ m_index += n;\r
+ m_iterator += n;\r
+ }\r
+ else\r
+ {\r
+ m_index += n;\r
+ update_iterator();\r
+ }\r
+ }\r
+\r
+ inline void update_iterator()\r
+ {\r
+ this->m_iterator = m_index <= m_size\r
+ ? boost::begin(*m_range) + (m_index % m_size)\r
+ : boost::end(*m_range)\r
+ ;\r
+ }\r
+\r
+ Range* m_range;\r
+ typename boost::range_iterator<Range>::type m_iterator;\r
+ typename boost::range_iterator<Range>::type m_end;\r
+ difference_type m_size;\r
+ difference_type m_index;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+\r
+template\r
+<\r
+ typename Iterator1,\r
+ typename Iterator2,\r
+ typename Value,\r
+ typename Reference = Value&\r
+>\r
+class concatenate_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ concatenate_iterator<Iterator1, Iterator2, Value, Reference>,\r
+ Value,\r
+ boost::bidirectional_traversal_tag,\r
+ Reference\r
+ >\r
+{\r
+private:\r
+ Iterator1 m_it1, m_end1;\r
+ Iterator2 m_begin2, m_it2;\r
+\r
+public:\r
+ typedef Iterator1 first_iterator_type;\r
+ typedef Iterator2 second_iterator_type;\r
+\r
+ // default constructor\r
+ concatenate_iterator() {}\r
+\r
+ // for begin\r
+ concatenate_iterator(Iterator1 it1, Iterator1 end1,\r
+ Iterator2 begin2, Iterator2 it2)\r
+ : m_it1(it1), m_end1(end1), m_begin2(begin2), m_it2(it2)\r
+ {}\r
+\r
+ // for end\r
+ concatenate_iterator(Iterator1 end1, Iterator2 begin2, Iterator2 end2)\r
+ : m_it1(end1), m_end1(end1), m_begin2(begin2), m_it2(end2)\r
+ {}\r
+\r
+ template\r
+ <\r
+ typename OtherIt1,\r
+ typename OtherIt2,\r
+ typename OtherValue,\r
+ typename OtherReference\r
+ >\r
+ concatenate_iterator(concatenate_iterator\r
+ <\r
+ OtherIt1,\r
+ OtherIt2,\r
+ OtherValue,\r
+ OtherReference\r
+ > const& other)\r
+ : m_it1(other.m_it1)\r
+ , m_end1(other.m_end1)\r
+ , m_begin2(other.m_begin2)\r
+ , m_it2(other.m_it2)\r
+ {\r
+ static const bool are_conv\r
+ = boost::is_convertible<OtherIt1, Iterator1>::value\r
+ && boost::is_convertible<OtherIt2, Iterator2>::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((are_conv),\r
+ NOT_CONVERTIBLE,\r
+ (types<OtherIt1, OtherIt2>));\r
+ }\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ template <typename It1, typename It2, typename V, typename R>\r
+ friend class concatenate_iterator;\r
+\r
+ inline Reference dereference() const\r
+ {\r
+ if ( m_it1 == m_end1 )\r
+ {\r
+ return *m_it2;\r
+ }\r
+ return *m_it1;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OtherIt1,\r
+ typename OtherIt2,\r
+ typename OtherValue,\r
+ typename OtherReference\r
+ >\r
+ inline bool equal(concatenate_iterator\r
+ <\r
+ OtherIt1,\r
+ OtherIt2,\r
+ OtherValue,\r
+ OtherReference\r
+ > const& other) const\r
+ {\r
+ return m_it1 == other.m_it1 && m_it2 == other.m_it2;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ if ( m_it1 == m_end1 )\r
+ {\r
+ ++m_it2;\r
+ }\r
+ else\r
+ {\r
+ ++m_it1;\r
+ }\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ if ( m_it2 == m_begin2 )\r
+ {\r
+ --m_it1;\r
+ }\r
+ else\r
+ {\r
+ --m_it2;\r
+ }\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_CONCATENATE_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_INNER_RANGE_TYPE_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_INNER_RANGE_TYPE_HPP\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/mpl/if.hpp>\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace point_iterator\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Geometry, \r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct inner_range_type\r
+{\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ !boost::is_const<Geometry>::type::value,\r
+ typename boost::range_value<Geometry>::type,\r
+ typename boost::range_value<Geometry>::type const\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct inner_range_type<Polygon, polygon_tag>\r
+{\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ !boost::is_const<Polygon>::type::value,\r
+ typename geometry::ring_type<Polygon>::type,\r
+ typename geometry::ring_type<Polygon>::type const\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace detail::point_iterator\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_INNER_RANGE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_ITERATOR_TYPE_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_ITERATOR_TYPE_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/iterators/flatten_iterator.hpp>\r
+#include <boost/geometry/iterators/concatenate_iterator.hpp>\r
+\r
+#include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>\r
+#include <boost/geometry/iterators/detail/point_iterator/value_type.hpp>\r
+\r
+#include <boost/geometry/iterators/dispatch/point_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace point_iterator\r
+{\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct iterator_type\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+\r
+\r
+template <typename Linestring>\r
+struct iterator_type<Linestring, linestring_tag>\r
+{\r
+ typedef typename boost::range_iterator<Linestring>::type type;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct iterator_type<Ring, ring_tag>\r
+{\r
+ typedef typename boost::range_iterator<Ring>::type type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+class iterator_type<Polygon, polygon_tag>\r
+{\r
+private:\r
+ typedef typename inner_range_type<Polygon>::type inner_range;\r
+\r
+public:\r
+ typedef concatenate_iterator\r
+ <\r
+ typename boost::range_iterator<inner_range>::type,\r
+ flatten_iterator\r
+ <\r
+ typename boost::range_iterator\r
+ <\r
+ typename geometry::interior_type<Polygon>::type\r
+ >::type,\r
+ typename iterator_type<inner_range>::type,\r
+ typename value_type<Polygon>::type,\r
+ dispatch::points_begin<inner_range>,\r
+ dispatch::points_end<inner_range>\r
+ >,\r
+ typename value_type<Polygon>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename MultiPoint>\r
+struct iterator_type<MultiPoint, multi_point_tag>\r
+{\r
+ typedef typename boost::range_iterator<MultiPoint>::type type;\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+class iterator_type<MultiLinestring, multi_linestring_tag>\r
+{\r
+private:\r
+ typedef typename inner_range_type<MultiLinestring>::type inner_range;\r
+\r
+public:\r
+ typedef flatten_iterator\r
+ <\r
+ typename boost::range_iterator<MultiLinestring>::type,\r
+ typename iterator_type<inner_range>::type,\r
+ typename value_type<MultiLinestring>::type,\r
+ dispatch::points_begin<inner_range>,\r
+ dispatch::points_end<inner_range>\r
+ > type;\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+class iterator_type<MultiPolygon, multi_polygon_tag>\r
+{\r
+private:\r
+ typedef typename inner_range_type<MultiPolygon>::type inner_range;\r
+\r
+public:\r
+ typedef flatten_iterator\r
+ <\r
+ typename boost::range_iterator<MultiPolygon>::type,\r
+ typename iterator_type<inner_range>::type,\r
+ typename value_type<MultiPolygon>::type,\r
+ dispatch::points_begin<inner_range>,\r
+ dispatch::points_end<inner_range>\r
+ > type;\r
+};\r
+\r
+\r
+}} // namespace detail::point_iterator\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_ITERATOR_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_VALUE_TYPE_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_VALUE_TYPE_HPP\r
+\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/mpl/if.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace point_iterator\r
+{\r
+\r
+\r
+template <typename Geometry>\r
+struct value_type\r
+{\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ !boost::is_const<Geometry>::type::value,\r
+ typename geometry::point_type<Geometry>::type,\r
+ typename geometry::point_type<Geometry>::type const\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace detail::point_iterator\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DETAIL_POINT_ITERATOR_VALUE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_ITERATOR_TYPE_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_ITERATOR_TYPE_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/interior_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+#include <boost/geometry/iterators/concatenate_iterator.hpp>\r
+#include <boost/geometry/iterators/flatten_iterator.hpp>\r
+#include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>\r
+\r
+#include <boost/geometry/iterators/detail/segment_iterator/range_segment_iterator.hpp>\r
+#include <boost/geometry/iterators/detail/segment_iterator/value_type.hpp>\r
+\r
+#include <boost/geometry/iterators/dispatch/segment_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace segment_iterator\r
+{\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct iterator_type\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+template <typename Linestring>\r
+struct iterator_type<Linestring, linestring_tag>\r
+{\r
+ typedef range_segment_iterator\r
+ <\r
+ Linestring, typename value_type<Linestring>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct iterator_type<Ring, ring_tag>\r
+{\r
+ typedef range_segment_iterator\r
+ <\r
+ Ring, typename value_type<Ring>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+class iterator_type<Polygon, polygon_tag>\r
+{\r
+private:\r
+ typedef typename detail::point_iterator::inner_range_type\r
+ <\r
+ Polygon\r
+ >::type inner_range;\r
+\r
+public:\r
+ typedef concatenate_iterator\r
+ <\r
+ range_segment_iterator\r
+ <\r
+ inner_range,\r
+ typename value_type<Polygon>::type\r
+ >,\r
+ flatten_iterator\r
+ <\r
+ typename boost::range_iterator\r
+ <\r
+ typename geometry::interior_type<Polygon>::type\r
+ >::type,\r
+ typename iterator_type<inner_range>::type,\r
+ typename value_type<Polygon>::type,\r
+ dispatch::segments_begin<inner_range>,\r
+ dispatch::segments_end<inner_range>,\r
+ typename value_type<Polygon>::type\r
+ >,\r
+ typename value_type<Polygon>::type,\r
+ typename value_type<Polygon>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+class iterator_type<MultiLinestring, multi_linestring_tag>\r
+{\r
+private:\r
+ typedef typename detail::point_iterator::inner_range_type\r
+ <\r
+ MultiLinestring\r
+ >::type inner_range;\r
+\r
+public:\r
+ typedef flatten_iterator\r
+ <\r
+ typename boost::range_iterator<MultiLinestring>::type,\r
+ typename iterator_type<inner_range>::type,\r
+ typename value_type<MultiLinestring>::type,\r
+ dispatch::segments_begin<inner_range>,\r
+ dispatch::segments_end<inner_range>,\r
+ typename value_type<MultiLinestring>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+class iterator_type<MultiPolygon, multi_polygon_tag>\r
+{\r
+private:\r
+ typedef typename detail::point_iterator::inner_range_type\r
+ <\r
+ MultiPolygon\r
+ >::type inner_range;\r
+public:\r
+ typedef flatten_iterator\r
+ <\r
+ typename boost::range_iterator<MultiPolygon>::type,\r
+ typename iterator_type<inner_range>::type,\r
+ typename value_type<MultiPolygon>::type,\r
+ dispatch::segments_begin<inner_range>,\r
+ dispatch::segments_end<inner_range>,\r
+ typename value_type<MultiPolygon>::type\r
+ > type;\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::segment_iterator\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_ITERATOR_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_RANGE_SEGMENT_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_RANGE_SEGMENT_ITERATOR_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/iterators/closing_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace segment_iterator\r
+{\r
+\r
+\r
+template <typename Range, closure_selector Closure = closure<Range>::value>\r
+struct range_iterator_type\r
+{\r
+ typedef typename boost::range_iterator<Range>::type type;\r
+};\r
+\r
+template <typename Range>\r
+struct range_iterator_type<Range, open>\r
+{\r
+ typedef closing_iterator<Range> type;\r
+};\r
+\r
+\r
+\r
+template <typename Range, closure_selector Closure = closure<Range>::value>\r
+struct range_iterator_begin\r
+{\r
+ static inline typename range_iterator_type<Range, Closure>::type\r
+ apply(Range& range)\r
+ {\r
+ return boost::begin(range);\r
+ }\r
+};\r
+\r
+template <typename Range>\r
+struct range_iterator_begin<Range, open>\r
+{\r
+ static inline typename range_iterator_type<Range, open>::type\r
+ apply(Range& range)\r
+ {\r
+ return closing_iterator<Range>(range);\r
+ }\r
+};\r
+\r
+\r
+\r
+template <typename Range, closure_selector Closure = closure<Range>::value>\r
+struct range_iterator_end\r
+{\r
+ static inline typename range_iterator_type<Range, Closure>::type\r
+ apply(Range& range)\r
+ {\r
+ return boost::end(range);\r
+ }\r
+};\r
+\r
+template <typename Range>\r
+struct range_iterator_end<Range, open>\r
+{\r
+ static inline typename range_iterator_type<Range, open>::type\r
+ apply(Range& range)\r
+ {\r
+ return closing_iterator<Range>(range, true);\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+template <typename Range, typename Value, typename Reference = Value>\r
+class range_segment_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ range_segment_iterator<Range, Value, Reference>,\r
+ Value,\r
+ boost::bidirectional_traversal_tag,\r
+ Reference\r
+ >\r
+{\r
+ static inline bool has_less_than_two_elements(Range const& r)\r
+ {\r
+ return boost::size(r) < ((closure<Range>::value == open) ? 1u : 2u);\r
+ }\r
+\r
+public:\r
+ typedef typename range_iterator_type<Range>::type iterator_type;\r
+\r
+ // default constructor\r
+ range_segment_iterator()\r
+ : m_it(), m_has_less_than_two_elements(false)\r
+ {}\r
+\r
+ // for begin\r
+ range_segment_iterator(Range& r)\r
+ : m_it(range_iterator_begin<Range>::apply(r))\r
+ , m_has_less_than_two_elements(has_less_than_two_elements(r))\r
+ {}\r
+\r
+ // for end\r
+ range_segment_iterator(Range& r, bool)\r
+ : m_it(range_iterator_end<Range>::apply(r))\r
+ , m_has_less_than_two_elements(has_less_than_two_elements(r))\r
+ {\r
+ if (! m_has_less_than_two_elements)\r
+ {\r
+ // the range consists of at least two items\r
+ --m_it;\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OtherRange,\r
+ typename OtherValue,\r
+ typename OtherReference\r
+ >\r
+ range_segment_iterator(range_segment_iterator\r
+ <\r
+ OtherRange,\r
+ OtherValue,\r
+ OtherReference\r
+ > const& other)\r
+ : m_it(other.m_it)\r
+ {\r
+ typedef typename range_segment_iterator\r
+ <\r
+ OtherRange, OtherValue, OtherReference\r
+ >::iterator_type other_iterator_type;\r
+\r
+ static const bool are_conv\r
+ = boost::is_convertible<other_iterator_type, iterator_type>::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((are_conv), NOT_CONVERTIBLE, (types<OtherRange>));\r
+ }\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ template <typename Rng, typename V, typename R>\r
+ friend class range_segment_iterator;\r
+\r
+ inline Reference dereference() const\r
+ {\r
+ if (m_has_less_than_two_elements)\r
+ {\r
+ return Reference(*m_it, *m_it);\r
+ }\r
+\r
+ iterator_type next(m_it);\r
+ ++next;\r
+ return Reference(*m_it, *next);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OtherRange,\r
+ typename OtherValue,\r
+ typename OtherReference\r
+ >\r
+ inline bool equal(range_segment_iterator\r
+ <\r
+ OtherRange,\r
+ OtherValue,\r
+ OtherReference\r
+ > const& other) const\r
+ {\r
+ return m_it == other.m_it;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ ++m_it;\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ --m_it;\r
+ }\r
+\r
+private:\r
+ iterator_type m_it;\r
+ bool m_has_less_than_two_elements;\r
+};\r
+\r
+\r
+}} // namespace detail::segment_iterator\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_RANGE_SEGMENT_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_VALUE_TYPE_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_VALUE_TYPE_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_reference.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+#include <boost/geometry/util/bare_type.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+#include <boost/geometry/geometries/pointing_segment.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace segment_iterator\r
+{\r
+\r
+template <typename Geometry>\r
+struct value_type\r
+{\r
+ typedef typename std::iterator_traits\r
+ <\r
+ geometry::point_iterator<Geometry>\r
+ >::reference point_iterator_reference_type;\r
+\r
+ typedef typename detail::point_iterator::value_type\r
+ <\r
+ Geometry\r
+ >::type point_iterator_value_type;\r
+\r
+ // If the reference type of the point iterator is not really a\r
+ // reference, then dereferencing a point iterator would create\r
+ // a temporary object.\r
+ // In this case using a pointing_segment to represent the\r
+ // dereferenced value of the segment iterator cannot be used, as\r
+ // it would store pointers to temporary objects. Instead we use a\r
+ // segment, which does a full copy of the temporary objects\r
+ // returned by the point iterator.\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_reference<point_iterator_reference_type>,\r
+ geometry::model::pointing_segment<point_iterator_value_type>,\r
+ geometry::model::segment\r
+ <\r
+ typename geometry::util::bare_type\r
+ <\r
+ point_iterator_value_type\r
+ >::type\r
+ >\r
+ >::type type;\r
+};\r
+\r
+}} // namespace detail::segment_iterator\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DETAIL_SEGMENT_ITERATOR_VALUE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// dispatch for points_begin\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct points_begin\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+\r
+// dispatch for points_end\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct points_end\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_POINT_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_DISPATCH_SEGMENT_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_DISPATCH_SEGMENT_ITERATOR_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// dispatch for segments_begin\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct segments_begin\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+\r
+// dispatch for segments_end\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct segments_end\r
+ : not_implemented<Geometry>\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_DISPATCH_SEGMENT_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_adaptor.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+\r
+#include <boost/geometry/iterators/base.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+ \brief Iterator which ever circles through a range\r
+ \tparam Iterator iterator on which this class is based on\r
+ \ingroup iterators\r
+ \details If the iterator arrives at range.end() it restarts from the\r
+ beginning. So it has to be stopped in another way.\r
+ Don't call for(....; it++) because it will turn in an endless loop\r
+ \note Name inspired on David Bowie's\r
+ "Chant Of The Ever Circling Skeletal Family"\r
+*/\r
+template <typename Iterator>\r
+struct ever_circling_iterator :\r
+ public detail::iterators::iterator_base\r
+ <\r
+ ever_circling_iterator<Iterator>,\r
+ Iterator\r
+ >\r
+{\r
+ friend class boost::iterator_core_access;\r
+\r
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end,\r
+ bool skip_first = false)\r
+ : m_begin(begin)\r
+ , m_end(end)\r
+ , m_skip_first(skip_first)\r
+ {\r
+ this->base_reference() = begin;\r
+ }\r
+\r
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,\r
+ bool skip_first = false)\r
+ : m_begin(begin)\r
+ , m_end(end)\r
+ , m_skip_first(skip_first)\r
+ {\r
+ this->base_reference() = start;\r
+ }\r
+\r
+ /// Navigate to a certain position, should be in [start .. end], if at end\r
+ /// it will circle again.\r
+ inline void moveto(Iterator it)\r
+ {\r
+ this->base_reference() = it;\r
+ check_end();\r
+ }\r
+\r
+private:\r
+\r
+ inline void increment(bool possibly_skip = true)\r
+ {\r
+ (this->base_reference())++;\r
+ check_end(possibly_skip);\r
+ }\r
+\r
+ inline void check_end(bool possibly_skip = true)\r
+ {\r
+ if (this->base() == this->m_end)\r
+ {\r
+ this->base_reference() = this->m_begin;\r
+ if (m_skip_first && possibly_skip)\r
+ {\r
+ increment(false);\r
+ }\r
+ }\r
+ }\r
+\r
+ Iterator m_begin;\r
+ Iterator m_end;\r
+ bool m_skip_first;\r
+};\r
+\r
+template <typename Range>\r
+struct ever_circling_range_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ ever_circling_range_iterator<Range>,\r
+ typename boost::range_value<Range>::type const,\r
+ boost::random_access_traversal_tag\r
+ >\r
+{\r
+ /// Constructor including the range it is based on\r
+ explicit inline ever_circling_range_iterator(Range& range)\r
+ : m_range(&range)\r
+ , m_iterator(boost::begin(range))\r
+ , m_size(boost::size(range))\r
+ , m_index(0)\r
+ {}\r
+\r
+ /// Default constructor\r
+ explicit inline ever_circling_range_iterator()\r
+ : m_range(NULL)\r
+ , m_size(0)\r
+ , m_index(0)\r
+ {}\r
+\r
+ typedef std::ptrdiff_t difference_type;\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ inline typename boost::range_value<Range>::type const& dereference() const\r
+ {\r
+ return *m_iterator;\r
+ }\r
+\r
+ inline difference_type distance_to(ever_circling_range_iterator<Range> const& other) const\r
+ {\r
+ return other.m_index - this->m_index;\r
+ }\r
+\r
+ inline bool equal(ever_circling_range_iterator<Range> const& other) const\r
+ {\r
+ return this->m_range == other.m_range\r
+ && this->m_index == other.m_index;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ ++m_index;\r
+ if (m_index >= 0 && m_index < m_size)\r
+ {\r
+ ++m_iterator;\r
+ }\r
+ else\r
+ {\r
+ update_iterator();\r
+ }\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ --m_index;\r
+ if (m_index >= 0 && m_index < m_size)\r
+ {\r
+ --m_iterator;\r
+ }\r
+ else\r
+ {\r
+ update_iterator();\r
+ }\r
+ }\r
+\r
+ inline void advance(difference_type n)\r
+ {\r
+ if (m_index >= 0 && m_index < m_size\r
+ && m_index + n >= 0 && m_index + n < m_size)\r
+ {\r
+ m_index += n;\r
+ m_iterator += n;\r
+ }\r
+ else\r
+ {\r
+ m_index += n;\r
+ update_iterator();\r
+ }\r
+ }\r
+\r
+ inline void update_iterator()\r
+ {\r
+ while (m_index < 0)\r
+ {\r
+ m_index += m_size;\r
+ }\r
+ m_index = m_index % m_size;\r
+ this->m_iterator = boost::begin(*m_range) + m_index;\r
+ }\r
+\r
+ Range* m_range;\r
+ typename boost::range_iterator<Range>::type m_iterator;\r
+ difference_type m_size;\r
+ difference_type m_index;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+\r
+template\r
+<\r
+ typename OuterIterator,\r
+ typename InnerIterator,\r
+ typename Value,\r
+ typename AccessInnerBegin,\r
+ typename AccessInnerEnd,\r
+ typename Reference = Value&\r
+>\r
+class flatten_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ flatten_iterator\r
+ <\r
+ OuterIterator,\r
+ InnerIterator,\r
+ Value,\r
+ AccessInnerBegin,\r
+ AccessInnerEnd,\r
+ Reference\r
+ >,\r
+ Value,\r
+ boost::bidirectional_traversal_tag,\r
+ Reference\r
+ >\r
+{\r
+private:\r
+ OuterIterator m_outer_it, m_outer_end;\r
+ InnerIterator m_inner_it;\r
+\r
+public:\r
+ typedef OuterIterator outer_iterator_type;\r
+ typedef InnerIterator inner_iterator_type;\r
+\r
+ // default constructor\r
+ flatten_iterator() {}\r
+\r
+ // for begin\r
+ flatten_iterator(OuterIterator outer_it, OuterIterator outer_end)\r
+ : m_outer_it(outer_it), m_outer_end(outer_end)\r
+ {\r
+ advance_through_empty();\r
+ }\r
+\r
+ // for end\r
+ flatten_iterator(OuterIterator outer_end)\r
+ : m_outer_it(outer_end), m_outer_end(outer_end)\r
+ {}\r
+\r
+ template\r
+ <\r
+ typename OtherOuterIterator, typename OtherInnerIterator,\r
+ typename OtherValue,\r
+ typename OtherAccessInnerBegin, typename OtherAccessInnerEnd,\r
+ typename OtherReference\r
+ >\r
+ flatten_iterator(flatten_iterator\r
+ <\r
+ OtherOuterIterator,\r
+ OtherInnerIterator,\r
+ OtherValue,\r
+ OtherAccessInnerBegin,\r
+ OtherAccessInnerEnd,\r
+ OtherReference\r
+ > const& other)\r
+ : m_outer_it(other.m_outer_it),\r
+ m_outer_end(other.m_outer_end),\r
+ m_inner_it(other.m_inner_it)\r
+ {\r
+ static const bool are_conv\r
+ = boost::is_convertible\r
+ <\r
+ OtherOuterIterator, OuterIterator\r
+ >::value\r
+ && boost::is_convertible\r
+ <\r
+ OtherInnerIterator, InnerIterator\r
+ >::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((are_conv),\r
+ NOT_CONVERTIBLE,\r
+ (types<OtherOuterIterator, OtherInnerIterator>));\r
+ }\r
+\r
+ flatten_iterator& operator=(flatten_iterator const& other)\r
+ {\r
+ m_outer_it = other.m_outer_it;\r
+ m_outer_end = other.m_outer_end;\r
+ // avoid assigning an iterator having singular value\r
+ if ( other.m_outer_it != other.m_outer_end )\r
+ {\r
+ m_inner_it = other.m_inner_it;\r
+ }\r
+ return *this;\r
+ }\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ template\r
+ <\r
+ typename Outer,\r
+ typename Inner,\r
+ typename V,\r
+ typename InnerBegin,\r
+ typename InnerEnd,\r
+ typename R\r
+ >\r
+ friend class flatten_iterator;\r
+\r
+ static inline bool empty(OuterIterator outer_it)\r
+ {\r
+ return AccessInnerBegin::apply(*outer_it)\r
+ == AccessInnerEnd::apply(*outer_it);\r
+ }\r
+\r
+ inline void advance_through_empty()\r
+ {\r
+ while ( m_outer_it != m_outer_end && empty(m_outer_it) )\r
+ {\r
+ ++m_outer_it;\r
+ }\r
+\r
+ if ( m_outer_it != m_outer_end )\r
+ {\r
+ m_inner_it = AccessInnerBegin::apply(*m_outer_it);\r
+ }\r
+ }\r
+\r
+ inline Reference dereference() const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );\r
+ BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );\r
+ return *m_inner_it;\r
+ }\r
+\r
+\r
+ template\r
+ <\r
+ typename OtherOuterIterator,\r
+ typename OtherInnerIterator,\r
+ typename OtherValue,\r
+ typename OtherAccessInnerBegin,\r
+ typename OtherAccessInnerEnd,\r
+ typename OtherReference\r
+ >\r
+ inline bool equal(flatten_iterator\r
+ <\r
+ OtherOuterIterator,\r
+ OtherInnerIterator,\r
+ OtherValue,\r
+ OtherAccessInnerBegin,\r
+ OtherAccessInnerEnd,\r
+ OtherReference\r
+ > const& other) const\r
+ {\r
+ if ( m_outer_it != other.m_outer_it )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ if ( m_outer_it == m_outer_end )\r
+ {\r
+ return true;\r
+ }\r
+\r
+ return m_inner_it == other.m_inner_it;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ BOOST_GEOMETRY_ASSERT( m_outer_it != m_outer_end );\r
+ BOOST_GEOMETRY_ASSERT( m_inner_it != AccessInnerEnd::apply(*m_outer_it) );\r
+\r
+ ++m_inner_it;\r
+ if ( m_inner_it == AccessInnerEnd::apply(*m_outer_it) )\r
+ {\r
+ ++m_outer_it;\r
+ advance_through_empty();\r
+ }\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ if ( m_outer_it == m_outer_end\r
+ || m_inner_it == AccessInnerBegin::apply(*m_outer_it) )\r
+ {\r
+ do\r
+ {\r
+ --m_outer_it;\r
+ }\r
+ while ( empty(m_outer_it) );\r
+ m_inner_it = AccessInnerEnd::apply(*m_outer_it);\r
+ } \r
+ --m_inner_it;\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_FLATTEN_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_HAS_ONE_ELEMENT_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_HAS_ONE_ELEMENT_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+// free function to test if an iterator range has a single element\r
+template <typename Iterator>\r
+inline bool has_one_element(Iterator first, Iterator beyond)\r
+{\r
+ return first != beyond && ++first == beyond;\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_HAS_ONE_ELEMENT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP\r
+\r
+#include <boost/iterator/iterator_adaptor.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/iterators/dispatch/point_iterator.hpp>\r
+#include <boost/geometry/iterators/detail/point_iterator/iterator_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// specializations for points_begin\r
+\r
+\r
+template <typename Linestring>\r
+struct points_begin<Linestring, linestring_tag>\r
+{\r
+ static inline typename detail::point_iterator::iterator_type\r
+ <\r
+ Linestring\r
+ >::type\r
+ apply(Linestring& linestring)\r
+ {\r
+ return boost::begin(linestring);\r
+ }\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct points_begin<Ring, ring_tag>\r
+{\r
+ static inline typename detail::point_iterator::iterator_type<Ring>::type\r
+ apply(Ring& ring)\r
+ {\r
+ return boost::begin(ring);\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct points_begin<Polygon, polygon_tag>\r
+{\r
+ typedef typename detail::point_iterator::iterator_type\r
+ <\r
+ Polygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Polygon& polygon)\r
+ {\r
+ typedef typename return_type::second_iterator_type flatten_iterator;\r
+\r
+ return return_type\r
+ (boost::begin(geometry::exterior_ring(polygon)),\r
+ boost::end(geometry::exterior_ring(polygon)),\r
+ flatten_iterator(boost::begin(geometry::interior_rings(polygon)),\r
+ boost::end(geometry::interior_rings(polygon))\r
+ ),\r
+ flatten_iterator(boost::begin(geometry::interior_rings(polygon)),\r
+ boost::end(geometry::interior_rings(polygon))\r
+ )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPoint>\r
+struct points_begin<MultiPoint, multi_point_tag>\r
+{\r
+ static inline typename detail::point_iterator::iterator_type\r
+ <\r
+ MultiPoint\r
+ >::type\r
+ apply(MultiPoint& multipoint)\r
+ {\r
+ return boost::begin(multipoint);\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct points_begin<MultiLinestring, multi_linestring_tag>\r
+{\r
+ typedef typename detail::point_iterator::iterator_type\r
+ <\r
+ MultiLinestring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiLinestring& multilinestring)\r
+ {\r
+ return return_type(boost::begin(multilinestring),\r
+ boost::end(multilinestring));\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct points_begin<MultiPolygon, multi_polygon_tag>\r
+{\r
+ typedef typename detail::point_iterator::iterator_type\r
+ <\r
+ MultiPolygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPolygon& multipolygon)\r
+ {\r
+ return return_type(boost::begin(multipolygon),\r
+ boost::end(multipolygon));\r
+ }\r
+};\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// specializations for points_end\r
+\r
+\r
+template <typename Linestring>\r
+struct points_end<Linestring, linestring_tag>\r
+{\r
+ static inline typename detail::point_iterator::iterator_type\r
+ <\r
+ Linestring\r
+ >::type\r
+ apply(Linestring& linestring)\r
+ {\r
+ return boost::end(linestring);\r
+ }\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct points_end<Ring, ring_tag>\r
+{\r
+ static inline typename detail::point_iterator::iterator_type<Ring>::type\r
+ apply(Ring& ring)\r
+ {\r
+ return boost::end(ring);\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct points_end<Polygon, polygon_tag>\r
+{\r
+ typedef typename detail::point_iterator::iterator_type\r
+ <\r
+ Polygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Polygon& polygon)\r
+ {\r
+ typedef typename return_type::second_iterator_type flatten_iterator;\r
+\r
+ return return_type\r
+ (boost::end(geometry::exterior_ring(polygon)),\r
+ flatten_iterator(boost::begin(geometry::interior_rings(polygon)),\r
+ boost::end(geometry::interior_rings(polygon))\r
+ ),\r
+ flatten_iterator( boost::end(geometry::interior_rings(polygon)) )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPoint>\r
+struct points_end<MultiPoint, multi_point_tag>\r
+{\r
+ static inline typename detail::point_iterator::iterator_type\r
+ <\r
+ MultiPoint\r
+ >::type\r
+ apply(MultiPoint& multipoint)\r
+ {\r
+ return boost::end(multipoint);\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct points_end<MultiLinestring, multi_linestring_tag>\r
+{\r
+ typedef typename detail::point_iterator::iterator_type\r
+ <\r
+ MultiLinestring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiLinestring& multilinestring)\r
+ {\r
+ return return_type(boost::end(multilinestring));\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct points_end<MultiPolygon, multi_polygon_tag>\r
+{\r
+ typedef typename detail::point_iterator::iterator_type\r
+ <\r
+ MultiPolygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPolygon& multipolygon)\r
+ {\r
+ return return_type(boost::end(multipolygon));\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+class point_iterator\r
+ : public boost::iterator_adaptor\r
+ <\r
+ point_iterator<Geometry>,\r
+ typename detail::point_iterator::iterator_type<Geometry>::type\r
+ >\r
+{\r
+private:\r
+ template <typename OtherGeometry> friend class point_iterator;\r
+ template <typename G> friend inline point_iterator<G> points_begin(G&);\r
+ template <typename G> friend inline point_iterator<G> points_end(G&);\r
+\r
+ inline point_iterator(typename point_iterator::base_type const& base_it)\r
+ : point_iterator::iterator_adaptor_(base_it) {}\r
+\r
+public:\r
+ inline point_iterator() {}\r
+\r
+ template <typename OtherGeometry>\r
+ inline point_iterator(point_iterator<OtherGeometry> const& other)\r
+ : point_iterator::iterator_adaptor_(other.base())\r
+ {\r
+ static const bool is_conv\r
+ = boost::is_convertible<\r
+ typename detail::point_iterator::iterator_type\r
+ <\r
+ OtherGeometry\r
+ >::type,\r
+ typename detail::point_iterator::iterator_type\r
+ <\r
+ Geometry\r
+ >::type\r
+ >::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((is_conv),\r
+ NOT_CONVERTIBLE,\r
+ (point_iterator<OtherGeometry>));\r
+ }\r
+};\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+inline point_iterator<Geometry>\r
+points_begin(Geometry& geometry)\r
+{\r
+ return dispatch::points_begin<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+inline point_iterator<Geometry>\r
+points_end(Geometry& geometry)\r
+{\r
+ return dispatch::points_end<Geometry>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_POINT_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_POINT_REVERSE_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_POINT_REVERSE_ITERATOR_HPP\r
+\r
+#include <iterator>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+\r
+#include <boost/geometry/iterators/point_iterator.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+class point_reverse_iterator\r
+ : public std::reverse_iterator<point_iterator<Geometry> >\r
+{\r
+private:\r
+ typedef std::reverse_iterator<point_iterator<Geometry> > base_type;\r
+\r
+ template <typename OtherGeometry> friend class point_reverse_iterator;\r
+ template <typename G>\r
+ friend inline point_reverse_iterator<G> points_rbegin(G&);\r
+\r
+ template <typename G>\r
+ friend inline point_reverse_iterator<G> points_rend(G&);\r
+\r
+ inline point_reverse_iterator(base_type const& base_it)\r
+ : base_type(base_it) {}\r
+\r
+public:\r
+ inline point_reverse_iterator() {}\r
+\r
+ template <typename OtherGeometry>\r
+ inline\r
+ point_reverse_iterator(point_reverse_iterator<OtherGeometry> const& other)\r
+ : base_type(other.base())\r
+ {\r
+ static const bool is_conv = boost::is_convertible\r
+ <\r
+ std::reverse_iterator<point_iterator<Geometry> >,\r
+ std::reverse_iterator<point_iterator<OtherGeometry> >\r
+ >::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((is_conv),\r
+ NOT_CONVERTIBLE,\r
+ (point_reverse_iterator<OtherGeometry>));\r
+ }\r
+};\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+inline point_reverse_iterator<Geometry>\r
+points_rbegin(Geometry& geometry)\r
+{\r
+ return std::reverse_iterator\r
+ <\r
+ point_iterator<Geometry>\r
+ >(points_end(geometry));\r
+}\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+inline point_reverse_iterator<Geometry>\r
+points_rend(Geometry& geometry)\r
+{\r
+ return std::reverse_iterator\r
+ <\r
+ point_iterator<Geometry>\r
+ >(points_begin(geometry));\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_POINT_REVERSE_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP\r
+#define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>\r
+#include <boost/geometry/iterators/detail/segment_iterator/iterator_type.hpp>\r
+\r
+#include <boost/geometry/iterators/dispatch/segment_iterator.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// specializations for segments_begin\r
+\r
+\r
+template <typename Linestring>\r
+struct segments_begin<Linestring, linestring_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Linestring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Linestring& linestring)\r
+ {\r
+ return return_type(linestring);\r
+ }\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct segments_begin<Ring, ring_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Ring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Ring& ring)\r
+ {\r
+ return return_type(ring);\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct segments_begin<Polygon, polygon_tag>\r
+{\r
+ typedef typename detail::point_iterator::inner_range_type\r
+ <\r
+ Polygon\r
+ >::type inner_range;\r
+\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Polygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Polygon& polygon)\r
+ {\r
+ typedef typename return_type::second_iterator_type flatten_iterator;\r
+\r
+ return return_type\r
+ (segments_begin\r
+ <\r
+ inner_range\r
+ >::apply(geometry::exterior_ring(polygon)),\r
+ segments_end\r
+ <\r
+ inner_range\r
+ >::apply(geometry::exterior_ring(polygon)),\r
+ flatten_iterator(boost::begin(geometry::interior_rings(polygon)),\r
+ boost::end(geometry::interior_rings(polygon))\r
+ ),\r
+ flatten_iterator(boost::begin(geometry::interior_rings(polygon)),\r
+ boost::end(geometry::interior_rings(polygon))\r
+ )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct segments_begin<MultiLinestring, multi_linestring_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ MultiLinestring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiLinestring& multilinestring)\r
+ {\r
+ return return_type(boost::begin(multilinestring),\r
+ boost::end(multilinestring));\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct segments_begin<MultiPolygon, multi_polygon_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ MultiPolygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPolygon& multipolygon)\r
+ {\r
+ return return_type(boost::begin(multipolygon),\r
+ boost::end(multipolygon));\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+// specializations for segments_end\r
+\r
+\r
+template <typename Linestring>\r
+struct segments_end<Linestring, linestring_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Linestring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Linestring& linestring)\r
+ {\r
+ return return_type(linestring, true);\r
+ }\r
+};\r
+\r
+\r
+template <typename Ring>\r
+struct segments_end<Ring, ring_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Ring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Ring& ring)\r
+ {\r
+ return return_type(ring, true);\r
+ }\r
+};\r
+\r
+\r
+template <typename Polygon>\r
+struct segments_end<Polygon, polygon_tag>\r
+{\r
+ typedef typename detail::point_iterator::inner_range_type\r
+ <\r
+ Polygon\r
+ >::type inner_range;\r
+\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Polygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(Polygon& polygon)\r
+ {\r
+ typedef typename return_type::second_iterator_type flatten_iterator;\r
+\r
+ return return_type\r
+ (segments_end\r
+ <\r
+ inner_range\r
+ >::apply(geometry::exterior_ring(polygon)),\r
+ flatten_iterator(boost::begin(geometry::interior_rings(polygon)),\r
+ boost::end(geometry::interior_rings(polygon))\r
+ ),\r
+ flatten_iterator( boost::end(geometry::interior_rings(polygon)) )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiLinestring>\r
+struct segments_end<MultiLinestring, multi_linestring_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ MultiLinestring\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiLinestring& multilinestring)\r
+ {\r
+ return return_type(boost::end(multilinestring));\r
+ }\r
+};\r
+\r
+\r
+template <typename MultiPolygon>\r
+struct segments_end<MultiPolygon, multi_polygon_tag>\r
+{\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ MultiPolygon\r
+ >::type return_type;\r
+\r
+ static inline return_type apply(MultiPolygon& multipolygon)\r
+ {\r
+ return return_type(boost::end(multipolygon));\r
+ }\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+class segment_iterator\r
+ : public detail::segment_iterator::iterator_type<Geometry>::type\r
+{\r
+private:\r
+ typedef typename detail::segment_iterator::iterator_type\r
+ <\r
+ Geometry\r
+ >::type base;\r
+\r
+ inline base const* base_ptr() const\r
+ {\r
+ return this;\r
+ }\r
+\r
+ template <typename OtherGeometry> friend class segment_iterator;\r
+\r
+ template <typename G>\r
+ friend inline segment_iterator<G const> segments_begin(G const&);\r
+\r
+ template <typename G>\r
+ friend inline segment_iterator<G const> segments_end(G const&);\r
+\r
+ inline segment_iterator(base const& base_it) : base(base_it) {}\r
+\r
+public:\r
+ // The following typedef is needed for this iterator to be\r
+ // bidirectional.\r
+ // Normally we would not have to define this. However, due to the\r
+ // fact that the value type of the iterator is not a reference,\r
+ // the iterator_facade framework (used to define the base class of\r
+ // this iterator) degrades automatically the iterator's category\r
+ // to input iterator. With the following typedef we recover the\r
+ // correct iterator category.\r
+ typedef std::bidirectional_iterator_tag iterator_category;\r
+\r
+ inline segment_iterator() {}\r
+\r
+ template <typename OtherGeometry>\r
+ inline segment_iterator(segment_iterator<OtherGeometry> const& other)\r
+ : base(*other.base_ptr())\r
+ {\r
+ static const bool is_conv\r
+ = boost::is_convertible<\r
+ typename detail::segment_iterator::iterator_type\r
+ <\r
+ OtherGeometry\r
+ >::type,\r
+ typename detail::segment_iterator::iterator_type<Geometry>::type\r
+ >::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((is_conv),\r
+ NOT_CONVERTIBLE,\r
+ (segment_iterator<OtherGeometry>));\r
+ }\r
+\r
+ inline segment_iterator& operator++() // prefix\r
+ {\r
+ base::operator++();\r
+ return *this;\r
+ }\r
+\r
+ inline segment_iterator& operator--() // prefix\r
+ {\r
+ base::operator--();\r
+ return *this;\r
+ }\r
+\r
+ inline segment_iterator operator++(int) // postfix\r
+ {\r
+ segment_iterator copy(*this);\r
+ base::operator++();\r
+ return copy;\r
+ }\r
+\r
+ inline segment_iterator operator--(int) // postfix\r
+ {\r
+ segment_iterator copy(*this);\r
+ base::operator--();\r
+ return copy;\r
+ }\r
+};\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+inline segment_iterator<Geometry const>\r
+segments_begin(Geometry const& geometry)\r
+{\r
+ return dispatch::segments_begin<Geometry const>::apply(geometry);\r
+}\r
+\r
+\r
+// MK:: need to add doc here\r
+template <typename Geometry>\r
+inline segment_iterator<Geometry const>\r
+segments_end(Geometry const& geometry)\r
+{\r
+ return dispatch::segments_end<Geometry const>::apply(geometry);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_APPEND_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_APPEND_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/append.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_APPEND_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/area.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/centroid.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CLEAR_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CLEAR_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/clear.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CLEAR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/correct.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/covered_by.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/extreme_points.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/multi_modify.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MULTI_SUM_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MULTI_SUM_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/multi_sum.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MULTI_SUM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013.\r
+// Modifications copyright (c) 2013, Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013.\r
+// Modifications copyright (c) 2013, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013.\r
+// Modifications copyright (c) 2013, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013.\r
+// Modifications copyright (c) 2013, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2012-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2012-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP\r
+\r
+#include <boost/geometry/algorithms/disjoint.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP\r
+\r
+// this file is intentionally empty (with the exception of the #include below)\r
+// it is used for backward compatinility and may be removed in the future\r
+\r
+#include <boost/geometry/algorithms/distance.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/equals.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/for_each.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/intersection.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/length.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_GEOMETRIES_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_GEOMETRIES_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/num_geometries.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_GEOMETRIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_INTERIOR_RINGS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_INTERIOR_RINGS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_INTERIOR_RINGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/num_points.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/perimeter.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_REMOVE_SPIKES_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_REMOVE_SPIKES_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/remove_spikes.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_REMOVE_SPIKES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_REVERSE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_REVERSE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/reverse.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_REVERSE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/simplify.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/transform.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_UNIQUE_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_UNIQUE_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/unique.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_UNIQUE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014.\r
+// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP\r
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP\r
+\r
+#include <boost/geometry/algorithms/within.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_CLOSURE_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_CLOSURE_HPP\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_CLOSURE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP\r
+\r
+#include <boost/geometry/core/geometry_id.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_INTERIOR_RINGS_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_INTERIOR_RINGS_HPP\r
+\r
+\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_INTERIOR_RINGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_IS_AREAL_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_IS_AREAL_HPP\r
+\r
+\r
+#include <boost/geometry/core/is_areal.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_IS_AREAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_POINT_ORDER_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_POINT_ORDER_HPP\r
+\r
+\r
+#include <boost/geometry/core/point_order.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_POINT_ORDER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP\r
+\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013.\r
+// Modifications copyright (c) 2013, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP\r
+\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP\r
+#define BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP\r
+\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_TOPOLOGICAL_DIMENSION_HPP\r
+#define BOOST_GEOMETRY_MULTI_TOPOLOGICAL_DIMENSION_HPP\r
+\r
+\r
+#include <boost/geometry/core/topological_dimension.hpp>\r
+\r
+\r
+#endif\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/concepts/check.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/concepts/multi_linestring_concept.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/concepts/multi_point_concept.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/concepts/multi_polygon_concept.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP\r
+\r
+#include <boost/geometry/geometries/multi_point.hpp>\r
+#include <boost/geometry/geometries/multi_linestring.hpp>\r
+#include <boost/geometry/geometries/multi_polygon.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_LINESTRING_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/multi_linestring.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/multi_point.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/multi_polygon.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/register/multi_linestring.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POINT_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POINT_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/register/multi_point.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP\r
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP\r
+\r
+\r
+#include <boost/geometry/geometries/register/multi_polygon.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_IO_DSV_WRITE_HPP\r
+#define BOOST_GEOMETRY_MULTI_IO_DSV_WRITE_HPP\r
+\r
+\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_IO_DSV_WRITE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP\r
+#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP\r
+\r
+\r
+#include <boost/geometry/io/wkt/detail/prefix.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP\r
+#define BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP\r
+\r
+\r
+#include <boost/geometry/io/wkt/read.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP\r
+#define BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP\r
+\r
+#include <boost/geometry/io/wkt/read.hpp>\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP\r
+#define BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP\r
+\r
+\r
+#include <boost/geometry/io/wkt/write.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2013, 2015.\r
+// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_HPP\r
+#define BOOST_GEOMETRY_MULTI_HPP\r
+\r
+// keep this file for now, for backward compatibility\r
+// functionality-wise, make it equivalent to boost/geometry/geometry.hpp\r
+#include <boost/geometry/geometry.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP\r
+#define BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP\r
+\r
+\r
+#include <boost/geometry/strategies/cartesian/centroid_average.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_MULTI_VIEWS_DETAIL_RANGE_TYPE_HPP\r
+#define BOOST_GEOMETRY_MULTI_VIEWS_DETAIL_RANGE_TYPE_HPP\r
+\r
+\r
+#include <boost/geometry/views/detail/range_type.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_MULTI_VIEWS_DETAIL_RANGE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_COMPARE_HPP\r
+#define BOOST_GEOMETRY_POLICIES_COMPARE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/strategies/compare.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace compare\r
+{\r
+\r
+\r
+template\r
+<\r
+ int Direction,\r
+ typename Point,\r
+ typename Strategy,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct compare_loop\r
+{\r
+ typedef typename strategy::compare::detail::select_strategy\r
+ <\r
+ Strategy, Direction, Point, Dimension\r
+ >::type compare_type;\r
+\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ static inline bool apply(Point const& left, Point const& right)\r
+ {\r
+ coordinate_type const& cleft = geometry::get<Dimension>(left);\r
+ coordinate_type const& cright = geometry::get<Dimension>(right);\r
+\r
+ if (geometry::math::equals(cleft, cright))\r
+ {\r
+ return compare_loop\r
+ <\r
+ Direction, Point, Strategy,\r
+ Dimension + 1, DimensionCount\r
+ >::apply(left, right);\r
+ }\r
+ else\r
+ {\r
+ compare_type compare;\r
+ return compare(cleft, cright);\r
+ }\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ int Direction,\r
+ typename Point,\r
+ typename Strategy,\r
+ std::size_t DimensionCount\r
+>\r
+struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>\r
+{\r
+ static inline bool apply(Point const&, Point const&)\r
+ {\r
+ // On coming here, points are equal. Return true if\r
+ // direction = 0 (equal), false if -1/1 (greater/less)\r
+ return Direction == 0;\r
+ }\r
+};\r
+\r
+\r
+template <int Direction, typename Point, typename Strategy>\r
+struct compare_in_all_dimensions\r
+{\r
+ inline bool operator()(Point const& left, Point const& right) const\r
+ {\r
+ return detail::compare::compare_loop\r
+ <\r
+ Direction, Point, Strategy,\r
+ 0, geometry::dimension<Point>::type::value\r
+ >::apply(left, right);\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, typename Strategy, std::size_t Dimension>\r
+class compare_in_one_dimension\r
+{\r
+ Strategy compare;\r
+\r
+public :\r
+ inline bool operator()(Point const& left, Point const& right) const\r
+ {\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+\r
+ coordinate_type const& cleft = get<Dimension>(left);\r
+ coordinate_type const& cright = get<Dimension>(right);\r
+ return compare(cleft, cright);\r
+ }\r
+};\r
+\r
+}} // namespace detail::compare\r
+\r
+#endif\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template\r
+<\r
+ int Direction,\r
+ typename Point,\r
+ typename Strategy,\r
+ int Dimension\r
+>\r
+struct compare_geometries\r
+ : detail::compare::compare_in_one_dimension\r
+ <\r
+ Point,\r
+ typename strategy::compare::detail::select_strategy\r
+ <\r
+ Strategy, Direction, Point, Dimension\r
+ >::type,\r
+ Dimension\r
+ >\r
+{};\r
+\r
+\r
+// Specialization with -1: compare in all dimensions\r
+template <int Direction, typename Point, typename Strategy>\r
+struct compare_geometries<Direction, Point, Strategy, -1>\r
+ : detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>\r
+{};\r
+\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+/*!\r
+\brief Less functor, to sort points in ascending order.\r
+\ingroup compare\r
+\details This functor compares points and orders them on x,\r
+ then on y, then on z coordinate.\r
+\tparam Geometry the geometry\r
+\tparam Dimension the dimension to sort on, defaults to -1,\r
+ indicating ALL dimensions. That's to say, first on x,\r
+ on equal x-es then on y, etc.\r
+ If a dimension is specified, only that dimension is considered\r
+\tparam Strategy underlying coordinate comparing functor,\r
+ defaults to the default comparison strategies\r
+ related to the point coordinate system. If specified, the specified\r
+ strategy is used. This can e.g. be std::less<double>.\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ int Dimension = -1,\r
+ typename Strategy = strategy::compare::default_strategy\r
+>\r
+struct less\r
+ : dispatch::compare_geometries\r
+ <\r
+ 1, // indicates ascending\r
+ Point,\r
+ Strategy,\r
+ Dimension\r
+ >\r
+{\r
+ typedef Point first_argument_type;\r
+ typedef Point second_argument_type;\r
+ typedef bool result_type;\r
+};\r
+\r
+\r
+/*!\r
+\brief Greater functor\r
+\ingroup compare\r
+\details Can be used to sort points in reverse order\r
+\see Less functor\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ int Dimension = -1,\r
+ typename Strategy = strategy::compare::default_strategy\r
+>\r
+struct greater\r
+ : dispatch::compare_geometries\r
+ <\r
+ -1, // indicates descending\r
+ Point,\r
+ Strategy,\r
+ Dimension\r
+ >\r
+{};\r
+\r
+\r
+/*!\r
+\brief Equal To functor, to compare if points are equal\r
+\ingroup compare\r
+\tparam Geometry the geometry\r
+\tparam Dimension the dimension to compare on, defaults to -1,\r
+ indicating ALL dimensions.\r
+ If a dimension is specified, only that dimension is considered\r
+\tparam Strategy underlying coordinate comparing functor\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ int Dimension = -1,\r
+ typename Strategy = strategy::compare::default_strategy\r
+>\r
+struct equal_to\r
+ : dispatch::compare_geometries\r
+ <\r
+ 0,\r
+ Point,\r
+ Strategy,\r
+ Dimension\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_COMPARE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013-2014.\r
+// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace disjoint\r
+{\r
+\r
+\r
+struct disjoint_interrupt_policy\r
+{\r
+ static bool const enabled = true;\r
+ bool has_intersections;\r
+\r
+ inline disjoint_interrupt_policy()\r
+ : has_intersections(false)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& range)\r
+ {\r
+ // If there is any IP in the range, it is NOT disjoint\r
+ if (boost::size(range) > 0)\r
+ {\r
+ has_intersections = true;\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace detail::disjoint\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP\r
+#define BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP\r
+\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+template <bool AllowDuplicates = true, bool AllowSpikes = true>\r
+class is_valid_default_policy\r
+{\r
+protected:\r
+ static inline bool is_valid(validity_failure_type failure)\r
+ {\r
+ return failure == no_failure\r
+ || (AllowDuplicates && failure == failure_duplicate_points);\r
+ }\r
+\r
+ static inline bool is_valid(validity_failure_type failure, bool is_linear)\r
+ {\r
+ return is_valid(failure)\r
+ || (is_linear && AllowSpikes && failure == failure_spikes);\r
+ }\r
+\r
+public:\r
+ template <validity_failure_type Failure>\r
+ static inline bool apply()\r
+ {\r
+ return is_valid(Failure);\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data>\r
+ static inline bool apply(Data const&)\r
+ {\r
+ return is_valid(Failure);\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data1, typename Data2>\r
+ static inline bool apply(Data1 const& data1, Data2 const&)\r
+ {\r
+ return is_valid(Failure, data1);\r
+ }\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP\r
+#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP\r
+\r
+#include <sstream>\r
+\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+#include <boost/geometry/util/condition.hpp>\r
+#include <boost/geometry/util/range.hpp>\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+inline char const* validity_failure_type_message(validity_failure_type failure)\r
+{\r
+ switch (failure)\r
+ {\r
+ case no_failure:\r
+ return "Geometry is valid";\r
+ case failure_few_points:\r
+ return "Geometry has too few points";\r
+ case failure_wrong_topological_dimension:\r
+ return "Geometry has wrong topological dimension";\r
+ case failure_not_closed:\r
+ return "Geometry is defined as closed but is open";\r
+ case failure_spikes:\r
+ return "Geometry has spikes";\r
+ case failure_self_intersections:\r
+ return "Geometry has invalid self-intersections";\r
+ case failure_wrong_orientation:\r
+ return "Geometry has wrong orientation";\r
+ case failure_interior_rings_outside:\r
+ return "Geometry has interior rings defined outside the outer boundary";\r
+ case failure_nested_interior_rings:\r
+ return "Geometry has nested interior rings";\r
+ case failure_disconnected_interior:\r
+ return "Geometry has disconnected interior";\r
+ case failure_intersecting_interiors:\r
+ return "Multi-polygon has intersecting interiors";\r
+ case failure_duplicate_points:\r
+ return "Geometry has duplicate (consecutive) points";\r
+ case failure_wrong_corner_order:\r
+ return "Box has corners in wrong order";\r
+ case failure_invalid_coordinate:\r
+ return "Geometry has point(s) with invalid coordinate(s)";\r
+ default: // to avoid -Wreturn-type warning\r
+ return "";\r
+ }\r
+}\r
+\r
+\r
+template <bool AllowDuplicates = true, bool AllowSpikes = true>\r
+class failing_reason_policy\r
+{\r
+private:\r
+ static inline\r
+ validity_failure_type transform_failure_type(validity_failure_type failure)\r
+ {\r
+ if (BOOST_GEOMETRY_CONDITION(\r
+ AllowDuplicates && failure == failure_duplicate_points))\r
+ {\r
+ return no_failure;\r
+ }\r
+ return failure;\r
+ }\r
+\r
+ static inline\r
+ validity_failure_type transform_failure_type(validity_failure_type failure,\r
+ bool is_linear)\r
+ {\r
+ if (BOOST_GEOMETRY_CONDITION(\r
+ is_linear && AllowSpikes && failure == failure_spikes))\r
+ {\r
+ return no_failure;\r
+ }\r
+ return transform_failure_type(failure);\r
+ }\r
+\r
+ inline void set_failure_message(validity_failure_type failure)\r
+ {\r
+ m_oss.str("");\r
+ m_oss.clear();\r
+ m_oss << validity_failure_type_message(failure);\r
+ }\r
+\r
+ template\r
+ <\r
+ validity_failure_type Failure,\r
+ typename Data1,\r
+ typename Data2 = Data1,\r
+ typename Dummy = void\r
+ >\r
+ struct process_data\r
+ {\r
+ static inline void apply(std::ostringstream&, Data1 const&)\r
+ {\r
+ }\r
+\r
+ static inline void apply(std::ostringstream&,\r
+ Data1 const&,\r
+ Data2 const&)\r
+ {\r
+ }\r
+ };\r
+\r
+ template <typename SpikePoint>\r
+ struct process_data<failure_spikes, bool, SpikePoint>\r
+ {\r
+ static inline void apply(std::ostringstream& oss,\r
+ bool is_linear,\r
+ SpikePoint const& spike_point)\r
+ {\r
+ if (BOOST_GEOMETRY_CONDITION(is_linear && AllowSpikes))\r
+ {\r
+ return;\r
+ }\r
+\r
+ oss << ". A spike point was found with apex at "\r
+ << geometry::dsv(spike_point);\r
+ }\r
+ };\r
+\r
+ template <typename Turns>\r
+ struct process_data<failure_self_intersections, Turns>\r
+ {\r
+ static inline\r
+ void apply_to_segment_identifier(std::ostringstream& oss,\r
+ segment_identifier seg_id)\r
+ {\r
+ oss << "{" << seg_id.source_index\r
+ << ", " << seg_id.multi_index\r
+ << ", " << seg_id.ring_index\r
+ << ", " << seg_id.segment_index\r
+ << "}";\r
+ }\r
+\r
+ static inline void apply(std::ostringstream& oss,\r
+ Turns const& turns)\r
+ {\r
+ typedef typename boost::range_value<Turns>::type turn_type;\r
+ turn_type const& turn = range::front(turns);\r
+ oss << ". A self-intersection point was found at "\r
+ << geometry::dsv(turn.point);\r
+\r
+ oss << "; method: " << method_char(turn.method)\r
+ << "; operations: "\r
+ << operation_char(turn.operations[0].operation)\r
+ << "/"\r
+ << operation_char(turn.operations[1].operation)\r
+ << "; segment IDs {source, multi, ring, segment}: ";\r
+ apply_to_segment_identifier(oss, turn.operations[0].seg_id);\r
+ oss << "/";\r
+ apply_to_segment_identifier(oss, turn.operations[1].seg_id);\r
+ }\r
+ };\r
+\r
+ template <typename Point>\r
+ struct process_data<failure_duplicate_points, Point>\r
+ {\r
+ static inline void apply(std::ostringstream& oss,\r
+ Point const& point)\r
+ {\r
+ if (BOOST_GEOMETRY_CONDITION(AllowDuplicates))\r
+ {\r
+ return;\r
+ }\r
+ oss << ". Duplicate points were found near point "\r
+ << geometry::dsv(point);\r
+ }\r
+ };\r
+\r
+public:\r
+ failing_reason_policy(std::ostringstream& oss)\r
+ : m_oss(oss)\r
+ {}\r
+\r
+ template <validity_failure_type Failure>\r
+ inline bool apply()\r
+ {\r
+ validity_failure_type const failure = transform_failure_type(Failure);\r
+ set_failure_message(failure);\r
+ return failure == no_failure;\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data>\r
+ inline bool apply(Data const& data)\r
+ {\r
+ validity_failure_type const failure = transform_failure_type(Failure);\r
+ set_failure_message(failure);\r
+ process_data<Failure, Data>::apply(m_oss, data);\r
+ return failure == no_failure;\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data1, typename Data2>\r
+ inline bool apply(Data1 const& data1, Data2 const& data2)\r
+ {\r
+ validity_failure_type const failure\r
+ = transform_failure_type(Failure, data1);\r
+ set_failure_message(failure);\r
+ process_data<Failure, Data1, Data2>::apply(m_oss, data1, data2);\r
+ return failure == no_failure;\r
+ }\r
+\r
+private:\r
+ std::ostringstream& m_oss;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP\r
+#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP\r
+\r
+#include <boost/geometry/algorithms/validity_failure_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+// policy that simply keeps (and can return) the failure type\r
+template <bool AllowDuplicates = true, bool AllowSpikes = true>\r
+class failure_type_policy\r
+{\r
+private:\r
+ static inline\r
+ validity_failure_type transform_failure_type(validity_failure_type failure)\r
+ {\r
+ if (AllowDuplicates && failure == failure_duplicate_points)\r
+ {\r
+ return no_failure;\r
+ }\r
+ return failure;\r
+ }\r
+\r
+ static inline\r
+ validity_failure_type transform_failure_type(validity_failure_type failure,\r
+ bool is_linear)\r
+ {\r
+ if (is_linear && AllowSpikes && failure == failure_spikes)\r
+ {\r
+ return no_failure;\r
+ }\r
+ return transform_failure_type(failure);\r
+ }\r
+\r
+public:\r
+ failure_type_policy()\r
+ : m_failure(no_failure)\r
+ {}\r
+\r
+ template <validity_failure_type Failure>\r
+ inline bool apply()\r
+ {\r
+ m_failure = transform_failure_type(Failure);\r
+ return m_failure == no_failure;\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data>\r
+ inline bool apply(Data const&)\r
+ {\r
+ return apply<Failure>();\r
+ }\r
+\r
+ template <validity_failure_type Failure, typename Data1, typename Data2>\r
+ inline bool apply(Data1 const& data1, Data2 const&)\r
+ {\r
+ m_failure = transform_failure_type(Failure, data1);\r
+ return m_failure == no_failure;\r
+ }\r
+\r
+ validity_failure_type failure() const\r
+ {\r
+ return m_failure;\r
+ }\r
+\r
+private:\r
+ validity_failure_type m_failure;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP\r
+#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace overlay\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename IsAcceptableTurnPredicate,\r
+ bool AllowEmptyTurnRange = true // by default, allow an empty turn range\r
+>\r
+struct stateless_predicate_based_interrupt_policy\r
+{\r
+ static bool const enabled = true;\r
+ bool has_intersections; // set to true if there is at least one\r
+ // unacceptable turn\r
+\r
+ inline stateless_predicate_based_interrupt_policy()\r
+ : has_intersections(false)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& range)\r
+ {\r
+ // if there is at least one unacceptable turn in the range, return false\r
+ has_intersections = !detail::check_iterator_range\r
+ <\r
+ IsAcceptableTurnPredicate,\r
+ AllowEmptyTurnRange\r
+ >::apply(boost::begin(range), boost::end(range));\r
+\r
+ return has_intersections;\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+template\r
+<\r
+ typename IsAcceptableTurnPredicate,\r
+ bool AllowEmptyTurnRange = true // by default, allow an empty turn range\r
+>\r
+struct predicate_based_interrupt_policy\r
+{\r
+ static bool const enabled = true;\r
+ bool has_intersections; // set to true if there is at least one\r
+ // unacceptable turn\r
+ IsAcceptableTurnPredicate const& m_predicate;\r
+\r
+ inline\r
+ predicate_based_interrupt_policy(IsAcceptableTurnPredicate const& predicate)\r
+ : has_intersections(false)\r
+ , m_predicate(predicate)\r
+ {}\r
+\r
+ template <typename Range>\r
+ inline bool apply(Range const& range)\r
+ {\r
+ // if there is at least one unacceptable turn in the range, return false\r
+ has_intersections = !detail::check_iterator_range\r
+ <\r
+ IsAcceptableTurnPredicate,\r
+ AllowEmptyTurnRange\r
+ >::apply(boost::begin(range), boost::end(range), m_predicate);\r
+\r
+ return has_intersections;\r
+ }\r
+};\r
+\r
+\r
+\r
+\r
+}} // namespace detail::overlay\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP\r
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP\r
+\r
+\r
+#include <cstddef>\r
+#include <string>\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/strategies/side_info.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace policies { namespace relate\r
+{\r
+\r
+struct direction_type\r
+{\r
+ // NOTE: "char" will be replaced by enum in future version\r
+\r
+ inline direction_type(side_info const& s, char h,\r
+ int ha, int hb,\r
+ int da = 0, int db = 0,\r
+ bool op = false)\r
+ : how(h)\r
+ , opposite(op)\r
+ , how_a(ha)\r
+ , how_b(hb)\r
+ , dir_a(da)\r
+ , dir_b(db)\r
+ , sides(s)\r
+ {\r
+ arrival[0] = ha;\r
+ arrival[1] = hb;\r
+ }\r
+\r
+ inline direction_type(char h, bool op, int ha = 0, int hb = 0)\r
+ : how(h)\r
+ , opposite(op)\r
+ , how_a(ha)\r
+ , how_b(hb)\r
+ , dir_a(0)\r
+ , dir_b(0)\r
+ {\r
+ arrival[0] = ha;\r
+ arrival[1] = hb;\r
+ }\r
+\r
+\r
+ // TODO: replace this\r
+ // NOTE: "char" will be replaced by enum in future version\r
+ // "How" is the intersection formed?\r
+ char how;\r
+\r
+ // Is it opposite (for collinear/equal cases)\r
+ bool opposite;\r
+\r
+ // Information on how A arrives at intersection, how B arrives at intersection\r
+ // 1: arrives at intersection\r
+ // -1: starts from intersection\r
+ int how_a;\r
+ int how_b;\r
+\r
+ // Direction: how is A positioned from B\r
+ // 1: points left, seen from IP\r
+ // -1: points right, seen from IP\r
+ // In case of intersection: B's TO direction\r
+ // In case that B's TO direction is at A: B's from direction\r
+ // In collinear cases: it is 0\r
+ int dir_a; // Direction of A-s TO from IP\r
+ int dir_b; // Direction of B-s TO from IP\r
+\r
+ // New information\r
+ side_info sides;\r
+ // THIS IS EQUAL TO arrival_a, arrival_b - they probably can go now we have robust fractions\r
+ int arrival[2]; // 1=arrival, -1=departure, 0=neutral; == how_a//how_b\r
+\r
+\r
+ // About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases\r
+ // Arrival 1: a1--------->a2 (a arrives within b)\r
+ // b1----->b2\r
+\r
+ // Arrival 1: (a in b)\r
+ //\r
+\r
+\r
+ // Arrival -1: a1--------->a2 (a does not arrive within b)\r
+ // b1----->b2\r
+\r
+ // Arrival -1: (b in a) a_1-------------a_2\r
+ // b_1---b_2\r
+\r
+ // Arrival 0: a1------->a2 (a arrives at TO-border of b)\r
+ // b1--->b2\r
+\r
+};\r
+\r
+struct segments_direction\r
+{\r
+ typedef direction_type return_type;\r
+\r
+ template\r
+ <\r
+ typename Segment1,\r
+ typename Segment2,\r
+ typename SegmentIntersectionInfo\r
+ >\r
+ static inline return_type segments_crosses(side_info const& sides,\r
+ SegmentIntersectionInfo const& ,\r
+ Segment1 const& , Segment2 const& )\r
+ {\r
+ bool const ra0 = sides.get<0,0>() == 0;\r
+ bool const ra1 = sides.get<0,1>() == 0;\r
+ bool const rb0 = sides.get<1,0>() == 0;\r
+ bool const rb1 = sides.get<1,1>() == 0;\r
+\r
+ return\r
+ // opposite and same starting point (FROM)\r
+ ra0 && rb0 ? calculate_side<1>(sides, 'f', -1, -1)\r
+\r
+ // opposite and point to each other (TO)\r
+ : ra1 && rb1 ? calculate_side<0>(sides, 't', 1, 1)\r
+\r
+ // not opposite, forming an angle, first a then b,\r
+ // directed either both left, or both right\r
+ // Check side of B2 from A. This is not calculated before\r
+ : ra1 && rb0 ? angle<1>(sides, 'a', 1, -1)\r
+\r
+ // not opposite, forming a angle, first b then a,\r
+ // directed either both left, or both right\r
+ : ra0 && rb1 ? angle<0>(sides, 'a', -1, 1)\r
+\r
+ // b starts from interior of a\r
+ : rb0 ? starts_from_middle(sides, 'B', 0, -1)\r
+\r
+ // a starts from interior of b (#39)\r
+ : ra0 ? starts_from_middle(sides, 'A', -1, 0)\r
+\r
+ // b ends at interior of a, calculate direction of A from IP\r
+ : rb1 ? b_ends_at_middle(sides)\r
+\r
+ // a ends at interior of b\r
+ : ra1 ? a_ends_at_middle(sides)\r
+\r
+ // normal intersection\r
+ : calculate_side<1>(sides, 'i', -1, -1)\r
+ ;\r
+ }\r
+\r
+ template <typename Ratio>\r
+ static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)\r
+ {\r
+ // a1--------->a2\r
+ // b1----->b2\r
+ // a departs: -1\r
+\r
+ // a1--------->a2\r
+ // b1----->b2\r
+ // a arrives: 1\r
+\r
+ // a1--------->a2\r
+ // b1----->b2\r
+ // both arrive there -> r-to = 1/1, or 0/1 (on_segment)\r
+\r
+ // First check the TO (for arrival), then FROM (for departure)\r
+ return r_to.in_segment() ? 1\r
+ : r_to.on_segment() ? 0\r
+ : r_from.on_segment() ? -1\r
+ : -1\r
+ ;\r
+ }\r
+\r
+ template <typename Ratio>\r
+ static inline void analyze(Ratio const& r,\r
+ int& in_segment_count,\r
+ int& on_end_count,\r
+ int& outside_segment_count)\r
+ {\r
+ if (r.on_end())\r
+ {\r
+ on_end_count++;\r
+ }\r
+ else if (r.in_segment())\r
+ {\r
+ in_segment_count++;\r
+ }\r
+ else\r
+ {\r
+ outside_segment_count++;\r
+ }\r
+ }\r
+\r
+ static inline int arrival_from_position_value(int /*v_from*/, int v_to)\r
+ {\r
+ return v_to == 2 ? 1\r
+ : v_to == 1 || v_to == 3 ? 0\r
+ //: v_from >= 1 && v_from <= 3 ? -1\r
+ : -1;\r
+\r
+ // NOTE: this should be an equivalent of the above for the other order\r
+ /* (v_from < 3 && v_to > 3) || (v_from > 3 && v_to < 3) ? 1\r
+ : v_from == 3 || v_to == 3 ? 0\r
+ : -1;*/\r
+ }\r
+\r
+ static inline void analyse_position_value(int pos_val,\r
+ int & in_segment_count,\r
+ int & on_end_count,\r
+ int & outside_segment_count)\r
+ {\r
+ if ( pos_val == 1 || pos_val == 3 )\r
+ {\r
+ on_end_count++;\r
+ }\r
+ else if ( pos_val == 2 )\r
+ {\r
+ in_segment_count++;\r
+ }\r
+ else\r
+ {\r
+ outside_segment_count++;\r
+ }\r
+ }\r
+\r
+ template <typename Segment1, typename Segment2, typename Ratio>\r
+ static inline return_type segments_collinear(\r
+ Segment1 const& , Segment2 const& , bool opposite,\r
+ int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,\r
+ Ratio const& /*ra_from_wrt_b*/, Ratio const& /*ra_to_wrt_b*/,\r
+ Ratio const& /*rb_from_wrt_a*/, Ratio const& /*rb_to_wrt_a*/)\r
+ {\r
+ return_type r('c', opposite);\r
+\r
+ // IMPORTANT: the order of conditions is different as in intersection_points.hpp\r
+ // We assign A in 0 and B in 1\r
+ r.arrival[0] = arrival_from_position_value(a1_wrt_b, a2_wrt_b);\r
+ r.arrival[1] = arrival_from_position_value(b1_wrt_a, b2_wrt_a);\r
+\r
+ // Analyse them\r
+ int a_in_segment_count = 0;\r
+ int a_on_end_count = 0;\r
+ int a_outside_segment_count = 0;\r
+ int b_in_segment_count = 0;\r
+ int b_on_end_count = 0;\r
+ int b_outside_segment_count = 0;\r
+ analyse_position_value(a1_wrt_b,\r
+ a_in_segment_count, a_on_end_count, a_outside_segment_count);\r
+ analyse_position_value(a2_wrt_b,\r
+ a_in_segment_count, a_on_end_count, a_outside_segment_count);\r
+ analyse_position_value(b1_wrt_a,\r
+ b_in_segment_count, b_on_end_count, b_outside_segment_count);\r
+ analyse_position_value(b2_wrt_a,\r
+ b_in_segment_count, b_on_end_count, b_outside_segment_count);\r
+\r
+ if (a_on_end_count == 1\r
+ && b_on_end_count == 1\r
+ && a_outside_segment_count == 1\r
+ && b_outside_segment_count == 1)\r
+ {\r
+ // This is a collinear touch\r
+ // --------> A (or B)\r
+ // <---------- B (or A)\r
+ // We adapt the "how"\r
+ // TODO: how was to be refactored anyway,\r
+ if (! opposite)\r
+ {\r
+ r.how = 'a';\r
+ }\r
+ else\r
+ {\r
+ r.how = r.arrival[0] == 0 ? 't' : 'f';\r
+ }\r
+ }\r
+ else if (a_on_end_count == 2\r
+ && b_on_end_count == 2)\r
+ {\r
+ r.how = 'e';\r
+ }\r
+\r
+ return r;\r
+ }\r
+\r
+ template <typename Segment>\r
+ static inline return_type degenerate(Segment const& , bool)\r
+ {\r
+ return return_type('0', false);\r
+ }\r
+\r
+ template <typename Segment, typename Ratio>\r
+ static inline return_type one_degenerate(Segment const& ,\r
+ Ratio const& ,\r
+ bool)\r
+ {\r
+ // To be decided\r
+ return return_type('0', false);\r
+ }\r
+\r
+ static inline return_type disjoint()\r
+ {\r
+ return return_type('d', false);\r
+ }\r
+\r
+ static inline return_type error(std::string const&)\r
+ {\r
+ // Return "E" to denote error\r
+ // This will throw an error in get_turn_info\r
+ // TODO: change to enum or similar\r
+ return return_type('E', false);\r
+ }\r
+\r
+private :\r
+\r
+ template <std::size_t I>\r
+ static inline return_type calculate_side(side_info const& sides,\r
+ char how, int how_a, int how_b)\r
+ {\r
+ int const dir = sides.get<1, I>() == 1 ? 1 : -1;\r
+ return return_type(sides, how, how_a, how_b, -dir, dir);\r
+ }\r
+\r
+ template <std::size_t I>\r
+ static inline return_type angle(side_info const& sides,\r
+ char how, int how_a, int how_b)\r
+ {\r
+ int const dir = sides.get<1, I>() == 1 ? 1 : -1;\r
+ return return_type(sides, how, how_a, how_b, dir, dir);\r
+ }\r
+\r
+\r
+ static inline return_type starts_from_middle(side_info const& sides,\r
+ char which,\r
+ int how_a, int how_b)\r
+ {\r
+ // Calculate ARROW of b segment w.r.t. s1\r
+ int dir = sides.get<1, 1>() == 1 ? 1 : -1;\r
+\r
+ // From other perspective, then reverse\r
+ bool const is_a = which == 'A';\r
+ if (is_a)\r
+ {\r
+ dir = -dir;\r
+ }\r
+\r
+ return return_type(sides, 's',\r
+ how_a,\r
+ how_b,\r
+ is_a ? dir : -dir,\r
+ ! is_a ? dir : -dir);\r
+ }\r
+\r
+\r
+\r
+ // To be harmonized\r
+ static inline return_type a_ends_at_middle(side_info const& sides)\r
+ {\r
+ // Ending at the middle, one ARRIVES, the other one is NEUTRAL\r
+ // (because it both "arrives" and "departs" there)\r
+ int const dir = sides.get<1, 1>() == 1 ? 1 : -1;\r
+ return return_type(sides, 'm', 1, 0, dir, dir);\r
+ }\r
+\r
+\r
+ static inline return_type b_ends_at_middle(side_info const& sides)\r
+ {\r
+ int const dir = sides.get<0, 1>() == 1 ? 1 : -1;\r
+ return return_type(sides, 'm', 0, 1, dir, dir);\r
+ }\r
+\r
+};\r
+\r
+}} // namespace policies::relate\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP\r
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP\r
+\r
+\r
+#include <algorithm>\r
+#include <string>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/strategies/side_info.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace policies { namespace relate\r
+{\r
+\r
+\r
+/*!\r
+\brief Policy calculating the intersection points themselves\r
+ */\r
+template\r
+<\r
+ typename ReturnType\r
+>\r
+struct segments_intersection_points\r
+{\r
+ typedef ReturnType return_type;\r
+\r
+ template\r
+ <\r
+ typename Segment1,\r
+ typename Segment2,\r
+ typename SegmentIntersectionInfo\r
+ >\r
+ static inline return_type segments_crosses(side_info const&,\r
+ SegmentIntersectionInfo const& sinfo,\r
+ Segment1 const& s1, Segment2 const& s2)\r
+ {\r
+ return_type result;\r
+ result.count = 1;\r
+\r
+ bool use_a = true;\r
+\r
+ // Prefer one segment if one is on or near an endpoint\r
+ bool const a_near_end = sinfo.robust_ra.near_end();\r
+ bool const b_near_end = sinfo.robust_rb.near_end();\r
+ if (a_near_end && ! b_near_end)\r
+ {\r
+ use_a = true;\r
+ }\r
+ else if (b_near_end && ! a_near_end)\r
+ {\r
+ use_a = false;\r
+ }\r
+ else\r
+ {\r
+ // Prefer shorter segment\r
+ typedef typename SegmentIntersectionInfo::promoted_type ptype;\r
+ ptype const len_a = sinfo.comparable_length_a();\r
+ ptype const len_b = sinfo.comparable_length_b();\r
+ if (len_b < len_a)\r
+ {\r
+ use_a = false;\r
+ }\r
+ // else use_a is true but was already assigned like that\r
+ }\r
+\r
+ if (use_a)\r
+ {\r
+ sinfo.assign_a(result.intersections[0], s1, s2);\r
+ }\r
+ else\r
+ {\r
+ sinfo.assign_b(result.intersections[0], s1, s2);\r
+ }\r
+\r
+ result.fractions[0].assign(sinfo);\r
+\r
+ return result;\r
+ }\r
+\r
+ template <typename Segment1, typename Segment2, typename Ratio>\r
+ static inline return_type segments_collinear(\r
+ Segment1 const& a, Segment2 const& b, bool /*opposite*/,\r
+ int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,\r
+ Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,\r
+ Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)\r
+ {\r
+ return_type result;\r
+ unsigned int index = 0, count_a = 0, count_b = 0;\r
+ Ratio on_a[2];\r
+\r
+ // The conditions "index < 2" are necessary for non-robust handling,\r
+ // if index would be 2 this indicate an (currently uncatched) error\r
+\r
+ // IMPORTANT: the order of conditions is different as in direction.hpp\r
+ if (a1_wrt_b >= 1 && a1_wrt_b <= 3 // ra_from_wrt_b.on_segment()\r
+ && index < 2)\r
+ {\r
+ // a1--------->a2\r
+ // b1----->b2\r
+ //\r
+ // ra1 (relative to b) is between 0/1:\r
+ // -> First point of A is intersection point\r
+ detail::assign_point_from_index<0>(a, result.intersections[index]);\r
+ result.fractions[index].assign(Ratio::zero(), ra_from_wrt_b);\r
+ on_a[index] = Ratio::zero();\r
+ index++;\r
+ count_a++;\r
+ }\r
+ if (b1_wrt_a == 2 //rb_from_wrt_a.in_segment()\r
+ && index < 2)\r
+ {\r
+ // We take the first intersection point of B\r
+ // a1--------->a2\r
+ // b1----->b2\r
+ // But only if it is not located on A\r
+ // a1--------->a2\r
+ // b1----->b2 rb_from_wrt_a == 0/1 -> a already taken\r
+\r
+ detail::assign_point_from_index<0>(b, result.intersections[index]);\r
+ result.fractions[index].assign(rb_from_wrt_a, Ratio::zero());\r
+ on_a[index] = rb_from_wrt_a;\r
+ index++;\r
+ count_b++;\r
+ }\r
+\r
+ if (a2_wrt_b >= 1 && a2_wrt_b <= 3 //ra_to_wrt_b.on_segment()\r
+ && index < 2)\r
+ {\r
+ // Similarly, second IP (here a2)\r
+ // a1--------->a2\r
+ // b1----->b2\r
+ detail::assign_point_from_index<1>(a, result.intersections[index]);\r
+ result.fractions[index].assign(Ratio::one(), ra_to_wrt_b);\r
+ on_a[index] = Ratio::one();\r
+ index++;\r
+ count_a++;\r
+ }\r
+ if (b2_wrt_a == 2 // rb_to_wrt_a.in_segment()\r
+ && index < 2)\r
+ {\r
+ detail::assign_point_from_index<1>(b, result.intersections[index]);\r
+ result.fractions[index].assign(rb_to_wrt_a, Ratio::one());\r
+ on_a[index] = rb_to_wrt_a;\r
+ index++;\r
+ count_b++;\r
+ }\r
+\r
+ // TEMPORARY\r
+ // If both are from b, and b is reversed w.r.t. a, we swap IP's\r
+ // to align them w.r.t. a\r
+ // get_turn_info still relies on some order (in some collinear cases)\r
+ if (index == 2 && on_a[1] < on_a[0])\r
+ {\r
+ std::swap(result.fractions[0], result.fractions[1]);\r
+ std::swap(result.intersections[0], result.intersections[1]);\r
+ }\r
+\r
+ result.count = index;\r
+\r
+ return result;\r
+ }\r
+\r
+ static inline return_type disjoint()\r
+ {\r
+ return return_type();\r
+ }\r
+ static inline return_type error(std::string const&)\r
+ {\r
+ return return_type();\r
+ }\r
+\r
+ // Both degenerate\r
+ template <typename Segment>\r
+ static inline return_type degenerate(Segment const& segment, bool)\r
+ {\r
+ return_type result;\r
+ result.count = 1;\r
+ set<0>(result.intersections[0], get<0, 0>(segment));\r
+ set<1>(result.intersections[0], get<0, 1>(segment));\r
+ return result;\r
+ }\r
+\r
+ // One degenerate\r
+ template <typename Segment, typename Ratio>\r
+ static inline return_type one_degenerate(Segment const& degenerate_segment,\r
+ Ratio const& ratio, bool a_degenerate)\r
+ {\r
+ return_type result;\r
+ result.count = 1;\r
+ set<0>(result.intersections[0], get<0, 0>(degenerate_segment));\r
+ set<1>(result.intersections[0], get<0, 1>(degenerate_segment));\r
+ if (a_degenerate)\r
+ {\r
+ // IP lies on ratio w.r.t. segment b\r
+ result.fractions[0].assign(Ratio::zero(), ratio);\r
+ }\r
+ else\r
+ {\r
+ result.fractions[0].assign(ratio, Ratio::zero());\r
+ }\r
+ return result;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace policies::relate\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP\r
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP\r
+\r
+\r
+#include <algorithm>\r
+#include <string>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/strategies/side_info.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace policies { namespace relate\r
+{\r
+\r
+\r
+/*!\r
+\brief Policy returning segment ratios\r
+\note Template argument FractionType should be a fraction_type<SegmentRatio>\r
+ */\r
+template\r
+<\r
+ typename FractionType\r
+>\r
+struct segments_intersection_ratios\r
+{\r
+ typedef FractionType return_type;\r
+\r
+ template\r
+ <\r
+ typename Segment1,\r
+ typename Segment2,\r
+ typename SegmentIntersectionInfo\r
+ >\r
+ static inline return_type segments_crosses(side_info const&,\r
+ SegmentIntersectionInfo const& sinfo,\r
+ Segment1 const& , Segment2 const& )\r
+ {\r
+ return_type result;\r
+ result.assign(sinfo);\r
+ return result;\r
+ }\r
+\r
+ template <typename Segment1, typename Segment2, typename Ratio>\r
+ static inline return_type segments_collinear(\r
+ Segment1 const& , Segment2 const& ,\r
+ Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,\r
+ Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)\r
+ {\r
+ // We have only one result, for (potentially) two IP's,\r
+ // so we take a first one\r
+ return_type result;\r
+\r
+ if (ra_from_wrt_b.on_segment())\r
+ {\r
+ result.assign(Ratio::zero(), ra_from_wrt_b);\r
+ }\r
+ else if (rb_from_wrt_a.in_segment())\r
+ {\r
+ result.assign(rb_from_wrt_a, Ratio::zero());\r
+ }\r
+ else if (ra_to_wrt_b.on_segment())\r
+ {\r
+ result.assign(Ratio::one(), ra_to_wrt_b);\r
+ }\r
+ else if (rb_to_wrt_a.in_segment())\r
+ {\r
+ result.assign(rb_to_wrt_a, Ratio::one());\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ static inline return_type disjoint()\r
+ {\r
+ return return_type();\r
+ }\r
+ static inline return_type error(std::string const&)\r
+ {\r
+ return return_type();\r
+ }\r
+\r
+ template <typename Segment>\r
+ static inline return_type degenerate(Segment const& segment, bool)\r
+ {\r
+ return return_type();\r
+ }\r
+\r
+ template <typename Segment, typename Ratio>\r
+ static inline return_type one_degenerate(Segment const& ,\r
+ Ratio const& ratio, bool a_degenerate)\r
+ {\r
+ return_type result;\r
+ if (a_degenerate)\r
+ {\r
+ // IP lies on ratio w.r.t. segment b\r
+ result.assign(Ratio::zero(), ratio);\r
+ }\r
+ else\r
+ {\r
+ result.assign(ratio, Ratio::zero());\r
+ }\r
+ return result;\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace policies::relate\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP\r
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP\r
+\r
+\r
+#include <string>\r
+\r
+#include <boost/tuple/tuple.hpp>\r
+#include <boost/geometry/strategies/side_info.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace policies { namespace relate\r
+{\r
+\r
+\r
+// "tupled" to return intersection results together.\r
+// Now with two, with some meta-programming and derivations it can also be three (or more)\r
+template <typename Policy1, typename Policy2>\r
+struct segments_tupled\r
+{\r
+ typedef boost::tuple\r
+ <\r
+ typename Policy1::return_type,\r
+ typename Policy2::return_type\r
+ > return_type;\r
+\r
+ template <typename Segment1, typename Segment2, typename SegmentIntersectionInfo>\r
+ static inline return_type segments_crosses(side_info const& sides,\r
+ SegmentIntersectionInfo const& sinfo,\r
+ Segment1 const& s1, Segment2 const& s2)\r
+ {\r
+ return boost::make_tuple\r
+ (\r
+ Policy1::segments_crosses(sides, sinfo, s1, s2),\r
+ Policy2::segments_crosses(sides, sinfo, s1, s2)\r
+ );\r
+ }\r
+\r
+ template <typename Segment1, typename Segment2, typename Ratio>\r
+ static inline return_type segments_collinear(\r
+ Segment1 const& segment1, Segment2 const& segment2,\r
+ bool opposite,\r
+ int pa1, int pa2, int pb1, int pb2,\r
+ Ratio const& ra1, Ratio const& ra2,\r
+ Ratio const& rb1, Ratio const& rb2)\r
+ {\r
+ return boost::make_tuple\r
+ (\r
+ Policy1::segments_collinear(segment1, segment2,\r
+ opposite,\r
+ pa1, pa2, pb1, pb2,\r
+ ra1, ra2, rb1, rb2),\r
+ Policy2::segments_collinear(segment1, segment2,\r
+ opposite,\r
+ pa1, pa2, pb1, pb2,\r
+ ra1, ra2, rb1, rb2)\r
+ );\r
+ }\r
+\r
+ template <typename Segment>\r
+ static inline return_type degenerate(Segment const& segment,\r
+ bool a_degenerate)\r
+ {\r
+ return boost::make_tuple\r
+ (\r
+ Policy1::degenerate(segment, a_degenerate),\r
+ Policy2::degenerate(segment, a_degenerate)\r
+ );\r
+ }\r
+\r
+ template <typename Segment, typename Ratio>\r
+ static inline return_type one_degenerate(Segment const& segment,\r
+ Ratio const& ratio,\r
+ bool a_degenerate)\r
+ {\r
+ return boost::make_tuple\r
+ (\r
+ Policy1::one_degenerate(segment, ratio, a_degenerate),\r
+ Policy2::one_degenerate(segment, ratio, a_degenerate)\r
+ );\r
+ }\r
+\r
+ static inline return_type disjoint()\r
+ {\r
+ return boost::make_tuple\r
+ (\r
+ Policy1::disjoint(),\r
+ Policy2::disjoint()\r
+ );\r
+ }\r
+\r
+ static inline return_type error(std::string const& msg)\r
+ {\r
+ return boost::make_tuple\r
+ (\r
+ Policy1::error(msg),\r
+ Policy2::error(msg)\r
+ );\r
+ }\r
+\r
+};\r
+\r
+}} // namespace policies::relate\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2014-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/tag_cast.hpp>\r
+\r
+#include <boost/geometry/algorithms/envelope.hpp>\r
+#include <boost/geometry/algorithms/expand.hpp>\r
+#include <boost/geometry/algorithms/is_empty.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+#include <boost/geometry/algorithms/detail/get_max_size.hpp>\r
+#include <boost/geometry/policies/robustness/robust_type.hpp>\r
+\r
+#include <boost/geometry/geometries/point.hpp>\r
+#include <boost/geometry/geometries/box.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>\r
+#include <boost/geometry/policies/robustness/rescale_policy.hpp>\r
+\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace get_rescale_policy\r
+{\r
+\r
+template\r
+<\r
+ typename Box,\r
+ typename Point,\r
+ typename RobustPoint,\r
+ typename Factor\r
+>\r
+inline void scale_box_to_integer_range(Box const& box,\r
+ Point& min_point,\r
+ RobustPoint& min_robust_point,\r
+ Factor& factor)\r
+{\r
+ // Scale box to integer-range\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename geometry::coordinate_type<Point>::type\r
+ >::type num_type;\r
+ num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(box));\r
+ num_type const range = 10000000.0; // Define a large range to get precise integer coordinates\r
+ num_type const half = 0.5;\r
+ if (math::equals(diff, num_type())\r
+ || diff >= range\r
+ || ! boost::math::isfinite(diff))\r
+ {\r
+ factor = 1;\r
+ }\r
+ else\r
+ {\r
+ factor = boost::numeric_cast<num_type>(\r
+ boost::numeric_cast<boost::long_long_type>(half + range / diff));\r
+ BOOST_GEOMETRY_ASSERT(factor >= 1);\r
+ }\r
+\r
+ // Assign input/output minimal points\r
+ detail::assign_point_from_index<0>(box, min_point);\r
+ num_type const two = 2;\r
+ boost::long_long_type const min_coordinate\r
+ = boost::numeric_cast<boost::long_long_type>(-range / two);\r
+ assign_values(min_robust_point, min_coordinate, min_coordinate);\r
+}\r
+\r
+template <typename Point, typename RobustPoint, typename Geometry, typename Factor>\r
+static inline void init_rescale_policy(Geometry const& geometry,\r
+ Point& min_point,\r
+ RobustPoint& min_robust_point,\r
+ Factor& factor)\r
+{\r
+ if (geometry::is_empty(geometry))\r
+ {\r
+ return;\r
+ }\r
+\r
+ // Get bounding boxes\r
+ model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);\r
+\r
+ scale_box_to_integer_range(env, min_point, min_robust_point, factor);\r
+}\r
+\r
+template <typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, typename Factor>\r
+static inline void init_rescale_policy(Geometry1 const& geometry1,\r
+ Geometry2 const& geometry2,\r
+ Point& min_point,\r
+ RobustPoint& min_robust_point,\r
+ Factor& factor)\r
+{\r
+ // Get bounding boxes (when at least one of the geometries is not empty)\r
+ bool const is_empty1 = geometry::is_empty(geometry1);\r
+ bool const is_empty2 = geometry::is_empty(geometry2);\r
+ if (is_empty1 && is_empty2)\r
+ {\r
+ return;\r
+ }\r
+\r
+ model::box<Point> env;\r
+ if (is_empty1)\r
+ {\r
+ geometry::envelope(geometry2, env);\r
+ }\r
+ else if (is_empty2)\r
+ {\r
+ geometry::envelope(geometry1, env);\r
+ }\r
+ else\r
+ {\r
+ // The following approach (envelope + expand) may not give the\r
+ // optimal MBR when then two geometries are in the spherical\r
+ // equatorial or geographic coordinate systems.\r
+ // TODO: implement envelope for two (or possibly more geometries)\r
+ geometry::envelope(geometry1, env);\r
+ model::box<Point> env2 = geometry::return_envelope\r
+ <\r
+ model::box<Point>\r
+ >(geometry2);\r
+ geometry::expand(env, env2);\r
+ }\r
+\r
+ scale_box_to_integer_range(env, min_point, min_robust_point, factor);\r
+}\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ bool IsFloatingPoint\r
+>\r
+struct rescale_policy_type\r
+{\r
+ typedef no_rescale_policy type;\r
+};\r
+\r
+// We rescale only all FP types\r
+template\r
+<\r
+ typename Point\r
+>\r
+struct rescale_policy_type<Point, true>\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+ typedef model::point\r
+ <\r
+ typename detail::robust_type<coordinate_type>::type,\r
+ geometry::dimension<Point>::value,\r
+ typename geometry::coordinate_system<Point>::type\r
+ > robust_point_type;\r
+ typedef typename promote_floating_point<coordinate_type>::type factor_type;\r
+ typedef detail::robust_policy<Point, robust_point_type, factor_type> type;\r
+};\r
+\r
+template <typename Policy>\r
+struct get_rescale_policy\r
+{\r
+ template <typename Geometry>\r
+ static inline Policy apply(Geometry const& geometry)\r
+ {\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;\r
+ typedef typename promote_floating_point<coordinate_type>::type factor_type;\r
+ typedef model::point\r
+ <\r
+ typename detail::robust_type<coordinate_type>::type,\r
+ geometry::dimension<point_type>::value,\r
+ typename geometry::coordinate_system<point_type>::type\r
+ > robust_point_type;\r
+\r
+ point_type min_point;\r
+ robust_point_type min_robust_point;\r
+ factor_type factor;\r
+ init_rescale_policy(geometry, min_point, min_robust_point, factor);\r
+\r
+ return Policy(min_point, min_robust_point, factor);\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ typedef typename point_type<Geometry1>::type point_type;\r
+ typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;\r
+ typedef typename promote_floating_point<coordinate_type>::type factor_type;\r
+ typedef model::point\r
+ <\r
+ typename detail::robust_type<coordinate_type>::type,\r
+ geometry::dimension<point_type>::value,\r
+ typename geometry::coordinate_system<point_type>::type\r
+ > robust_point_type;\r
+\r
+ point_type min_point;\r
+ robust_point_type min_robust_point;\r
+ factor_type factor;\r
+ init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, factor);\r
+\r
+ return Policy(min_point, min_robust_point, factor);\r
+ }\r
+};\r
+\r
+// Specialization for no-rescaling\r
+template <>\r
+struct get_rescale_policy<no_rescale_policy>\r
+{\r
+ template <typename Geometry>\r
+ static inline no_rescale_policy apply(Geometry const& )\r
+ {\r
+ return no_rescale_policy();\r
+ }\r
+\r
+ template <typename Geometry1, typename Geometry2>\r
+ static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& )\r
+ {\r
+ return no_rescale_policy();\r
+ }\r
+};\r
+\r
+\r
+}} // namespace detail::get_rescale_policy\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+template<typename Point>\r
+struct rescale_policy_type\r
+ : public detail::get_rescale_policy::rescale_policy_type\r
+ <\r
+ Point,\r
+#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)\r
+ false\r
+#else\r
+ boost::is_floating_point\r
+ <\r
+ typename geometry::coordinate_type<Point>::type\r
+ >::type::value\r
+ &&\r
+ boost::is_same\r
+ <\r
+ typename geometry::coordinate_system<Point>::type,\r
+ geometry::cs::cartesian\r
+ >::value\r
+#endif\r
+ >\r
+{\r
+ static const bool is_point\r
+ = boost::is_same\r
+ <\r
+ typename geometry::tag<Point>::type,\r
+ geometry::point_tag\r
+ >::type::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((is_point),\r
+ INVALID_INPUT_GEOMETRY,\r
+ (typename geometry::tag<Point>::type));\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Tag1 = typename tag_cast\r
+ <\r
+ typename tag<Geometry1>::type,\r
+ box_tag,\r
+ pointlike_tag,\r
+ linear_tag,\r
+ areal_tag\r
+ >::type,\r
+ typename Tag2 = typename tag_cast\r
+ <\r
+ typename tag<Geometry2>::type,\r
+ box_tag,\r
+ pointlike_tag,\r
+ linear_tag,\r
+ areal_tag\r
+ >::type\r
+>\r
+struct rescale_overlay_policy_type\r
+ // Default: no rescaling\r
+ : public detail::get_rescale_policy::rescale_policy_type\r
+ <\r
+ typename geometry::point_type<Geometry1>::type,\r
+ false\r
+ >\r
+{};\r
+\r
+// Areal/areal: get rescale policy based on coordinate type\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2\r
+>\r
+struct rescale_overlay_policy_type<Geometry1, Geometry2, areal_tag, areal_tag>\r
+ : public rescale_policy_type\r
+ <\r
+ typename geometry::point_type<Geometry1>::type\r
+ >\r
+{};\r
+\r
+\r
+template <typename Policy, typename Geometry>\r
+inline Policy get_rescale_policy(Geometry const& geometry)\r
+{\r
+ return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry);\r
+}\r
+\r
+template <typename Policy, typename Geometry1, typename Geometry2>\r
+inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+{\r
+ return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry1, geometry2);\r
+}\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP\r
+\r
+#include <stddef.h>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+// Probably this will be moved out of namespace detail\r
+struct no_rescale_policy\r
+{\r
+ static bool const enabled = false;\r
+\r
+ // We don't rescale but return the reference of the input\r
+ template <std::size_t Dimension, typename Value>\r
+ inline Value const& apply(Value const& value) const\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+\r
+// Implement meta-functions for this policy\r
+template <typename Point>\r
+struct robust_point_type<Point, detail::no_rescale_policy>\r
+{\r
+ // The point itself\r
+ typedef Point type;\r
+};\r
+\r
+template <typename Point>\r
+struct segment_ratio_type<Point, detail::no_rescale_policy>\r
+{\r
+ // Define a segment_ratio defined on coordinate type, e.g.\r
+ // int/int or float/float\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+ typedef segment_ratio<coordinate_type> type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2014-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename FpPoint, typename IntPoint, typename CalculationType>\r
+struct robust_policy\r
+{\r
+ static bool const enabled = true;\r
+\r
+ typedef typename geometry::coordinate_type<IntPoint>::type output_ct;\r
+\r
+ robust_policy(FpPoint const& fp_min, IntPoint const& int_min, CalculationType const& the_factor)\r
+ : m_fp_min(fp_min)\r
+ , m_int_min(int_min)\r
+ , m_multiplier(the_factor)\r
+ {\r
+ }\r
+\r
+ template <std::size_t Dimension, typename Value>\r
+ inline output_ct apply(Value const& value) const\r
+ {\r
+ // a + (v-b)*f\r
+ CalculationType const a = static_cast<CalculationType>(get<Dimension>(m_int_min));\r
+ CalculationType const b = static_cast<CalculationType>(get<Dimension>(m_fp_min));\r
+ CalculationType const result = a + (value - b) * m_multiplier;\r
+\r
+ return geometry::math::rounding_cast<output_ct>(result);\r
+ }\r
+\r
+ FpPoint m_fp_min;\r
+ IntPoint m_int_min;\r
+ CalculationType m_multiplier;\r
+};\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+\r
+// Implement meta-functions for this policy\r
+\r
+// Define the IntPoint as a robust-point type\r
+template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>\r
+struct robust_point_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >\r
+{\r
+ typedef IntPoint type;\r
+};\r
+\r
+// Meta function for rescaling, if rescaling is done segment_ratio is based on long long\r
+template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>\r
+struct segment_ratio_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >\r
+{\r
+ typedef segment_ratio<boost::long_long_type> type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Meta-function to typedef a robust point type for a policy\r
+template <typename Point, typename Policy>\r
+struct robust_point_type\r
+{\r
+ // By default, the point itself is the robust type\r
+ typedef Point type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2014 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP\r
+\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+\r
+namespace detail_dispatch\r
+{\r
+\r
+template <typename CoordinateType, typename IsFloatingPoint>\r
+struct robust_type\r
+{\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct robust_type<CoordinateType, boost::false_type>\r
+{\r
+ typedef CoordinateType type;\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct robust_type<CoordinateType, boost::true_type>\r
+{\r
+ typedef boost::long_long_type type;\r
+};\r
+\r
+} // namespace detail_dispatch\r
+\r
+namespace detail\r
+{\r
+\r
+template <typename CoordinateType>\r
+struct robust_type\r
+{\r
+ typedef typename detail_dispatch::robust_type\r
+ <\r
+ CoordinateType,\r
+ typename boost::is_floating_point<CoordinateType>::type\r
+ >::type type;\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/rational.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace detail { namespace segment_ratio\r
+{\r
+\r
+template\r
+<\r
+ typename Type,\r
+ bool IsIntegral = boost::is_integral<Type>::type::value\r
+>\r
+struct less {};\r
+\r
+template <typename Type>\r
+struct less<Type, true>\r
+{\r
+ template <typename Ratio>\r
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)\r
+ {\r
+ return boost::rational<Type>(lhs.numerator(), lhs.denominator())\r
+ < boost::rational<Type>(rhs.numerator(), rhs.denominator());\r
+ }\r
+};\r
+\r
+template <typename Type>\r
+struct less<Type, false>\r
+{\r
+ template <typename Ratio>\r
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);\r
+ BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);\r
+ return lhs.numerator() * rhs.denominator()\r
+ < rhs.numerator() * lhs.denominator();\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Type,\r
+ bool IsIntegral = boost::is_integral<Type>::type::value\r
+>\r
+struct equal {};\r
+\r
+template <typename Type>\r
+struct equal<Type, true>\r
+{\r
+ template <typename Ratio>\r
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)\r
+ {\r
+ return boost::rational<Type>(lhs.numerator(), lhs.denominator())\r
+ == boost::rational<Type>(rhs.numerator(), rhs.denominator());\r
+ }\r
+};\r
+\r
+template <typename Type>\r
+struct equal<Type, false>\r
+{\r
+ template <typename Ratio>\r
+ static inline bool apply(Ratio const& lhs, Ratio const& rhs)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);\r
+ BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);\r
+ return geometry::math::equals\r
+ (\r
+ lhs.numerator() * rhs.denominator(),\r
+ rhs.numerator() * lhs.denominator()\r
+ );\r
+ }\r
+};\r
+\r
+}}\r
+\r
+//! Small class to keep a ratio (e.g. 1/4)\r
+//! Main purpose is intersections and checking on 0, 1, and smaller/larger\r
+//! The prototype used Boost.Rational. However, we also want to store FP ratios,\r
+//! (so numerator/denominator both in float)\r
+//! and Boost.Rational starts with GCD which we prefer to avoid if not necessary\r
+//! On a segment means: this ratio is between 0 and 1 (both inclusive)\r
+//!\r
+template <typename Type>\r
+class segment_ratio\r
+{\r
+public :\r
+ typedef Type numeric_type;\r
+\r
+ // Type-alias for the type itself\r
+ typedef segment_ratio<Type> thistype;\r
+\r
+ inline segment_ratio()\r
+ : m_numerator(0)\r
+ , m_denominator(1)\r
+ , m_approximation(0)\r
+ {}\r
+\r
+ inline segment_ratio(const Type& nominator, const Type& denominator)\r
+ : m_numerator(nominator)\r
+ , m_denominator(denominator)\r
+ {\r
+ initialize();\r
+ }\r
+\r
+ inline Type const& numerator() const { return m_numerator; }\r
+ inline Type const& denominator() const { return m_denominator; }\r
+\r
+ inline void assign(const Type& nominator, const Type& denominator)\r
+ {\r
+ m_numerator = nominator;\r
+ m_denominator = denominator;\r
+ initialize();\r
+ }\r
+\r
+ inline void initialize()\r
+ {\r
+ // Minimal normalization\r
+ // 1/-4 => -1/4, -1/-4 => 1/4\r
+ if (m_denominator < 0)\r
+ {\r
+ m_numerator = -m_numerator;\r
+ m_denominator = -m_denominator;\r
+ }\r
+\r
+ m_approximation =\r
+ m_denominator == 0 ? 0\r
+ : boost::numeric_cast<double>\r
+ (\r
+ boost::numeric_cast<fp_type>(m_numerator) * scale()\r
+ / boost::numeric_cast<fp_type>(m_denominator)\r
+ );\r
+ }\r
+\r
+ inline bool is_zero() const { return math::equals(m_numerator, 0); }\r
+ inline bool is_one() const { return math::equals(m_numerator, m_denominator); }\r
+ inline bool on_segment() const\r
+ {\r
+ // e.g. 0/4 or 4/4 or 2/4\r
+ return m_numerator >= 0 && m_numerator <= m_denominator;\r
+ }\r
+ inline bool in_segment() const\r
+ {\r
+ // e.g. 1/4\r
+ return m_numerator > 0 && m_numerator < m_denominator;\r
+ }\r
+ inline bool on_end() const\r
+ {\r
+ // e.g. 0/4 or 4/4\r
+ return is_zero() || is_one();\r
+ }\r
+ inline bool left() const\r
+ {\r
+ // e.g. -1/4\r
+ return m_numerator < 0;\r
+ }\r
+ inline bool right() const\r
+ {\r
+ // e.g. 5/4\r
+ return m_numerator > m_denominator;\r
+ }\r
+\r
+ inline bool near_end() const\r
+ {\r
+ if (left() || right())\r
+ {\r
+ return false;\r
+ }\r
+\r
+ static fp_type const small_part_of_scale = scale() / 100.0;\r
+ return m_approximation < small_part_of_scale\r
+ || m_approximation > scale() - small_part_of_scale;\r
+ }\r
+\r
+ inline bool close_to(thistype const& other) const\r
+ {\r
+ return geometry::math::abs(m_approximation - other.m_approximation) < 50;\r
+ }\r
+\r
+ inline bool operator< (thistype const& other) const\r
+ {\r
+ return close_to(other)\r
+ ? detail::segment_ratio::less<Type>::apply(*this, other)\r
+ : m_approximation < other.m_approximation;\r
+ }\r
+\r
+ inline bool operator== (thistype const& other) const\r
+ {\r
+ return close_to(other)\r
+ && detail::segment_ratio::equal<Type>::apply(*this, other);\r
+ }\r
+\r
+ static inline thistype zero()\r
+ {\r
+ static thistype result(0, 1);\r
+ return result;\r
+ }\r
+\r
+ static inline thistype one()\r
+ {\r
+ static thistype result(1, 1);\r
+ return result;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO)\r
+ friend std::ostream& operator<<(std::ostream &os, segment_ratio const& ratio)\r
+ {\r
+ os << ratio.m_numerator << "/" << ratio.m_denominator\r
+ << " (" << (static_cast<double>(ratio.m_numerator)\r
+ / static_cast<double>(ratio.m_denominator))\r
+ << ")";\r
+ return os;\r
+ }\r
+#endif\r
+\r
+\r
+\r
+private :\r
+ typedef typename promote_floating_point<Type>::type fp_type;\r
+\r
+ Type m_numerator;\r
+ Type m_denominator;\r
+\r
+ // Contains ratio on scale 0..1000000 (for 0..1)\r
+ // This is an approximation for fast and rough comparisons\r
+ // Boost.Rational is used if the approximations are close.\r
+ // Reason: performance, Boost.Rational does a GCD by default and also the\r
+ // comparisons contain while-loops.\r
+ fp_type m_approximation;\r
+\r
+\r
+ static inline fp_type scale()\r
+ {\r
+ return 1000000.0;\r
+ }\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2013 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP\r
+#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Meta-function to access segment-ratio for a policy\r
+template <typename Point, typename Policy>\r
+struct segment_ratio_type {}; // : not_implemented<> {};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+\r
+/*!\r
+\brief Let the buffer for linestrings be asymmetric\r
+\ingroup strategies\r
+\tparam NumericType \tparam_numeric\r
+\details This strategy can be used as DistanceStrategy for the buffer algorithm.\r
+ It can be applied for (multi)linestrings. It uses a (potentially) different\r
+ distances for left and for right. This means the (multi)linestrings are\r
+ interpreted having a direction.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_distance_asymmetric]\r
+[heading Output]\r
+[$img/strategies/buffer_distance_asymmetric.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_distance_symmetric distance_symmetric]\r
+}\r
+ */\r
+template<typename NumericType>\r
+class distance_asymmetric\r
+{\r
+public :\r
+ //! \brief Constructs the strategy, two distances must be specified\r
+ //! \param left The distance (or radius) of the buffer on the left side\r
+ //! \param right The distance on the right side\r
+ distance_asymmetric(NumericType const& left,\r
+ NumericType const& right)\r
+ : m_left(left)\r
+ , m_right(right)\r
+ {}\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Returns the distance-value for the specified side\r
+ template <typename Point>\r
+ inline NumericType apply(Point const& , Point const& ,\r
+ buffer_side_selector side) const\r
+ {\r
+ NumericType result = side == buffer_side_left ? m_left : m_right;\r
+ return negative() ? math::abs(result) : result;\r
+ }\r
+\r
+ //! Used internally, returns -1 for deflate, 1 for inflate\r
+ inline int factor() const\r
+ {\r
+ return negative() ? -1 : 1;\r
+ }\r
+\r
+ //! Returns true if both distances are negative\r
+ inline bool negative() const\r
+ {\r
+ return m_left < 0 && m_right < 0;\r
+ }\r
+\r
+ //! Returns the max distance distance up to the buffer will reach\r
+ template <typename JoinStrategy, typename EndStrategy>\r
+ inline NumericType max_distance(JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy) const\r
+ {\r
+ boost::ignore_unused(join_strategy, end_strategy);\r
+\r
+ NumericType const left = geometry::math::abs(m_left);\r
+ NumericType const right = geometry::math::abs(m_right);\r
+ NumericType const dist = (std::max)(left, right);\r
+ return (std::max)(join_strategy.max_distance(dist),\r
+ end_strategy.max_distance(dist));\r
+ }\r
+\r
+ //! Returns the distance at which the input is simplified before the buffer process\r
+ inline NumericType simplify_distance() const\r
+ {\r
+ NumericType const left = geometry::math::abs(m_left);\r
+ NumericType const right = geometry::math::abs(m_right);\r
+ return (std::min)(left, right) / 1000.0;\r
+ }\r
+\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+private :\r
+ NumericType m_left;\r
+ NumericType m_right;\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_ASYMMETRIC_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+\r
+/*!\r
+\brief Let the buffer algorithm create buffers with same distances\r
+\ingroup strategies\r
+\tparam NumericType \tparam_numeric\r
+\details This strategy can be used as DistanceStrategy for the buffer algorithm.\r
+ It can be applied for all geometries. It uses one distance for left and\r
+ for right.\r
+ If the distance is negative and used with a (multi)polygon or ring, the\r
+ geometry will shrink (deflate) instead of expand (inflate).\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_distance_symmetric]\r
+[heading Output]\r
+[$img/strategies/buffer_distance_symmetric.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_distance_asymmetric distance_asymmetric]\r
+}\r
+ */\r
+template<typename NumericType>\r
+class distance_symmetric\r
+{\r
+public :\r
+ //! \brief Constructs the strategy, a distance must be specified\r
+ //! \param distance The distance (or radius) of the buffer\r
+ explicit inline distance_symmetric(NumericType const& distance)\r
+ : m_distance(distance)\r
+ {}\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Returns the distance-value\r
+ template <typename Point>\r
+ inline NumericType apply(Point const& , Point const& ,\r
+ buffer_side_selector ) const\r
+ {\r
+ return negative() ? geometry::math::abs(m_distance) : m_distance;\r
+ }\r
+\r
+ //! Used internally, returns -1 for deflate, 1 for inflate\r
+ inline int factor() const\r
+ {\r
+ return negative() ? -1 : 1;\r
+ }\r
+\r
+ //! Returns true if distance is negative\r
+ inline bool negative() const\r
+ {\r
+ return m_distance < 0;\r
+ }\r
+\r
+ //! Returns the max distance distance up to the buffer will reach\r
+ template <typename JoinStrategy, typename EndStrategy>\r
+ inline NumericType max_distance(JoinStrategy const& join_strategy,\r
+ EndStrategy const& end_strategy) const\r
+ {\r
+ boost::ignore_unused(join_strategy, end_strategy);\r
+\r
+ NumericType const dist = geometry::math::abs(m_distance);\r
+ return (std::max)(join_strategy.max_distance(dist),\r
+ end_strategy.max_distance(dist));\r
+ }\r
+\r
+\r
+ //! Returns the distance at which the input is simplified before the buffer process\r
+ inline NumericType simplify_distance() const\r
+ {\r
+ return geometry::math::abs(m_distance) / 1000.0;\r
+ }\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+private :\r
+ NumericType m_distance;\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_BUFFER_DISTANCE_SYMMETRIC_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP\r
+\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/strategies/convex_hull.hpp>\r
+\r
+#include <boost/geometry/views/detail/range_type.hpp>\r
+\r
+#include <boost/geometry/policies/compare.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace convex_hull\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename InputRange,\r
+ typename RangeIterator,\r
+ typename StrategyLess,\r
+ typename StrategyGreater\r
+>\r
+struct get_extremes\r
+{\r
+ typedef typename point_type<InputRange>::type point_type;\r
+\r
+ point_type left, right;\r
+\r
+ bool first;\r
+\r
+ StrategyLess less;\r
+ StrategyGreater greater;\r
+\r
+ inline get_extremes()\r
+ : first(true)\r
+ {}\r
+\r
+ inline void apply(InputRange const& range)\r
+ {\r
+ if (boost::size(range) == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ // First iterate through this range\r
+ // (this two-stage approach avoids many point copies,\r
+ // because iterators are kept in memory. Because iterators are\r
+ // not persistent (in MSVC) this approach is not applicable\r
+ // for more ranges together)\r
+\r
+ RangeIterator left_it = boost::begin(range);\r
+ RangeIterator right_it = boost::begin(range);\r
+\r
+ for (RangeIterator it = boost::begin(range) + 1;\r
+ it != boost::end(range);\r
+ ++it)\r
+ {\r
+ if (less(*it, *left_it))\r
+ {\r
+ left_it = it;\r
+ }\r
+\r
+ if (greater(*it, *right_it))\r
+ {\r
+ right_it = it;\r
+ }\r
+ }\r
+\r
+ // Then compare with earlier\r
+ if (first)\r
+ {\r
+ // First time, assign left/right\r
+ left = *left_it;\r
+ right = *right_it;\r
+ first = false;\r
+ }\r
+ else\r
+ {\r
+ // Next time, check if this range was left/right from\r
+ // the extremes already collected\r
+ if (less(*left_it, left))\r
+ {\r
+ left = *left_it;\r
+ }\r
+\r
+ if (greater(*right_it, right))\r
+ {\r
+ right = *right_it;\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename InputRange,\r
+ typename RangeIterator,\r
+ typename Container,\r
+ typename SideStrategy\r
+>\r
+struct assign_range\r
+{\r
+ Container lower_points, upper_points;\r
+\r
+ typedef typename point_type<InputRange>::type point_type;\r
+\r
+ point_type const& most_left;\r
+ point_type const& most_right;\r
+\r
+ inline assign_range(point_type const& left, point_type const& right)\r
+ : most_left(left)\r
+ , most_right(right)\r
+ {}\r
+\r
+ inline void apply(InputRange const& range)\r
+ {\r
+ typedef SideStrategy side;\r
+\r
+ // Put points in one of the two output sequences\r
+ for (RangeIterator it = boost::begin(range);\r
+ it != boost::end(range);\r
+ ++it)\r
+ {\r
+ // check if it is lying most_left or most_right from the line\r
+\r
+ int dir = side::apply(most_left, most_right, *it);\r
+ switch(dir)\r
+ {\r
+ case 1 : // left side\r
+ upper_points.push_back(*it);\r
+ break;\r
+ case -1 : // right side\r
+ lower_points.push_back(*it);\r
+ break;\r
+\r
+ // 0: on line most_left-most_right,\r
+ // or most_left, or most_right,\r
+ // -> all never part of hull\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+template <typename Range>\r
+static inline void sort(Range& range)\r
+{\r
+ typedef typename boost::range_value<Range>::type point_type;\r
+ typedef geometry::less<point_type> comparator;\r
+\r
+ std::sort(boost::begin(range), boost::end(range), comparator());\r
+}\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Graham scan strategy to calculate convex hull\r
+\ingroup strategies\r
+\note Completely reworked version inspired on the sources listed below\r
+\see http://www.ddj.com/architect/201806315\r
+\see http://marknelson.us/2007/08/22/convex\r
+ */\r
+template <typename InputGeometry, typename OutputPoint>\r
+class graham_andrew\r
+{\r
+public :\r
+ typedef OutputPoint point_type;\r
+ typedef InputGeometry geometry_type;\r
+\r
+private:\r
+\r
+ typedef typename cs_tag<point_type>::type cs_tag;\r
+\r
+ typedef typename std::vector<point_type> container_type;\r
+ typedef typename std::vector<point_type>::const_iterator iterator;\r
+ typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;\r
+\r
+\r
+ class partitions\r
+ {\r
+ friend class graham_andrew;\r
+\r
+ container_type m_lower_hull;\r
+ container_type m_upper_hull;\r
+ container_type m_copied_input;\r
+ };\r
+\r
+\r
+public:\r
+ typedef partitions state_type;\r
+\r
+\r
+ inline void apply(InputGeometry const& geometry, partitions& state) const\r
+ {\r
+ // First pass.\r
+ // Get min/max (in most cases left / right) points\r
+ // This makes use of the geometry::less/greater predicates\r
+\r
+ // For the left boundary it is important that multiple points\r
+ // are sorted from bottom to top. Therefore the less predicate\r
+ // does not take the x-only template parameter (this fixes ticket #6019.\r
+ // For the right boundary it is not necessary (though also not harmful),\r
+ // because points are sorted from bottom to top in a later stage.\r
+ // For symmetry and to get often more balanced lower/upper halves\r
+ // we keep it.\r
+\r
+ typedef typename geometry::detail::range_type<InputGeometry>::type range_type;\r
+\r
+ typedef typename boost::range_iterator\r
+ <\r
+ range_type const\r
+ >::type range_iterator;\r
+\r
+ detail::get_extremes\r
+ <\r
+ range_type,\r
+ range_iterator,\r
+ geometry::less<point_type>,\r
+ geometry::greater<point_type>\r
+ > extremes;\r
+ geometry::detail::for_each_range(geometry, extremes);\r
+\r
+ // Bounding left/right points\r
+ // Second pass, now that extremes are found, assign all points\r
+ // in either lower, either upper\r
+ detail::assign_range\r
+ <\r
+ range_type,\r
+ range_iterator,\r
+ container_type,\r
+ typename strategy::side::services::default_strategy<cs_tag>::type\r
+ > assigner(extremes.left, extremes.right);\r
+\r
+ geometry::detail::for_each_range(geometry, assigner);\r
+\r
+\r
+ // Sort both collections, first on x(, then on y)\r
+ detail::sort(assigner.lower_points);\r
+ detail::sort(assigner.upper_points);\r
+\r
+ //std::cout << boost::size(assigner.lower_points) << std::endl;\r
+ //std::cout << boost::size(assigner.upper_points) << std::endl;\r
+\r
+ // And decide which point should be in the final hull\r
+ build_half_hull<-1>(assigner.lower_points, state.m_lower_hull,\r
+ extremes.left, extremes.right);\r
+ build_half_hull<1>(assigner.upper_points, state.m_upper_hull,\r
+ extremes.left, extremes.right);\r
+ }\r
+\r
+\r
+ template <typename OutputIterator>\r
+ inline void result(partitions const& state,\r
+ OutputIterator out,\r
+ bool clockwise,\r
+ bool closed) const\r
+ {\r
+ if (clockwise)\r
+ {\r
+ output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);\r
+ }\r
+ else\r
+ {\r
+ output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);\r
+ }\r
+ }\r
+\r
+\r
+private:\r
+\r
+ template <int Factor>\r
+ static inline void build_half_hull(container_type const& input,\r
+ container_type& output,\r
+ point_type const& left, point_type const& right)\r
+ {\r
+ output.push_back(left);\r
+ for(iterator it = input.begin(); it != input.end(); ++it)\r
+ {\r
+ add_to_hull<Factor>(*it, output);\r
+ }\r
+ add_to_hull<Factor>(right, output);\r
+ }\r
+\r
+\r
+ template <int Factor>\r
+ static inline void add_to_hull(point_type const& p, container_type& output)\r
+ {\r
+ typedef typename strategy::side::services::default_strategy<cs_tag>::type side;\r
+\r
+ output.push_back(p);\r
+ std::size_t output_size = output.size();\r
+ while (output_size >= 3)\r
+ {\r
+ rev_iterator rit = output.rbegin();\r
+ point_type const last = *rit++;\r
+ point_type const& last2 = *rit++;\r
+\r
+ if (Factor * side::apply(*rit, last, last2) <= 0)\r
+ {\r
+ // Remove last two points from stack, and add last again\r
+ // This is much faster then erasing the one but last.\r
+ output.pop_back();\r
+ output.pop_back();\r
+ output.push_back(last);\r
+ output_size--;\r
+ }\r
+ else\r
+ {\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ template <typename OutputIterator>\r
+ static inline void output_ranges(container_type const& first, container_type const& second,\r
+ OutputIterator out, bool closed)\r
+ {\r
+ std::copy(boost::begin(first), boost::end(first), out);\r
+\r
+ BOOST_GEOMETRY_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1);\r
+ std::copy(++boost::rbegin(second), // skip the first Point\r
+ closed ? boost::rend(second) : --boost::rend(second), // skip the last Point if open\r
+ out);\r
+\r
+ typedef typename boost::range_size<container_type>::type size_type;\r
+ size_type const count = boost::size(first) + boost::size(second) - 1;\r
+ // count describes a closed case but comparison with min size of closed\r
+ // gives the result compatible also with open\r
+ // here core_detail::closure::minimum_ring_size<closed> could be used\r
+ if (count < 4)\r
+ {\r
+ // there should be only one missing\r
+ *out++ = *boost::begin(first);\r
+ }\r
+ }\r
+};\r
+\r
+}} // namespace strategy::convex_hull\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+template <typename InputGeometry, typename OutputPoint>\r
+struct strategy_convex_hull<InputGeometry, OutputPoint, cartesian_tag>\r
+{\r
+ typedef strategy::convex_hull::graham_andrew<InputGeometry, OutputPoint> type;\r
+};\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP\r
+\r
+#include <boost/array.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/strategies/covered_by.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace strategy\r
+{\r
+\r
+namespace within\r
+{\r
+\r
+struct decide_within\r
+{\r
+ static inline bool apply(int side, bool& result)\r
+ {\r
+ if (side != 1)\r
+ {\r
+ result = false;\r
+ return false;\r
+ }\r
+ return true; // continue\r
+ }\r
+};\r
+\r
+struct decide_covered_by\r
+{\r
+ static inline bool apply(int side, bool& result)\r
+ {\r
+ if (side != 1)\r
+ {\r
+ result = side >= 0;\r
+ return false;\r
+ }\r
+ return true; // continue\r
+ }\r
+};\r
+\r
+\r
+// WARNING\r
+// This strategy is not suitable for boxes in non-cartesian CSes having edges\r
+// longer than 180deg because e.g. the SSF formula picks the side of the closer\r
+// longitude, so for long edges the side is the opposite.\r
+template <typename Point, typename Box, typename Decide = decide_within>\r
+struct point_in_box_by_side\r
+{\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Box>::type\r
+ >::type side_strategy_type;\r
+\r
+ static inline bool apply(Point const& point, Box const& box)\r
+ {\r
+ // Create (counterclockwise) array of points, the fifth one closes it\r
+ // Every point should be on the LEFT side (=1), or ON the border (=0),\r
+ // So >= 1 or >= 0\r
+ boost::array<typename point_type<Box>::type, 5> bp;\r
+ geometry::detail::assign_box_corners_oriented<true>(box, bp);\r
+ bp[4] = bp[0];\r
+\r
+ bool result = true;\r
+ side_strategy_type strategy;\r
+ boost::ignore_unused_variable_warning(strategy);\r
+\r
+ for (int i = 1; i < 5; i++)\r
+ {\r
+ int const side = strategy.apply(point, bp[i - 1], bp[i]);\r
+ if (! Decide::apply(side, result))\r
+ {\r
+ return result;\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+};\r
+\r
+\r
+} // namespace within\r
+\r
+\r
+}}} // namespace boost::geometry::strategy\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP\r
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP\r
+\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+#include <boost/geometry/strategies/covered_by.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace within\r
+{\r
+\r
+template\r
+<\r
+ typename Point1, typename Point2\r
+>\r
+struct point_in_point\r
+{\r
+ static inline bool apply(Point1 const& point1, Point2 const& point2)\r
+ {\r
+ return detail::equals::equals_point_point(point1, point2);\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+template <typename Point1, typename Point2>\r
+struct default_strategy<point_tag, point_tag, point_tag, point_tag, cartesian_tag, cartesian_tag, Point1, Point2>\r
+{\r
+ typedef strategy::within::point_in_point<Point1, Point2> type;\r
+};\r
+\r
+template <typename Point1, typename Point2>\r
+struct default_strategy<point_tag, point_tag, point_tag, point_tag, spherical_tag, spherical_tag, Point1, Point2>\r
+{\r
+ typedef strategy::within::point_in_point<Point1, Point2> type;\r
+};\r
+\r
+template <typename Point1, typename Point2, typename AnyCS1, typename AnyCS2>\r
+struct default_strategy<point_tag, point_tag, point_tag, point_tag, AnyCS1, AnyCS2, Point1, Point2>\r
+{\r
+ typedef strategy::within::point_in_point<Point1, Point2> type;\r
+};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, cartesian_tag, cartesian_tag, Point, MultiPoint>\r
+{\r
+ typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;\r
+};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, spherical_tag, spherical_tag, Point, MultiPoint>\r
+{\r
+ typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;\r
+};\r
+\r
+template <typename Point, typename MultiPoint, typename AnyCS1, typename AnyCS2>\r
+struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, AnyCS1, AnyCS2, Point, MultiPoint>\r
+{\r
+ typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;\r
+};\r
+\r
+} // namespace services\r
+\r
+#endif\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace strategy { namespace covered_by { namespace services\r
+{\r
+\r
+template <typename Point1, typename Point2>\r
+struct default_strategy<point_tag, point_tag, point_tag, point_tag, cartesian_tag, cartesian_tag, Point1, Point2>\r
+{\r
+ typedef strategy::within::point_in_point<Point1, Point2> type;\r
+};\r
+\r
+template <typename Point1, typename Point2>\r
+struct default_strategy<point_tag, point_tag, point_tag, point_tag, spherical_tag, spherical_tag, Point1, Point2>\r
+{\r
+ typedef strategy::within::point_in_point<Point1, Point2> type;\r
+};\r
+\r
+template <typename Point1, typename Point2, typename AnyCS1, typename AnyCS2>\r
+struct default_strategy<point_tag, point_tag, point_tag, point_tag, AnyCS1, AnyCS2, Point1, Point2>\r
+{\r
+ typedef strategy::within::point_in_point<Point1, Point2> type;\r
+};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, cartesian_tag, cartesian_tag, Point, MultiPoint>\r
+{\r
+ typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;\r
+};\r
+\r
+template <typename Point, typename MultiPoint>\r
+struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, spherical_tag, spherical_tag, Point, MultiPoint>\r
+{\r
+ typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;\r
+};\r
+\r
+template <typename Point, typename MultiPoint, typename AnyCS1, typename AnyCS2>\r
+struct default_strategy<point_tag, multi_point_tag, point_tag, multi_point_tag, AnyCS1, AnyCS2, Point, MultiPoint>\r
+{\r
+ typedef strategy::within::point_in_point<Point, typename point_type<MultiPoint>::type> type;\r
+};\r
+\r
+}}} // namespace strategy::covered_by::services\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP\r
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP\r
+\r
+\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace within\r
+{\r
+\r
+/*!\r
+\brief Within detection using winding rule, but checking if enclosing ring is\r
+ counter clockwise and, if so, reverses the result\r
+\ingroup strategies\r
+\tparam Point \tparam_point\r
+\tparam Reverse True if parameter should be reversed\r
+\tparam PointOfSegment \tparam_segment_point\r
+\tparam CalculationType \tparam_calculation\r
+\author Barend Gehrels\r
+\note The implementation is inspired by terralib http://www.terralib.org (LGPL)\r
+\note but totally revised afterwards, especially for cases on segments\r
+\note Only dependant on "side", -> agnostic, suitable for spherical/latlong\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]\r
+}\r
+ */\r
+template\r
+<\r
+ bool Reverse,\r
+ typename Point,\r
+ typename PointOfSegment = Point,\r
+ typename CalculationType = void\r
+>\r
+class oriented_winding\r
+{\r
+ typedef typename select_calculation_type\r
+ <\r
+ Point,\r
+ PointOfSegment,\r
+ CalculationType\r
+ >::type calculation_type;\r
+\r
+\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type strategy_side_type;\r
+\r
+\r
+ /*! subclass to keep state */\r
+ class counter\r
+ {\r
+ int m_count;\r
+ bool m_touches;\r
+ calculation_type m_sum_area;\r
+\r
+ inline int code() const\r
+ {\r
+ return m_touches ? 0 : m_count == 0 ? -1 : 1;\r
+ }\r
+ inline int clockwise_oriented_code() const\r
+ {\r
+ return (m_sum_area > 0) ? code() : -code();\r
+ }\r
+ inline int oriented_code() const\r
+ {\r
+ return Reverse\r
+ ? -clockwise_oriented_code()\r
+ : clockwise_oriented_code();\r
+ }\r
+\r
+ public :\r
+ friend class oriented_winding;\r
+\r
+ inline counter()\r
+ : m_count(0)\r
+ , m_touches(false)\r
+ , m_sum_area(0)\r
+ {}\r
+\r
+ inline void add_to_area(calculation_type triangle)\r
+ {\r
+ m_sum_area += triangle;\r
+ }\r
+\r
+ };\r
+\r
+\r
+ template <size_t D>\r
+ static inline int check_touch(Point const& point,\r
+ PointOfSegment const& seg1, PointOfSegment const& seg2,\r
+ counter& state)\r
+ {\r
+ calculation_type const p = get<D>(point);\r
+ calculation_type const s1 = get<D>(seg1);\r
+ calculation_type const s2 = get<D>(seg2);\r
+ if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))\r
+ {\r
+ state.m_touches = true;\r
+ }\r
+ return 0;\r
+ }\r
+\r
+\r
+ template <size_t D>\r
+ static inline int check_segment(Point const& point,\r
+ PointOfSegment const& seg1, PointOfSegment const& seg2,\r
+ counter& state)\r
+ {\r
+ calculation_type const p = get<D>(point);\r
+ calculation_type const s1 = get<D>(seg1);\r
+ calculation_type const s2 = get<D>(seg2);\r
+\r
+\r
+ // Check if one of segment endpoints is at same level of point\r
+ bool eq1 = math::equals(s1, p);\r
+ bool eq2 = math::equals(s2, p);\r
+\r
+ if (eq1 && eq2)\r
+ {\r
+ // Both equal p -> segment is horizontal (or vertical for D=0)\r
+ // The only thing which has to be done is check if point is ON segment\r
+ return check_touch<1 - D>(point, seg1, seg2, state);\r
+ }\r
+\r
+ return\r
+ eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2\r
+ : eq2 ? (s1 > p ? -1 : 1) // idem\r
+ : s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP\r
+ : s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN\r
+ : 0;\r
+ }\r
+\r
+\r
+\r
+\r
+public :\r
+\r
+ // Typedefs and static methods to fulfill the concept\r
+ typedef Point point_type;\r
+ typedef PointOfSegment segment_point_type;\r
+ typedef counter state_type;\r
+\r
+ static inline bool apply(Point const& point,\r
+ PointOfSegment const& s1, PointOfSegment const& s2,\r
+ counter& state)\r
+ {\r
+ state.add_to_area(get<0>(s2) * get<1>(s1) - get<0>(s1) * get<1>(s2));\r
+\r
+ int count = check_segment<1>(point, s1, s2, state);\r
+ if (count != 0)\r
+ {\r
+ int side = strategy_side_type::apply(s1, s2, point);\r
+ if (side == 0)\r
+ {\r
+ // Point is lying on segment\r
+ state.m_touches = true;\r
+ state.m_count = 0;\r
+ return false;\r
+ }\r
+\r
+ // Side is NEG for right, POS for left.\r
+ // The count is -2 for down, 2 for up (or -1/1)\r
+ // Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE\r
+ // See accompagnying figure (TODO)\r
+ if (side * count > 0)\r
+ {\r
+ state.m_count += count;\r
+ }\r
+ }\r
+ return ! state.m_touches;\r
+ }\r
+\r
+ static inline int result(counter const& state)\r
+ {\r
+ return state.oriented_code();\r
+ }\r
+};\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2016.\r
+// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP\r
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/covered_by.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace within\r
+{\r
+\r
+// 1 deg or pi/180 rad\r
+template <typename Point,\r
+ typename CalculationType = typename coordinate_type<Point>::type>\r
+struct winding_small_angle\r
+{\r
+ typedef typename coordinate_system<Point>::type cs_t;\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ CalculationType,\r
+ typename cs_t::units\r
+ > constants;\r
+\r
+ static inline CalculationType apply()\r
+ {\r
+ return constants::half_period() / CalculationType(180);\r
+ }\r
+};\r
+\r
+\r
+// Fix for https://svn.boost.org/trac/boost/ticket/9628\r
+// For floating point coordinates, the <D> coordinate of a point is compared\r
+// with the segment's points using some EPS. If the coordinates are "equal"\r
+// the sides are calculated. Therefore we can treat a segment as a long areal\r
+// geometry having some width. There is a small ~triangular area somewhere\r
+// between the segment's effective area and a segment's line used in sides\r
+// calculation where the segment is on the one side of the line but on the\r
+// other side of a segment (due to the width).\r
+// Below picture assuming D = 1, if D = 0 horiz<->vert, E<->N, RIGHT<->UP.\r
+// For the s1 of a segment going NE the real side is RIGHT but the point may\r
+// be detected as LEFT, like this:\r
+// RIGHT\r
+// ___----->\r
+// ^ O Pt __ __\r
+// EPS __ __\r
+// v__ __ BUT DETECTED AS LEFT OF THIS LINE\r
+// _____7\r
+// _____/\r
+// _____/\r
+// In the code below actually D = 0, so segments are nearly-vertical\r
+// Called when the point is on the same level as one of the segment's points\r
+// but the point is not aligned with a vertical segment\r
+template <typename CSTag>\r
+struct winding_side_equal\r
+{\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ CSTag\r
+ >::type strategy_side_type;\r
+\r
+ template <typename Point, typename PointOfSegment>\r
+ static inline int apply(Point const& point,\r
+ PointOfSegment const& se,\r
+ int count)\r
+ {\r
+ typedef typename coordinate_type<PointOfSegment>::type scoord_t;\r
+ typedef typename coordinate_system<PointOfSegment>::type::units units_t;\r
+\r
+ if (math::equals(get<1>(point), get<1>(se)))\r
+ return 0;\r
+\r
+ // Create a horizontal segment intersecting the original segment's endpoint\r
+ // equal to the point, with the derived direction (E/W).\r
+ PointOfSegment ss1, ss2;\r
+ set<1>(ss1, get<1>(se));\r
+ set<0>(ss1, get<0>(se));\r
+ set<1>(ss2, get<1>(se));\r
+ scoord_t ss20 = get<0>(se);\r
+ if (count > 0)\r
+ {\r
+ ss20 += winding_small_angle<PointOfSegment>::apply();\r
+ }\r
+ else\r
+ {\r
+ ss20 -= winding_small_angle<PointOfSegment>::apply();\r
+ }\r
+ math::normalize_longitude<units_t>(ss20);\r
+ set<0>(ss2, ss20);\r
+\r
+ // Check the side using this vertical segment\r
+ return strategy_side_type::apply(ss1, ss2, point);\r
+ }\r
+};\r
+// The optimization for cartesian\r
+template <>\r
+struct winding_side_equal<cartesian_tag>\r
+{\r
+ template <typename Point, typename PointOfSegment>\r
+ static inline int apply(Point const& point,\r
+ PointOfSegment const& se,\r
+ int count)\r
+ {\r
+ // NOTE: for D=0 the signs would be reversed\r
+ return math::equals(get<1>(point), get<1>(se)) ?\r
+ 0 :\r
+ get<1>(point) < get<1>(se) ?\r
+ // assuming count is equal to 1 or -1\r
+ -count : // ( count > 0 ? -1 : 1) :\r
+ count; // ( count > 0 ? 1 : -1) ;\r
+ }\r
+};\r
+\r
+\r
+template <typename Point,\r
+ typename CalculationType,\r
+ typename CSTag = typename cs_tag<Point>::type>\r
+struct winding_check_touch\r
+{\r
+ typedef CalculationType calc_t;\r
+ typedef typename coordinate_system<Point>::type::units units_t;\r
+ typedef math::detail::constants_on_spheroid<CalculationType, units_t> constants;\r
+\r
+ template <typename PointOfSegment, typename State>\r
+ static inline int apply(Point const& point,\r
+ PointOfSegment const& seg1,\r
+ PointOfSegment const& seg2,\r
+ State& state,\r
+ bool& eq1,\r
+ bool& eq2)\r
+ {\r
+ calc_t const pi = constants::half_period();\r
+ calc_t const pi2 = pi / calc_t(2);\r
+\r
+ calc_t const px = get<0>(point);\r
+ calc_t const s1x = get<0>(seg1);\r
+ calc_t const s2x = get<0>(seg2);\r
+ calc_t const py = get<1>(point);\r
+ calc_t const s1y = get<1>(seg1);\r
+ calc_t const s2y = get<1>(seg2);\r
+\r
+ // NOTE: lat in {-90, 90} and arbitrary lon\r
+ // it doesn't matter what lon it is if it's a pole\r
+ // so e.g. if one of the segment endpoints is a pole\r
+ // then only the other lon matters\r
+ \r
+ bool eq1_strict = math::equals(s1x, px);\r
+ bool eq2_strict = math::equals(s2x, px);\r
+\r
+ eq1 = eq1_strict // lon strictly equal to s1\r
+ || math::equals(s1y, pi2) || math::equals(s1y, -pi2); // s1 is pole\r
+ eq2 = eq2_strict // lon strictly equal to s2\r
+ || math::equals(s2y, pi2) || math::equals(s2y, -pi2); // s2 is pole\r
+ \r
+ // segment overlapping pole\r
+ calc_t s1x_anti = s1x + constants::half_period();\r
+ math::normalize_longitude<units_t, calc_t>(s1x_anti);\r
+ bool antipodal = math::equals(s2x, s1x_anti);\r
+ if (antipodal)\r
+ {\r
+ eq1 = eq2 = eq1 || eq2;\r
+\r
+ // segment overlapping pole and point is pole\r
+ if (math::equals(py, pi2) || math::equals(py, -pi2))\r
+ {\r
+ eq1 = eq2 = true;\r
+ }\r
+ }\r
+ \r
+ // Both equal p -> segment vertical\r
+ // The only thing which has to be done is check if point is ON segment\r
+ if (eq1 && eq2)\r
+ {\r
+ // segment endpoints on the same sides of the globe\r
+ if (! antipodal\r
+ // p's lat between segment endpoints' lats\r
+ ? (s1y <= py && s2y >= py) || (s2y <= py && s1y >= py)\r
+ // going through north or south pole?\r
+ : (pi - s1y - s2y <= pi\r
+ ? (eq1_strict && s1y <= py) || (eq2_strict && s2y <= py) // north\r
+ || math::equals(py, pi2) // point on north pole\r
+ : (eq1_strict && s1y >= py) || (eq2_strict && s2y >= py)) // south\r
+ || math::equals(py, -pi2) // point on south pole\r
+ )\r
+ {\r
+ state.m_touches = true;\r
+ }\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+// The optimization for cartesian\r
+template <typename Point, typename CalculationType>\r
+struct winding_check_touch<Point, CalculationType, cartesian_tag>\r
+{\r
+ typedef CalculationType calc_t;\r
+\r
+ template <typename PointOfSegment, typename State>\r
+ static inline bool apply(Point const& point,\r
+ PointOfSegment const& seg1,\r
+ PointOfSegment const& seg2,\r
+ State& state,\r
+ bool& eq1,\r
+ bool& eq2)\r
+ {\r
+ calc_t const px = get<0>(point);\r
+ calc_t const s1x = get<0>(seg1);\r
+ calc_t const s2x = get<0>(seg2);\r
+\r
+ eq1 = math::equals(s1x, px);\r
+ eq2 = math::equals(s2x, px);\r
+\r
+ // Both equal p -> segment vertical\r
+ // The only thing which has to be done is check if point is ON segment\r
+ if (eq1 && eq2)\r
+ {\r
+ calc_t const py = get<1>(point);\r
+ calc_t const s1y = get<1>(seg1);\r
+ calc_t const s2y = get<1>(seg2);\r
+ if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))\r
+ {\r
+ state.m_touches = true;\r
+ }\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+};\r
+\r
+\r
+// Called if point is not aligned with a vertical segment\r
+template <typename Point,\r
+ typename CalculationType,\r
+ typename CSTag = typename cs_tag<Point>::type>\r
+struct winding_calculate_count\r
+{\r
+ typedef CalculationType calc_t;\r
+ typedef typename coordinate_system<Point>::type::units units_t;\r
+\r
+ static inline bool greater(calc_t const& l, calc_t const& r)\r
+ {\r
+ calc_t diff = l - r;\r
+ math::normalize_longitude<units_t, calc_t>(diff);\r
+ return diff > calc_t(0);\r
+ }\r
+\r
+ static inline int apply(calc_t const& p,\r
+ calc_t const& s1, calc_t const& s2,\r
+ bool eq1, bool eq2)\r
+ {\r
+ // Probably could be optimized by avoiding normalization for some comparisons\r
+ // e.g. s1 > p could be calculated from p > s1\r
+\r
+ // If both segment endpoints were poles below checks wouldn't be enough\r
+ // but this means that either both are the same or that they are N/S poles\r
+ // and therefore the segment is not valid.\r
+ // If needed (eq1 && eq2 ? 0) could be returned\r
+\r
+ return\r
+ eq1 ? (greater(s2, p) ? 1 : -1) // Point on level s1, E/W depending on s2\r
+ : eq2 ? (greater(s1, p) ? -1 : 1) // idem\r
+ : greater(p, s1) && greater(s2, p) ? 2 // Point between s1 -> s2 --> E\r
+ : greater(p, s2) && greater(s1, p) ? -2 // Point between s2 -> s1 --> W\r
+ : 0;\r
+ }\r
+};\r
+// The optimization for cartesian\r
+template <typename Point, typename CalculationType>\r
+struct winding_calculate_count<Point, CalculationType, cartesian_tag>\r
+{\r
+ typedef CalculationType calc_t;\r
+ \r
+ static inline int apply(calc_t const& p,\r
+ calc_t const& s1, calc_t const& s2,\r
+ bool eq1, bool eq2)\r
+ {\r
+ return\r
+ eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2\r
+ : eq2 ? (s1 > p ? -1 : 1) // idem\r
+ : s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> E\r
+ : s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> W\r
+ : 0;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+\brief Within detection using winding rule\r
+\ingroup strategies\r
+\tparam Point \tparam_point\r
+\tparam PointOfSegment \tparam_segment_point\r
+\tparam CalculationType \tparam_calculation\r
+\author Barend Gehrels\r
+\note The implementation is inspired by terralib http://www.terralib.org (LGPL)\r
+\note but totally revised afterwards, especially for cases on segments\r
+\note Only dependant on "side", -> agnostic, suitable for spherical/latlong\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]\r
+}\r
+ */\r
+template\r
+<\r
+ typename Point,\r
+ typename PointOfSegment = Point,\r
+ typename CalculationType = void\r
+>\r
+class winding\r
+{\r
+ typedef typename select_calculation_type\r
+ <\r
+ Point,\r
+ PointOfSegment,\r
+ CalculationType\r
+ >::type calculation_type;\r
+\r
+\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ typename cs_tag<Point>::type\r
+ >::type strategy_side_type;\r
+\r
+\r
+ /*! subclass to keep state */\r
+ class counter\r
+ {\r
+ int m_count;\r
+ bool m_touches;\r
+\r
+ inline int code() const\r
+ {\r
+ return m_touches ? 0 : m_count == 0 ? -1 : 1;\r
+ }\r
+\r
+ public :\r
+ friend class winding;\r
+\r
+ template <typename P, typename CT, typename CST>\r
+ friend struct winding_check_touch;\r
+\r
+ inline counter()\r
+ : m_count(0)\r
+ , m_touches(false)\r
+ {}\r
+\r
+ };\r
+\r
+\r
+ static inline int check_segment(Point const& point,\r
+ PointOfSegment const& seg1, PointOfSegment const& seg2,\r
+ counter& state, bool& eq1, bool& eq2)\r
+ {\r
+ if (winding_check_touch<Point, calculation_type>\r
+ ::apply(point, seg1, seg2, state, eq1, eq2))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ calculation_type const p = get<0>(point);\r
+ calculation_type const s1 = get<0>(seg1);\r
+ calculation_type const s2 = get<0>(seg2);\r
+ return winding_calculate_count<Point, calculation_type>\r
+ ::apply(p, s1, s2, eq1, eq2);\r
+ }\r
+\r
+\r
+public :\r
+\r
+ // Typedefs and static methods to fulfill the concept\r
+ typedef Point point_type;\r
+ typedef PointOfSegment segment_point_type;\r
+ typedef counter state_type;\r
+\r
+ static inline bool apply(Point const& point,\r
+ PointOfSegment const& s1, PointOfSegment const& s2,\r
+ counter& state)\r
+ {\r
+ typedef typename cs_tag<Point>::type cs_t;\r
+\r
+ bool eq1 = false;\r
+ bool eq2 = false;\r
+ boost::ignore_unused(eq2);\r
+\r
+ int count = check_segment(point, s1, s2, state, eq1, eq2);\r
+ if (count != 0)\r
+ {\r
+ int side = 0;\r
+ if (count == 1 || count == -1)\r
+ {\r
+ side = winding_side_equal<cs_t>::apply(point, eq1 ? s1 : s2, count);\r
+ }\r
+ else // count == 2 || count == -2\r
+ {\r
+ // 1 left, -1 right\r
+ side = strategy_side_type::apply(s1, s2, point);\r
+ }\r
+ \r
+ if (side == 0)\r
+ {\r
+ // Point is lying on segment\r
+ state.m_touches = true;\r
+ state.m_count = 0;\r
+ return false;\r
+ }\r
+\r
+ // Side is NEG for right, POS for left.\r
+ // The count is -2 for down, 2 for up (or -1/1)\r
+ // Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE\r
+ // See accompagnying figure (TODO)\r
+ if (side * count > 0)\r
+ {\r
+ state.m_count += count;\r
+ }\r
+ }\r
+ return ! state.m_touches;\r
+ }\r
+\r
+ static inline int result(counter const& state)\r
+ {\r
+ return state.code();\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+// Register using "areal_tag" for ring, polygon, multi-polygon\r
+template <typename AnyTag, typename Point, typename Geometry>\r
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>\r
+{\r
+ typedef winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+template <typename AnyTag, typename Point, typename Geometry>\r
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>\r
+{\r
+ typedef winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used\r
+\r
+template <typename Point, typename Geometry, typename AnyTag>\r
+struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, cartesian_tag, cartesian_tag, Point, Geometry>\r
+{\r
+ typedef winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+template <typename Point, typename Geometry, typename AnyTag>\r
+struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, spherical_tag, Point, Geometry>\r
+{\r
+ typedef winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+} // namespace services\r
+\r
+#endif\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace strategy { namespace covered_by { namespace services\r
+{\r
+\r
+// Register using "areal_tag" for ring, polygon, multi-polygon\r
+template <typename AnyTag, typename Point, typename Geometry>\r
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>\r
+{\r
+ typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+template <typename AnyTag, typename Point, typename Geometry>\r
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>\r
+{\r
+ typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+// TODO: use linear_tag and pointlike_tag the same way how areal_tag is used\r
+\r
+template <typename Point, typename Geometry, typename AnyTag>\r
+struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, cartesian_tag, cartesian_tag, Point, Geometry>\r
+{\r
+ typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+template <typename Point, typename Geometry, typename AnyTag>\r
+struct default_strategy<point_tag, AnyTag, point_tag, AnyTag, spherical_tag, spherical_tag, Point, Geometry>\r
+{\r
+ typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;\r
+};\r
+\r
+}}} // namespace strategy::covered_by::services\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP\r
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP\r
+\r
+#include <boost/geometry/algorithms/relate.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace relate\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2, typename StaticMask>\r
+struct relate\r
+{\r
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)\r
+ {\r
+ return geometry::relate(geometry1, geometry2, StaticMask());\r
+ }\r
+};\r
+\r
+} // namespace relate\r
+\r
+namespace within\r
+{\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+\r
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>\r
+struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>\r
+{\r
+ typedef strategy::relate::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename detail::de9im::static_mask_within_type\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ > type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>\r
+struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>\r
+{\r
+ typedef strategy::relate::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename detail::de9im::static_mask_within_type\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ > type;\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+#endif\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace strategy { namespace covered_by { namespace services\r
+{\r
+\r
+\r
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>\r
+struct default_strategy<AnyTag1, AnyTag2, AnyTag1, AnyTag2, AnyCS, AnyCS, Geometry1, Geometry2>\r
+{\r
+ typedef strategy::relate::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename detail::de9im::static_mask_covered_by_type\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ > type;\r
+};\r
+\r
+template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2, typename AnyCS>\r
+struct default_strategy<AnyTag1, AnyTag2, AnyTag1, areal_tag, AnyCS, AnyCS, Geometry1, Geometry2>\r
+{\r
+ typedef strategy::relate::relate\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename detail::de9im::static_mask_covered_by_type\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ > type;\r
+};\r
+\r
+\r
+}}} // namespace strategy::covered_by::services\r
+#endif\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_RELATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 1995, 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 1995 Maarten Hilferink, Amsterdam, the Netherlands\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP\r
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP\r
+\r
+\r
+#include <cstddef>\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+#include <iostream>\r
+#endif\r
+#include <vector>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+#include <boost/geometry/io/dsv/write.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace simplify\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+ /*!\r
+ \brief Small wrapper around a point, with an extra member "included"\r
+ \details\r
+ It has a const-reference to the original point (so no copy here)\r
+ \tparam the enclosed point type\r
+ */\r
+ template<typename Point>\r
+ struct douglas_peucker_point\r
+ {\r
+ Point const& p;\r
+ bool included;\r
+\r
+ inline douglas_peucker_point(Point const& ap)\r
+ : p(ap)\r
+ , included(false)\r
+ {}\r
+\r
+ // Necessary for proper compilation\r
+ inline douglas_peucker_point<Point> operator=(douglas_peucker_point<Point> const& )\r
+ {\r
+ return douglas_peucker_point<Point>(*this);\r
+ }\r
+ };\r
+\r
+ template\r
+ <\r
+ typename Point,\r
+ typename PointDistanceStrategy,\r
+ typename LessCompare\r
+ = std::less\r
+ <\r
+ typename strategy::distance::services::return_type\r
+ <\r
+ PointDistanceStrategy,\r
+ Point, Point\r
+ >::type\r
+ >\r
+ >\r
+ class douglas_peucker\r
+ : LessCompare // for empty base optimization\r
+ {\r
+ public :\r
+\r
+ // See also ticket 5954 https://svn.boost.org/trac/boost/ticket/5954\r
+ // Comparable is currently not possible here because it has to be compared to the squared of max_distance, and more.\r
+ // For now we have to take the real distance.\r
+ typedef PointDistanceStrategy distance_strategy_type;\r
+ // typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type distance_strategy_type;\r
+\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ distance_strategy_type,\r
+ Point, Point\r
+ >::type distance_type;\r
+\r
+ douglas_peucker()\r
+ {}\r
+\r
+ douglas_peucker(LessCompare const& less_compare)\r
+ : LessCompare(less_compare)\r
+ {}\r
+\r
+ private :\r
+ typedef detail::douglas_peucker_point<Point> dp_point_type;\r
+ typedef typename std::vector<dp_point_type>::iterator iterator_type;\r
+\r
+\r
+ LessCompare const& less() const\r
+ {\r
+ return *this;\r
+ }\r
+\r
+ inline void consider(iterator_type begin,\r
+ iterator_type end,\r
+ distance_type const& max_dist,\r
+ int& n,\r
+ distance_strategy_type const& ps_distance_strategy) const\r
+ {\r
+ std::size_t size = end - begin;\r
+\r
+ // size must be at least 3\r
+ // because we want to consider a candidate point in between\r
+ if (size <= 2)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+ if (begin != end)\r
+ {\r
+ std::cout << "ignore between " << dsv(begin->p)\r
+ << " and " << dsv((end - 1)->p)\r
+ << " size=" << size << std::endl;\r
+ }\r
+ std::cout << "return because size=" << size << std::endl;\r
+#endif\r
+ return;\r
+ }\r
+\r
+ iterator_type last = end - 1;\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+ std::cout << "find between " << dsv(begin->p)\r
+ << " and " << dsv(last->p)\r
+ << " size=" << size << std::endl;\r
+#endif\r
+\r
+\r
+ // Find most far point, compare to the current segment\r
+ //geometry::segment<Point const> s(begin->p, last->p);\r
+ distance_type md(-1.0); // any value < 0\r
+ iterator_type candidate;\r
+ for(iterator_type it = begin + 1; it != last; ++it)\r
+ {\r
+ distance_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+ std::cout << "consider " << dsv(it->p)\r
+ << " at " << double(dist)\r
+ << ((dist > max_dist) ? " maybe" : " no")\r
+ << std::endl;\r
+\r
+#endif\r
+ if ( less()(md, dist) )\r
+ {\r
+ md = dist;\r
+ candidate = it;\r
+ }\r
+ }\r
+\r
+ // If a point is found, set the include flag\r
+ // and handle segments in between recursively\r
+ if ( less()(max_dist, md) )\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+ std::cout << "use " << dsv(candidate->p) << std::endl;\r
+#endif\r
+\r
+ candidate->included = true;\r
+ n++;\r
+\r
+ consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);\r
+ consider(candidate, end, max_dist, n, ps_distance_strategy);\r
+ }\r
+ }\r
+\r
+\r
+ public :\r
+\r
+ template <typename Range, typename OutputIterator>\r
+ inline OutputIterator apply(Range const& range,\r
+ OutputIterator out,\r
+ distance_type max_distance) const\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER\r
+ std::cout << "max distance: " << max_distance\r
+ << std::endl << std::endl;\r
+#endif\r
+ distance_strategy_type strategy;\r
+\r
+ // Copy coordinates, a vector of references to all points\r
+ std::vector<dp_point_type> ref_candidates(boost::begin(range),\r
+ boost::end(range));\r
+\r
+ // Include first and last point of line,\r
+ // they are always part of the line\r
+ int n = 2;\r
+ ref_candidates.front().included = true;\r
+ ref_candidates.back().included = true;\r
+\r
+ // Get points, recursively, including them if they are further away\r
+ // than the specified distance\r
+ consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);\r
+\r
+ // Copy included elements to the output\r
+ for(typename std::vector<dp_point_type>::const_iterator it\r
+ = boost::begin(ref_candidates);\r
+ it != boost::end(ref_candidates);\r
+ ++it)\r
+ {\r
+ if (it->included)\r
+ {\r
+ // copy-coordinates does not work because OutputIterator\r
+ // does not model Point (??)\r
+ //geometry::convert(it->p, *out);\r
+ *out = it->p;\r
+ out++;\r
+ }\r
+ }\r
+ return out;\r
+ }\r
+\r
+ };\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Implements the simplify algorithm.\r
+\ingroup strategies\r
+\details The douglas_peucker strategy simplifies a linestring, ring or\r
+ vector of points using the well-known Douglas-Peucker algorithm.\r
+\tparam Point the point type\r
+\tparam PointDistanceStrategy point-segment distance strategy to be used\r
+\note This strategy uses itself a point-segment-distance strategy which\r
+ can be specified\r
+\author Barend and Maarten, 1995/1996\r
+\author Barend, revised for Generic Geometry Library, 2008\r
+*/\r
+\r
+/*\r
+For the algorithm, see for example:\r
+ - http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm\r
+ - http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html\r
+*/\r
+template\r
+<\r
+ typename Point,\r
+ typename PointDistanceStrategy\r
+>\r
+class douglas_peucker\r
+{\r
+public :\r
+\r
+ typedef PointDistanceStrategy distance_strategy_type;\r
+\r
+ typedef typename detail::douglas_peucker\r
+ <\r
+ Point,\r
+ PointDistanceStrategy\r
+ >::distance_type distance_type;\r
+\r
+ template <typename Range, typename OutputIterator>\r
+ static inline OutputIterator apply(Range const& range,\r
+ OutputIterator out,\r
+ distance_type const& max_distance)\r
+ {\r
+ namespace services = strategy::distance::services;\r
+\r
+ typedef typename services::comparable_type\r
+ <\r
+ PointDistanceStrategy\r
+ >::type comparable_distance_strategy_type;\r
+\r
+ return detail::douglas_peucker\r
+ <\r
+ Point, comparable_distance_strategy_type\r
+ >().apply(range, out,\r
+ services::result_from_distance\r
+ <\r
+ comparable_distance_strategy_type, Point, Point\r
+ >::apply(comparable_distance_strategy_type(),\r
+ max_distance)\r
+ );\r
+ }\r
+\r
+};\r
+\r
+}} // namespace strategy::simplify\r
+\r
+\r
+namespace traits {\r
+\r
+template <typename P>\r
+struct point_type<geometry::strategy::simplify::detail::douglas_peucker_point<P> >\r
+{\r
+ typedef P type;\r
+};\r
+\r
+} // namespace traits\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_AREA_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_AREA_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace area { namespace services\r
+{\r
+\r
+/*!\r
+ \brief Traits class binding a default area strategy to a coordinate system\r
+ \ingroup area\r
+ \tparam Tag tag of coordinate system\r
+ \tparam PointOfSegment point-type\r
+*/\r
+template <typename Tag, typename PointOfSegment>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE\r
+ , (types<PointOfSegment>)\r
+ );\r
+};\r
+\r
+\r
+}}} // namespace strategy::area::services\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_AREA_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+/*\r
+\r
+ A Buffer-join strategy gets 4 input points.\r
+ On the two consecutive segments s1 and s2 (joining at vertex v):\r
+\r
+ The lines from parallel at s1, s2 (at buffer-distance) end/start\r
+ in two points perpendicular to the segments: p1 and p2.\r
+ These parallel lines interesct in point ip\r
+\r
+ (s2)\r
+ |\r
+ |\r
+ ^\r
+ |\r
+ (p2) |(v)\r
+ * +----<--- (s1)\r
+\r
+ x(ip) *(p1)\r
+\r
+\r
+ So, in clockwise order:\r
+ v : vertex point\r
+ p1: perpendicular on left side of segment1<1> (perp1)\r
+ ip: intersection point\r
+ p2: perpendicular on left side of segment2<0> (perp2)\r
+*/\r
+\r
+\r
+\r
+/*!\r
+\brief Enumerates options for side of buffer (left/right w.r.t. directed\r
+ segment)\r
+\ingroup enum\r
+\details Around a linestring, a buffer can be defined left or right.\r
+ Around a polygon, assumed clockwise internally,\r
+ a buffer is either on the left side (inflates the polygon), or on the\r
+ right side (deflates the polygon)\r
+*/\r
+enum buffer_side_selector { buffer_side_left, buffer_side_right };\r
+\r
+/*!\r
+\brief Enumerates types of pieces (parts of buffer) around geometries\r
+\ingroup enum\r
+*/\r
+enum piece_type\r
+{\r
+ buffered_segment,\r
+ buffered_join,\r
+ buffered_round_end,\r
+ buffered_flat_end,\r
+ buffered_point,\r
+ buffered_concave, // always on the inside\r
+ piece_type_unknown\r
+};\r
+\r
+\r
+/*!\r
+\brief Enumerates types of joins\r
+\ingroup enum\r
+*/\r
+enum join_selector\r
+{\r
+ join_convex,\r
+ join_concave,\r
+ join_continue, // collinear, next segment touches previous segment\r
+ join_spike // collinear, with overlap, next segment goes back\r
+};\r
+\r
+/*!\r
+\brief Enumerates types of result codes from buffer strategies\r
+\ingroup enum\r
+*/\r
+enum result_code\r
+{\r
+ result_normal,\r
+ result_error_numerical,\r
+ result_no_output\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP\r
+\r
+\r
+#include <boost/mpl/if.hpp>\r
+\r
+//#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace area\r
+{\r
+\r
+/*!\r
+\brief Area calculation for cartesian points\r
+\ingroup strategies\r
+\details Calculates area using the Surveyor's formula, a well-known\r
+ triangulation algorithm\r
+\tparam PointOfSegment \tparam_segment_point\r
+\tparam CalculationType \tparam_calculation\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename PointOfSegment,\r
+ typename CalculationType = void\r
+>\r
+class surveyor\r
+{\r
+public :\r
+ // If user specified a calculation type, use that type,\r
+ // whatever it is and whatever the point-type is.\r
+ // Else, use the pointtype, but at least double\r
+ typedef typename\r
+ boost::mpl::if_c\r
+ <\r
+ boost::is_void<CalculationType>::type::value,\r
+ typename select_most_precise\r
+ <\r
+ typename coordinate_type<PointOfSegment>::type,\r
+ double\r
+ >::type,\r
+ CalculationType\r
+ >::type return_type;\r
+\r
+\r
+private :\r
+\r
+ class summation\r
+ {\r
+ friend class surveyor;\r
+\r
+ return_type sum;\r
+ public :\r
+\r
+ inline summation() : sum(return_type())\r
+ {\r
+ // Strategy supports only 2D areas\r
+ assert_dimension<PointOfSegment, 2>();\r
+ }\r
+ inline return_type area() const\r
+ {\r
+ return_type result = sum;\r
+ return_type const two = 2;\r
+ result /= two;\r
+ return result;\r
+ }\r
+ };\r
+\r
+public :\r
+ typedef summation state_type;\r
+ typedef PointOfSegment segment_point_type;\r
+\r
+ static inline void apply(PointOfSegment const& p1,\r
+ PointOfSegment const& p2,\r
+ summation& state)\r
+ {\r
+ // Below formulas are equivalent, however the two lower ones\r
+ // suffer less from accuracy loss for great values of coordinates.\r
+ // See: https://svn.boost.org/trac/boost/ticket/11928\r
+\r
+ // SUM += x2 * y1 - x1 * y2;\r
+ // state.sum += detail::determinant<return_type>(p2, p1);\r
+\r
+ // SUM += (x2 - x1) * (y2 + y1)\r
+ //state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))\r
+ // * (return_type(get<1>(p2)) + return_type(get<1>(p1)));\r
+\r
+ // SUM += (x1 + x2) * (y1 - y2)\r
+ state.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))\r
+ * (return_type(get<1>(p1)) - return_type(get<1>(p2)));\r
+ }\r
+\r
+ static inline return_type result(summation const& state)\r
+ {\r
+ return state.area();\r
+ }\r
+\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+ template <typename Point>\r
+ struct default_strategy<cartesian_tag, Point>\r
+ {\r
+ typedef strategy::area::surveyor<Point> type;\r
+ };\r
+\r
+} // namespace services\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::area\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2015, 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/strategies/covered_by.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace strategy\r
+{\r
+\r
+\r
+namespace within\r
+{\r
+\r
+\r
+template <typename Geometry, std::size_t Dimension, typename CSTag>\r
+struct box_within_range\r
+{\r
+ template <typename BoxContainedValue, typename BoxContainingValue>\r
+ static inline bool apply(BoxContainedValue const& bed_min,\r
+ BoxContainedValue const& bed_max,\r
+ BoxContainingValue const& bing_min,\r
+ BoxContainingValue const& bing_max)\r
+ {\r
+ return bing_min <= bed_min && bed_max <= bing_max // contained in containing\r
+ && bed_min < bed_max; // interiors overlap\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry, std::size_t Dimension, typename CSTag>\r
+struct box_covered_by_range\r
+{\r
+ template <typename BoxContainedValue, typename BoxContainingValue>\r
+ static inline bool apply(BoxContainedValue const& bed_min,\r
+ BoxContainedValue const& bed_max,\r
+ BoxContainingValue const& bing_min,\r
+ BoxContainingValue const& bing_max)\r
+ {\r
+ return bed_min >= bing_min && bed_max <= bing_max;\r
+ }\r
+};\r
+\r
+\r
+struct box_within_longitude_check\r
+{\r
+ template <typename CalcT>\r
+ static inline bool apply(CalcT const& diff_ed)\r
+ {\r
+ return diff_ed > CalcT(0);\r
+ }\r
+};\r
+\r
+struct box_covered_by_longitude_check\r
+{\r
+ template <typename CalcT>\r
+ static inline bool apply(CalcT const&)\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename Geometry,\r
+ typename InteriorCheck>\r
+struct box_longitude_range\r
+{\r
+ template <typename BoxContainedValue, typename BoxContainingValue>\r
+ static inline bool apply(BoxContainedValue const& bed_min,\r
+ BoxContainedValue const& bed_max,\r
+ BoxContainingValue const& bing_min,\r
+ BoxContainingValue const& bing_max)\r
+ {\r
+ typedef typename select_most_precise\r
+ <\r
+ BoxContainedValue,\r
+ BoxContainingValue\r
+ >::type calc_t;\r
+ typedef typename coordinate_system<Geometry>::type::units units_t;\r
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;\r
+\r
+ // min <= max <=> diff >= 0\r
+ calc_t const diff_ed = bed_max - bed_min;\r
+ calc_t const diff_ing = bing_max - bing_min;\r
+ \r
+ // if containing covers the whole globe it contains all\r
+ if (diff_ing >= constants::period())\r
+ {\r
+ return true;\r
+ }\r
+\r
+ // if containing is smaller it cannot contain\r
+ // and check interior (within vs covered_by)\r
+ if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // calculate positive longitude translation with bing_min as origin\r
+ calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);\r
+\r
+ // max of contained translated into the containing origin must be lesser than max of containing\r
+ return bing_min + diff_min + diff_ed <= bing_max;\r
+ }\r
+};\r
+\r
+\r
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag\r
+template <typename Geometry>\r
+struct box_within_range<Geometry, 0, spherical_tag>\r
+ : box_longitude_range<Geometry, box_within_longitude_check>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct box_covered_by_range<Geometry, 0, spherical_tag>\r
+ : box_longitude_range<Geometry, box_covered_by_longitude_check>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ template <typename, std::size_t, typename> class SubStrategy,\r
+ typename Box1,\r
+ typename Box2,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct relate_box_box_loop\r
+{\r
+ static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)\r
+ {\r
+ assert_dimension_equal<Box1, Box2>();\r
+ typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t;\r
+\r
+ if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(\r
+ get<min_corner, Dimension>(b_contained),\r
+ get<max_corner, Dimension>(b_contained),\r
+ get<min_corner, Dimension>(b_containing),\r
+ get<max_corner, Dimension>(b_containing)\r
+ )\r
+ )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return relate_box_box_loop\r
+ <\r
+ SubStrategy,\r
+ Box1, Box2,\r
+ Dimension + 1, DimensionCount\r
+ >::apply(b_contained, b_containing);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ template <typename, std::size_t, typename> class SubStrategy,\r
+ typename Box1,\r
+ typename Box2,\r
+ std::size_t DimensionCount\r
+>\r
+struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>\r
+{\r
+ static inline bool apply(Box1 const& , Box2 const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Box1,\r
+ typename Box2,\r
+ template <typename, std::size_t, typename> class SubStrategy = box_within_range\r
+>\r
+struct box_in_box\r
+{\r
+ static inline bool apply(Box1 const& box1, Box2 const& box2)\r
+ {\r
+ return relate_box_box_loop\r
+ <\r
+ SubStrategy,\r
+ Box1, Box2, 0, dimension<Box1>::type::value\r
+ >::apply(box1, box2);\r
+ }\r
+};\r
+\r
+\r
+} // namespace within\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+namespace within { namespace services\r
+{\r
+\r
+template <typename BoxContained, typename BoxContaining>\r
+struct default_strategy\r
+ <\r
+ box_tag, box_tag,\r
+ box_tag, areal_tag,\r
+ cartesian_tag, cartesian_tag,\r
+ BoxContained, BoxContaining\r
+ >\r
+{\r
+ typedef within::box_in_box<BoxContained, BoxContaining> type;\r
+};\r
+\r
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag\r
+template <typename BoxContained, typename BoxContaining>\r
+struct default_strategy\r
+ <\r
+ box_tag, box_tag,\r
+ box_tag, areal_tag,\r
+ spherical_tag, spherical_tag,\r
+ BoxContained, BoxContaining\r
+ >\r
+{\r
+ typedef within::box_in_box<BoxContained, BoxContaining> type;\r
+};\r
+\r
+\r
+}} // namespace within::services\r
+\r
+namespace covered_by { namespace services\r
+{\r
+\r
+template <typename BoxContained, typename BoxContaining>\r
+struct default_strategy\r
+ <\r
+ box_tag, box_tag,\r
+ box_tag, areal_tag,\r
+ cartesian_tag, cartesian_tag,\r
+ BoxContained, BoxContaining\r
+ >\r
+{\r
+ typedef within::box_in_box\r
+ <\r
+ BoxContained, BoxContaining,\r
+ within::box_covered_by_range\r
+ > type;\r
+};\r
+\r
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag\r
+template <typename BoxContained, typename BoxContaining>\r
+struct default_strategy\r
+ <\r
+ box_tag, box_tag,\r
+ box_tag, areal_tag,\r
+ spherical_tag, spherical_tag,\r
+ BoxContained, BoxContaining\r
+ >\r
+{\r
+ typedef within::box_in_box\r
+ <\r
+ BoxContained, BoxContaining,\r
+ within::box_covered_by_range\r
+ > type;\r
+};\r
+\r
+\r
+}} // namespace covered_by::services\r
+\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}}} // namespace boost::geometry::strategy\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+\r
+/*!\r
+\brief Let the buffer create flat ends\r
+\ingroup strategies\r
+\details This strategy can be used as EndStrategy for the buffer algorithm.\r
+ It creates a flat end for each linestring-end. It can be applied\r
+ for (multi)linestrings. Also it is applicable for spikes in (multi)polygons.\r
+ This strategy is only applicable for Cartesian coordinate systems.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_end_flat]\r
+[heading Output]\r
+[$img/strategies/buffer_end_flat.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_end_round end_round]\r
+}\r
+ */\r
+class end_flat\r
+{\r
+\r
+public :\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Fills output_range with a flat end\r
+ template <typename Point, typename RangeOut, typename DistanceStrategy>\r
+ inline void apply(Point const& penultimate_point,\r
+ Point const& perp_left_point,\r
+ Point const& ultimate_point,\r
+ Point const& perp_right_point,\r
+ buffer_side_selector side,\r
+ DistanceStrategy const& distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ coordinate_type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);\r
+ promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);\r
+\r
+ bool reversed = (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)\r
+ || (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right)\r
+ ;\r
+ if (reversed)\r
+ {\r
+ range_out.push_back(perp_right_point);\r
+ range_out.push_back(perp_left_point);\r
+ }\r
+ else\r
+ {\r
+ range_out.push_back(perp_left_point);\r
+ range_out.push_back(perp_right_point);\r
+ }\r
+ // Don't add the ultimate_point (endpoint of the linestring).\r
+ // The buffer might be generated completely at one side.\r
+ // In other cases it does no harm but is further useless\r
+ }\r
+\r
+ template <typename NumericType>\r
+ static inline NumericType max_distance(NumericType const& distance)\r
+ {\r
+ return distance;\r
+ }\r
+\r
+ //! Returns the piece_type (flat end)\r
+ static inline piece_type get_piece_type()\r
+ {\r
+ return buffered_flat_end;\r
+ }\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+#include <boost/geometry/io/wkt/wkt.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+\r
+/*!\r
+\brief Let the buffer create rounded ends\r
+\ingroup strategies\r
+\details This strategy can be used as EndStrategy for the buffer algorithm.\r
+ It creates a rounded end for each linestring-end. It can be applied\r
+ for (multi)linestrings. Also it is applicable for spikes in (multi)polygons.\r
+ This strategy is only applicable for Cartesian coordinate systems.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_end_round]\r
+[heading Output]\r
+[$img/strategies/buffer_end_round.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_end_flat end_flat]\r
+}\r
+ */\r
+class end_round\r
+{\r
+private :\r
+ std::size_t m_points_per_circle;\r
+\r
+ template\r
+ <\r
+ typename Point,\r
+ typename PromotedType,\r
+ typename DistanceType,\r
+ typename RangeOut\r
+ >\r
+ inline void generate_points(Point const& point,\r
+ PromotedType alpha, // by value\r
+ DistanceType const& buffer_distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ PromotedType const two_pi = geometry::math::two_pi<PromotedType>();\r
+\r
+ std::size_t point_buffer_count = m_points_per_circle;\r
+\r
+ PromotedType const diff = two_pi / PromotedType(point_buffer_count);\r
+\r
+ // For half circle:\r
+ point_buffer_count /= 2;\r
+ point_buffer_count++;\r
+\r
+ for (std::size_t i = 0; i < point_buffer_count; i++, alpha -= diff)\r
+ {\r
+ typename boost::range_value<RangeOut>::type p;\r
+ set<0>(p, get<0>(point) + buffer_distance * cos(alpha));\r
+ set<1>(p, get<1>(point) + buffer_distance * sin(alpha));\r
+ range_out.push_back(p);\r
+ }\r
+ }\r
+\r
+ template <typename T, typename P1, typename P2>\r
+ static inline T calculate_angle(P1 const& from_point, P2 const& to_point)\r
+ {\r
+ typedef P1 vector_type;\r
+ vector_type v = from_point;\r
+ geometry::subtract_point(v, to_point);\r
+ return atan2(geometry::get<1>(v), geometry::get<0>(v));\r
+ }\r
+\r
+public :\r
+\r
+ //! \brief Constructs the strategy\r
+ //! \param points_per_circle points which would be used for a full circle\r
+ //! (if points_per_circle is smaller than 4, it is internally set to 4)\r
+ explicit inline end_round(std::size_t points_per_circle = 90)\r
+ : m_points_per_circle((points_per_circle < 4u) ? 4u : points_per_circle)\r
+ {}\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+ //! Fills output_range with a flat end\r
+ template <typename Point, typename RangeOut, typename DistanceStrategy>\r
+ inline void apply(Point const& penultimate_point,\r
+ Point const& perp_left_point,\r
+ Point const& ultimate_point,\r
+ Point const& perp_right_point,\r
+ buffer_side_selector side,\r
+ DistanceStrategy const& distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ coordinate_type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ promoted_type const alpha = calculate_angle<promoted_type>(perp_left_point, ultimate_point);\r
+\r
+ promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);\r
+ promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);\r
+ if (geometry::math::equals(dist_left, dist_right))\r
+ {\r
+ generate_points(ultimate_point, alpha, dist_left, range_out);\r
+ }\r
+ else\r
+ {\r
+ promoted_type const two = 2.0;\r
+ promoted_type dist_half_diff = (dist_left - dist_right) / two;\r
+\r
+ if (side == buffer_side_right)\r
+ {\r
+ dist_half_diff = -dist_half_diff;\r
+ }\r
+\r
+ Point shifted_point;\r
+ set<0>(shifted_point, get<0>(ultimate_point) + dist_half_diff * cos(alpha));\r
+ set<1>(shifted_point, get<1>(ultimate_point) + dist_half_diff * sin(alpha));\r
+ generate_points(shifted_point, alpha, (dist_left + dist_right) / two, range_out);\r
+ }\r
+\r
+ if (m_points_per_circle % 2 == 1)\r
+ {\r
+ // For a half circle, if the number of points is not even,\r
+ // we should insert the end point too, to generate a full cap\r
+ range_out.push_back(perp_right_point);\r
+ }\r
+ }\r
+\r
+ template <typename NumericType>\r
+ static inline NumericType max_distance(NumericType const& distance)\r
+ {\r
+ return distance;\r
+ }\r
+\r
+ //! Returns the piece_type (flat end)\r
+ static inline piece_type get_piece_type()\r
+ {\r
+ return buffered_round_end;\r
+ }\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+/*!\r
+\brief Let the buffer create sharp corners\r
+\ingroup strategies\r
+\details This strategy can be used as JoinStrategy for the buffer algorithm.\r
+ It creates a sharp corners around each convex vertex. It can be applied\r
+ for (multi)linestrings and (multi)polygons.\r
+ If corners are sharp by themselves, the miters might become very long. Therefore\r
+ there is a limit (miter_limit), in terms of the used distance, which limits\r
+ their length. The miter is not changed to a bevel form (as done in some\r
+ other software), it is just adapted to the specified miter_limit but keeps\r
+ its miter form.\r
+ If the buffer distance is 5.0, and the miter limit is 2.0, generated points\r
+ will be located at a distance of at most 10.0 (2*5) units.\r
+ This strategy is only applicable for Cartesian coordinate systems.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_join_miter]\r
+[heading Output]\r
+[$img/strategies/buffer_join_miter.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_join_round join_round]\r
+}\r
+ */\r
+class join_miter\r
+{\r
+public:\r
+\r
+ //! \brief Constructs the strategy\r
+ //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners\r
+ explicit inline join_miter(double miter_limit = 5.0)\r
+ : m_miter_limit(valid_limit(miter_limit))\r
+ {}\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Fills output_range with a sharp shape around a vertex\r
+ template <typename Point, typename DistanceType, typename RangeOut>\r
+ inline bool apply(Point const& ip, Point const& vertex,\r
+ Point const& perp1, Point const& perp2,\r
+ DistanceType const& buffer_distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ geometry::equal_to<Point> equals;\r
+ if (equals(ip, vertex))\r
+ {\r
+ return false;\r
+ }\r
+ if (equals(perp1, perp2))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ coordinate_type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ Point p = ip;\r
+\r
+ // Check the distance ip-vertex (= miter distance)\r
+ // (We calculate it manually (not using Pythagoras strategy) to reuse\r
+ // dx and dy)\r
+ coordinate_type const dx = get<0>(p) - get<0>(vertex);\r
+ coordinate_type const dy = get<1>(p) - get<1>(vertex);\r
+\r
+ promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);\r
+\r
+ promoted_type const max_distance\r
+ = m_miter_limit * geometry::math::abs(buffer_distance);\r
+\r
+ if (distance > max_distance)\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(distance != 0.0);\r
+\r
+ promoted_type const proportion = max_distance / distance;\r
+ set<0>(p, get<0>(vertex) + dx * proportion);\r
+ set<1>(p, get<1>(vertex) + dy * proportion);\r
+ }\r
+\r
+ range_out.push_back(perp1);\r
+ range_out.push_back(p);\r
+ range_out.push_back(perp2);\r
+ return true;\r
+ }\r
+\r
+ template <typename NumericType>\r
+ inline NumericType max_distance(NumericType const& distance) const\r
+ {\r
+ return distance * m_miter_limit;\r
+ }\r
+\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+private :\r
+ double valid_limit(double miter_limit) const\r
+ {\r
+ if (miter_limit < 1.0)\r
+ {\r
+ // It should always exceed the buffer distance\r
+ miter_limit = 1.0;\r
+ }\r
+ return miter_limit;\r
+ }\r
+\r
+ double m_miter_limit;\r
+};\r
+\r
+}} // namespace strategy::buffer\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN\r
+#include <iostream>\r
+#include <boost/geometry/io/wkt/wkt.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+/*!\r
+\brief Let the buffer create rounded corners\r
+\ingroup strategies\r
+\details This strategy can be used as JoinStrategy for the buffer algorithm.\r
+ It creates a rounded corners around each convex vertex. It can be applied\r
+ for (multi)linestrings and (multi)polygons.\r
+ This strategy is only applicable for Cartesian coordinate systems.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_join_round]\r
+[heading Output]\r
+[$img/strategies/buffer_join_round.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_join_miter join_miter]\r
+}\r
+ */\r
+class join_round\r
+{\r
+public :\r
+\r
+ //! \brief Constructs the strategy\r
+ //! \param points_per_circle points which would be used for a full circle\r
+ explicit inline join_round(std::size_t points_per_circle = 90)\r
+ : m_points_per_circle(points_per_circle)\r
+ {}\r
+\r
+private :\r
+ template\r
+ <\r
+ typename PromotedType,\r
+ typename Point,\r
+ typename DistanceType,\r
+ typename RangeOut\r
+ >\r
+ inline void generate_points(Point const& vertex,\r
+ Point const& perp1, Point const& perp2,\r
+ DistanceType const& buffer_distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);\r
+ PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);\r
+ PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);\r
+ PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);\r
+\r
+ PromotedType const two_pi = geometry::math::two_pi<PromotedType>();\r
+\r
+ PromotedType const angle1 = atan2(dy1, dx1);\r
+ PromotedType angle2 = atan2(dy2, dx2);\r
+ while (angle2 > angle1)\r
+ {\r
+ angle2 -= two_pi;\r
+ }\r
+ PromotedType const angle_diff = angle1 - angle2;\r
+\r
+ // Divide the angle into an integer amount of steps to make it\r
+ // visually correct also for a low number of points / circle\r
+\r
+ // If a full circle is divided into 3 parts (e.g. angle is 125),\r
+ // the one point in between must still be generated\r
+ // The calculation below:\r
+ // - generates 1 point in between for an angle of 125 based on 3 points\r
+ // - generates 0 points in between for an angle of 90 based on 4 points\r
+\r
+ std::size_t const n = (std::max)(static_cast<std::size_t>(\r
+ ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));\r
+\r
+ PromotedType const diff = angle_diff / static_cast<PromotedType>(n);\r
+ PromotedType a = angle1 - diff;\r
+\r
+ // Walk to n - 1 to avoid generating the last point\r
+ for (std::size_t i = 0; i < n - 1; i++, a -= diff)\r
+ {\r
+ Point p;\r
+ set<0>(p, get<0>(vertex) + buffer_distance * cos(a));\r
+ set<1>(p, get<1>(vertex) + buffer_distance * sin(a));\r
+ range_out.push_back(p);\r
+ }\r
+ }\r
+\r
+public :\r
+\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Fills output_range with a rounded shape around a vertex\r
+ template <typename Point, typename DistanceType, typename RangeOut>\r
+ inline bool apply(Point const& ip, Point const& vertex,\r
+ Point const& perp1, Point const& perp2,\r
+ DistanceType const& buffer_distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+ typedef typename boost::range_value<RangeOut>::type output_point_type;\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ typename geometry::select_most_precise\r
+ <\r
+ coordinate_type,\r
+ typename geometry::coordinate_type<output_point_type>::type\r
+ >::type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ geometry::equal_to<Point> equals;\r
+ if (equals(perp1, perp2))\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN\r
+ std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;\r
+#endif\r
+ return false;\r
+ }\r
+\r
+ // Generate 'vectors'\r
+ coordinate_type vix = (get<0>(ip) - get<0>(vertex));\r
+ coordinate_type viy = (get<1>(ip) - get<1>(vertex));\r
+\r
+ promoted_type length_i = geometry::math::sqrt(vix * vix + viy * viy);\r
+ DistanceType const bd = geometry::math::abs(buffer_distance);\r
+ promoted_type prop = bd / length_i;\r
+\r
+ Point bp;\r
+ set<0>(bp, get<0>(vertex) + vix * prop);\r
+ set<1>(bp, get<1>(vertex) + viy * prop);\r
+\r
+ range_out.push_back(perp1);\r
+ generate_points<promoted_type>(vertex, perp1, perp2, bd, range_out);\r
+ range_out.push_back(perp2);\r
+ return true;\r
+ }\r
+\r
+ template <typename NumericType>\r
+ static inline NumericType max_distance(NumericType const& distance)\r
+ {\r
+ return distance;\r
+ }\r
+\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+private :\r
+ std::size_t m_points_per_circle;\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/policies/compare.hpp>\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN\r
+#include <boost/geometry/io/wkt/wkt.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+\r
+class join_round_by_divide\r
+{\r
+public :\r
+\r
+ inline join_round_by_divide(std::size_t max_level = 4)\r
+ : m_max_level(max_level)\r
+ {}\r
+\r
+ template\r
+ <\r
+ typename PromotedType,\r
+ typename Point,\r
+ typename DistanceType,\r
+ typename RangeOut\r
+ >\r
+ inline void mid_points(Point const& vertex,\r
+ Point const& p1, Point const& p2,\r
+ DistanceType const& buffer_distance,\r
+ RangeOut& range_out,\r
+ std::size_t level = 1) const\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ // Generate 'vectors'\r
+ coordinate_type const vp1_x = get<0>(p1) - get<0>(vertex);\r
+ coordinate_type const vp1_y = get<1>(p1) - get<1>(vertex);\r
+\r
+ coordinate_type const vp2_x = (get<0>(p2) - get<0>(vertex));\r
+ coordinate_type const vp2_y = (get<1>(p2) - get<1>(vertex));\r
+\r
+ // Average them to generate vector in between\r
+ coordinate_type const two = 2;\r
+ coordinate_type const v_x = (vp1_x + vp2_x) / two;\r
+ coordinate_type const v_y = (vp1_y + vp2_y) / two;\r
+\r
+ PromotedType const length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y);\r
+\r
+ PromotedType prop = buffer_distance / length2;\r
+\r
+ Point mid_point;\r
+ set<0>(mid_point, get<0>(vertex) + v_x * prop);\r
+ set<1>(mid_point, get<1>(vertex) + v_y * prop);\r
+\r
+ if (level < m_max_level)\r
+ {\r
+ mid_points<PromotedType>(vertex, p1, mid_point, buffer_distance, range_out, level + 1);\r
+ }\r
+ range_out.push_back(mid_point);\r
+ if (level < m_max_level)\r
+ {\r
+ mid_points<PromotedType>(vertex, mid_point, p2, buffer_distance, range_out, level + 1);\r
+ }\r
+ }\r
+\r
+ template <typename Point, typename DistanceType, typename RangeOut>\r
+ inline bool apply(Point const& ip, Point const& vertex,\r
+ Point const& perp1, Point const& perp2,\r
+ DistanceType const& buffer_distance,\r
+ RangeOut& range_out) const\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ coordinate_type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ geometry::equal_to<Point> equals;\r
+\r
+ if (equals(perp1, perp2))\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN\r
+ std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;\r
+#endif\r
+ return false;\r
+ }\r
+\r
+ // Generate 'vectors'\r
+ coordinate_type const vix = (get<0>(ip) - get<0>(vertex));\r
+ coordinate_type const viy = (get<1>(ip) - get<1>(vertex));\r
+\r
+ promoted_type const length_i = geometry::math::sqrt(vix * vix + viy * viy);\r
+\r
+ promoted_type const bd = geometry::math::abs(buffer_distance);\r
+ promoted_type prop = bd / length_i;\r
+\r
+ Point bp;\r
+ set<0>(bp, get<0>(vertex) + vix * prop);\r
+ set<1>(bp, get<1>(vertex) + viy * prop);\r
+\r
+ range_out.push_back(perp1);\r
+\r
+ if (m_max_level > 1)\r
+ {\r
+ mid_points<promoted_type>(vertex, perp1, bp, bd, range_out);\r
+ range_out.push_back(bp);\r
+ mid_points<promoted_type>(vertex, bp, perp2, bd, range_out);\r
+ }\r
+ else if (m_max_level == 1)\r
+ {\r
+ range_out.push_back(bp);\r
+ }\r
+\r
+ range_out.push_back(perp2);\r
+ return true;\r
+ }\r
+\r
+ template <typename NumericType>\r
+ static inline NumericType max_distance(NumericType const& distance)\r
+ {\r
+ return distance;\r
+ }\r
+\r
+private :\r
+ std::size_t m_max_level;\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+/*!\r
+\brief Create a circular buffer around a point\r
+\ingroup strategies\r
+\details This strategy can be used as PointStrategy for the buffer algorithm.\r
+ It creates a circular buffer around a point. It can be applied\r
+ for points and multi_points, but also for a linestring (if it is degenerate,\r
+ so consisting of only one point) and for polygons (if it is degenerate).\r
+ This strategy is only applicable for Cartesian coordinate systems.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_point_circle]\r
+[heading Output]\r
+[$img/strategies/buffer_point_circle.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_point_square point_square]\r
+}\r
+ */\r
+class point_circle\r
+{\r
+public :\r
+ //! \brief Constructs the strategy\r
+ //! \param count number of points for the created circle (if count\r
+ //! is smaller than 3, count is internally set to 3)\r
+ explicit point_circle(std::size_t count = 90)\r
+ : m_count((count < 3u) ? 3u : count)\r
+ {}\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Fills output_range with a circle around point using distance_strategy\r
+ template\r
+ <\r
+ typename Point,\r
+ typename OutputRange,\r
+ typename DistanceStrategy\r
+ >\r
+ inline void apply(Point const& point,\r
+ DistanceStrategy const& distance_strategy,\r
+ OutputRange& output_range) const\r
+ {\r
+ typedef typename boost::range_value<OutputRange>::type output_point_type;\r
+\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ typename geometry::select_most_precise\r
+ <\r
+ typename geometry::coordinate_type<Point>::type,\r
+ typename geometry::coordinate_type<output_point_type>::type\r
+ >::type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ promoted_type const buffer_distance = distance_strategy.apply(point, point,\r
+ strategy::buffer::buffer_side_left);\r
+\r
+ promoted_type const two_pi = geometry::math::two_pi<promoted_type>();\r
+\r
+ promoted_type const diff = two_pi / promoted_type(m_count);\r
+ promoted_type a = 0;\r
+\r
+ for (std::size_t i = 0; i < m_count; i++, a -= diff)\r
+ {\r
+ output_point_type p;\r
+ set<0>(p, get<0>(point) + buffer_distance * cos(a));\r
+ set<1>(p, get<1>(point) + buffer_distance * sin(a));\r
+ output_range.push_back(p);\r
+ }\r
+\r
+ // Close it:\r
+ output_range.push_back(output_range.front());\r
+ }\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+private :\r
+ std::size_t m_count;\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+/*!\r
+\brief Create a squared form buffer around a point\r
+\ingroup strategies\r
+\details This strategy can be used as PointStrategy for the buffer algorithm.\r
+ It creates a square from each point, where the point lies in the center.\r
+ It can be applied for points and multi_points, but also for a linestring (if it is degenerate,\r
+ so consisting of only one point) and for polygons (if it is degenerate).\r
+ This strategy is only applicable for Cartesian coordinate systems.\r
+\r
+\qbk{\r
+[heading Example]\r
+[buffer_point_square]\r
+[heading Output]\r
+[$img/strategies/buffer_point_square.png]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+\* [link geometry.reference.strategies.strategy_buffer_point_circle point_circle]\r
+}\r
+ */\r
+class point_square\r
+{\r
+ template\r
+ <\r
+ typename Point,\r
+ typename DistanceType,\r
+ typename OutputRange\r
+ >\r
+ inline void add_point(Point const& point,\r
+ DistanceType const& distance,\r
+ DistanceType const& x,\r
+ DistanceType const& y,\r
+ OutputRange& output_range) const\r
+ {\r
+ typename boost::range_value<OutputRange>::type p;\r
+ set<0>(p, get<0>(point) + x * distance);\r
+ set<1>(p, get<1>(point) + y * distance);\r
+ output_range.push_back(p);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename Point,\r
+ typename DistanceType,\r
+ typename OutputRange\r
+ >\r
+ inline void add_points(Point const& point,\r
+ DistanceType const& distance,\r
+ OutputRange& output_range) const\r
+ {\r
+ add_point(point, distance, -1.0, -1.0, output_range);\r
+ add_point(point, distance, -1.0, +1.0, output_range);\r
+ add_point(point, distance, +1.0, +1.0, output_range);\r
+ add_point(point, distance, +1.0, -1.0, output_range);\r
+\r
+ // Close it:\r
+ output_range.push_back(output_range.front());\r
+ }\r
+\r
+public :\r
+\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ //! Fills output_range with a square around point using distance_strategy\r
+ template\r
+ <\r
+ typename Point,\r
+ typename DistanceStrategy,\r
+ typename OutputRange\r
+ >\r
+ inline void apply(Point const& point,\r
+ DistanceStrategy const& distance_strategy,\r
+ OutputRange& output_range) const\r
+ {\r
+ add_points(point, distance_strategy.apply(point, point,\r
+ strategy::buffer::buffer_side_left), output_range);\r
+ }\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace buffer\r
+{\r
+\r
+\r
+\r
+/*!\r
+\brief Let the buffer use straight sides along segments (the default)\r
+\ingroup strategies\r
+\details This strategy can be used as SideStrategy for the buffer algorithm.\r
+ It is currently the only provided strategy for this purpose\r
+\r
+\qbk{\r
+[heading Example]\r
+See the examples for other buffer strategies\, for example\r
+[link geometry.reference.strategies.strategy_buffer_join_round join_round]\r
+[heading See also]\r
+\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]\r
+}\r
+ */\r
+class side_straight\r
+{\r
+public :\r
+#ifndef DOXYGEN_SHOULD_SKIP_THIS\r
+ template\r
+ <\r
+ typename Point,\r
+ typename OutputRange,\r
+ typename DistanceStrategy\r
+ >\r
+ static inline result_code apply(\r
+ Point const& input_p1, Point const& input_p2,\r
+ buffer_side_selector side,\r
+ DistanceStrategy const& distance,\r
+ OutputRange& output_range)\r
+ {\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+ typedef typename geometry::select_most_precise\r
+ <\r
+ coordinate_type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ // Generate a block along (left or right of) the segment\r
+\r
+ // Simulate a vector d (dx,dy)\r
+ coordinate_type const dx = get<0>(input_p2) - get<0>(input_p1);\r
+ coordinate_type const dy = get<1>(input_p2) - get<1>(input_p1);\r
+\r
+ // For normalization [0,1] (=dot product d.d, sqrt)\r
+ promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);\r
+\r
+ if (! boost::math::isfinite(length))\r
+ {\r
+ // In case of coordinates differences of e.g. 1e300, length\r
+ // will overflow and we should not generate output\r
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN\r
+ std::cout << "Error in length calculation for points "\r
+ << geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)\r
+ << " length: " << length << std::endl;\r
+#endif\r
+ return result_error_numerical;\r
+ }\r
+\r
+ if (geometry::math::equals(length, 0))\r
+ {\r
+ // Coordinates are simplified and therefore most often not equal.\r
+ // But if simplify is skipped, or for lines with two\r
+ // equal points, length is 0 and we cannot generate output.\r
+ return result_no_output;\r
+ }\r
+\r
+ promoted_type const d = distance.apply(input_p1, input_p2, side);\r
+\r
+ // Generate the normalized perpendicular p, to the left (ccw)\r
+ promoted_type const px = -dy / length;\r
+ promoted_type const py = dx / length;\r
+\r
+ if (geometry::math::equals(px, 0)\r
+ && geometry::math::equals(py, 0))\r
+ {\r
+ // This basically should not occur - because of the checks above.\r
+ // There are no unit tests triggering this condition\r
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN\r
+ std::cout << "Error in perpendicular calculation for points "\r
+ << geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)\r
+ << " length: " << length\r
+ << " distance: " << d\r
+ << std::endl;\r
+#endif\r
+ return result_no_output;\r
+ }\r
+\r
+ output_range.resize(2);\r
+\r
+ set<0>(output_range.front(), get<0>(input_p1) + px * d);\r
+ set<1>(output_range.front(), get<1>(input_p1) + py * d);\r
+ set<0>(output_range.back(), get<0>(input_p2) + px * d);\r
+ set<1>(output_range.back(), get<1>(input_p2) + py * d);\r
+\r
+ return result_normal;\r
+ }\r
+#endif // DOXYGEN_SHOULD_SKIP_THIS\r
+};\r
+\r
+\r
+}} // namespace strategy::buffer\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.\r
+\r
+// This file was modified by Oracle on 2014, 2016.\r
+// Modifications copyright (c) 2014-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/geometry/core/exception.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>\r
+\r
+#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_values.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_integral.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+// Temporary / will be Strategy as template parameter\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>\r
+\r
+#include <boost/geometry/strategies/side_info.hpp>\r
+#include <boost/geometry/strategies/intersection.hpp>\r
+#include <boost/geometry/strategies/intersection_result.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/robust_point_type.hpp>\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)\r
+# include <boost/geometry/io/wkt/write.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace intersection\r
+{\r
+\r
+\r
+/*!\r
+ \see http://mathworld.wolfram.com/Line-LineIntersection.html\r
+ */\r
+template <typename Policy, typename CalculationType = void>\r
+struct relate_cartesian_segments\r
+{\r
+ typedef typename Policy::return_type return_type;\r
+\r
+ template <typename CoordinateType, typename SegmentRatio>\r
+ struct segment_intersection_info\r
+ {\r
+ typedef typename select_most_precise\r
+ <\r
+ CoordinateType, double\r
+ >::type promoted_type;\r
+\r
+ promoted_type comparable_length_a() const\r
+ {\r
+ return dx_a * dx_a + dy_a * dy_a;\r
+ }\r
+\r
+ promoted_type comparable_length_b() const\r
+ {\r
+ return dx_b * dx_b + dy_b * dy_b;\r
+ }\r
+\r
+ template <typename Point, typename Segment1, typename Segment2>\r
+ void assign_a(Point& point, Segment1 const& a, Segment2 const& ) const\r
+ {\r
+ assign(point, a, dx_a, dy_a, robust_ra);\r
+ }\r
+ template <typename Point, typename Segment1, typename Segment2>\r
+ void assign_b(Point& point, Segment1 const& , Segment2 const& b) const\r
+ {\r
+ assign(point, b, dx_b, dy_b, robust_rb);\r
+ }\r
+\r
+ template <typename Point, typename Segment>\r
+ void assign(Point& point, Segment const& segment, CoordinateType const& dx, CoordinateType const& dy, SegmentRatio const& ratio) const\r
+ {\r
+ // Calculate the intersection point based on segment_ratio\r
+ // Up to now, division was postponed. Here we divide using numerator/\r
+ // denominator. In case of integer this results in an integer\r
+ // division.\r
+ BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);\r
+\r
+ typedef typename promote_integral<CoordinateType>::type promoted_type;\r
+\r
+ promoted_type const numerator\r
+ = boost::numeric_cast<promoted_type>(ratio.numerator());\r
+ promoted_type const denominator\r
+ = boost::numeric_cast<promoted_type>(ratio.denominator());\r
+ promoted_type const dx_promoted = boost::numeric_cast<promoted_type>(dx);\r
+ promoted_type const dy_promoted = boost::numeric_cast<promoted_type>(dy);\r
+\r
+ set<0>(point, get<0, 0>(segment) + boost::numeric_cast\r
+ <\r
+ CoordinateType\r
+ >(numerator * dx_promoted / denominator));\r
+ set<1>(point, get<0, 1>(segment) + boost::numeric_cast\r
+ <\r
+ CoordinateType\r
+ >(numerator * dy_promoted / denominator));\r
+ }\r
+\r
+ CoordinateType dx_a, dy_a;\r
+ CoordinateType dx_b, dy_b;\r
+ SegmentRatio robust_ra;\r
+ SegmentRatio robust_rb;\r
+ };\r
+\r
+ template <typename D, typename W, typename ResultType>\r
+ static inline void cramers_rule(D const& dx_a, D const& dy_a,\r
+ D const& dx_b, D const& dy_b, W const& wx, W const& wy,\r
+ // out:\r
+ ResultType& d, ResultType& da)\r
+ {\r
+ // Cramers rule\r
+ d = geometry::detail::determinant<ResultType>(dx_a, dy_a, dx_b, dy_b);\r
+ da = geometry::detail::determinant<ResultType>(dx_b, dy_b, wx, wy);\r
+ // Ratio is da/d , collinear if d == 0, intersecting if 0 <= r <= 1\r
+ // IntersectionPoint = (x1 + r * dx_a, y1 + r * dy_a)\r
+ }\r
+\r
+\r
+ // Relate segments a and b\r
+ template <typename Segment1, typename Segment2, typename RobustPolicy>\r
+ static inline return_type apply(Segment1 const& a, Segment2 const& b,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ // type them all as in Segment1 - TODO reconsider this, most precise?\r
+ typedef typename geometry::point_type<Segment1>::type point_type;\r
+\r
+ typedef typename geometry::robust_point_type\r
+ <\r
+ point_type, RobustPolicy\r
+ >::type robust_point_type;\r
+\r
+ point_type a0, a1, b0, b1;\r
+ robust_point_type a0_rob, a1_rob, b0_rob, b1_rob;\r
+\r
+ detail::assign_point_from_index<0>(a, a0);\r
+ detail::assign_point_from_index<1>(a, a1);\r
+ detail::assign_point_from_index<0>(b, b0);\r
+ detail::assign_point_from_index<1>(b, b1);\r
+\r
+ geometry::recalculate(a0_rob, a0, robust_policy);\r
+ geometry::recalculate(a1_rob, a1, robust_policy);\r
+ geometry::recalculate(b0_rob, b0, robust_policy);\r
+ geometry::recalculate(b1_rob, b1, robust_policy);\r
+\r
+ return apply(a, b, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);\r
+ }\r
+\r
+ // The main entry-routine, calculating intersections of segments a / b\r
+ // NOTE: Robust* types may be the same as Segments' point types\r
+ template <typename Segment1, typename Segment2,\r
+ typename RobustPolicy,\r
+ typename RobustPoint1, typename RobustPoint2>\r
+ static inline return_type apply(Segment1 const& a, Segment2 const& b,\r
+ RobustPolicy const& /*robust_policy*/,\r
+ RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,\r
+ RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );\r
+\r
+ using geometry::detail::equals::equals_point_point;\r
+ bool const a_is_point = equals_point_point(robust_a1, robust_a2);\r
+ bool const b_is_point = equals_point_point(robust_b1, robust_b2);\r
+\r
+ if(a_is_point && b_is_point)\r
+ {\r
+ return equals_point_point(robust_a1, robust_b2)\r
+ ? Policy::degenerate(a, true)\r
+ : Policy::disjoint()\r
+ ;\r
+ }\r
+\r
+ typedef typename select_calculation_type\r
+ <Segment1, Segment2, CalculationType>::type coordinate_type;\r
+\r
+ typedef side::side_by_triangle<coordinate_type> side;\r
+\r
+ side_info sides;\r
+ sides.set<0>(side::apply(robust_b1, robust_b2, robust_a1),\r
+ side::apply(robust_b1, robust_b2, robust_a2));\r
+\r
+ if (sides.same<0>())\r
+ {\r
+ // Both points are at same side of other segment, we can leave\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ sides.set<1>(side::apply(robust_a1, robust_a2, robust_b1),\r
+ side::apply(robust_a1, robust_a2, robust_b2));\r
+ \r
+ if (sides.same<1>())\r
+ {\r
+ // Both points are at same side of other segment, we can leave\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ bool collinear = sides.collinear();\r
+\r
+ typedef typename select_most_precise\r
+ <\r
+ typename geometry::coordinate_type<RobustPoint1>::type,\r
+ typename geometry::coordinate_type<RobustPoint2>::type\r
+ >::type robust_coordinate_type;\r
+\r
+ typedef typename segment_ratio_type\r
+ <\r
+ typename geometry::point_type<Segment1>::type, // TODO: most precise point?\r
+ RobustPolicy\r
+ >::type ratio_type;\r
+\r
+ segment_intersection_info\r
+ <\r
+ coordinate_type,\r
+ ratio_type\r
+ > sinfo;\r
+\r
+ sinfo.dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir\r
+ sinfo.dx_b = get<1, 0>(b) - get<0, 0>(b);\r
+ sinfo.dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir\r
+ sinfo.dy_b = get<1, 1>(b) - get<0, 1>(b);\r
+\r
+ robust_coordinate_type const robust_dx_a = get<0>(robust_a2) - get<0>(robust_a1);\r
+ robust_coordinate_type const robust_dx_b = get<0>(robust_b2) - get<0>(robust_b1);\r
+ robust_coordinate_type const robust_dy_a = get<1>(robust_a2) - get<1>(robust_a1);\r
+ robust_coordinate_type const robust_dy_b = get<1>(robust_b2) - get<1>(robust_b1);\r
+\r
+ // r: ratio 0-1 where intersection divides A/B\r
+ // (only calculated for non-collinear segments)\r
+ if (! collinear)\r
+ {\r
+ robust_coordinate_type robust_da0, robust_da;\r
+ robust_coordinate_type robust_db0, robust_db;\r
+\r
+ cramers_rule(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b,\r
+ get<0>(robust_a1) - get<0>(robust_b1),\r
+ get<1>(robust_a1) - get<1>(robust_b1),\r
+ robust_da0, robust_da);\r
+\r
+ cramers_rule(robust_dx_b, robust_dy_b, robust_dx_a, robust_dy_a,\r
+ get<0>(robust_b1) - get<0>(robust_a1),\r
+ get<1>(robust_b1) - get<1>(robust_a1),\r
+ robust_db0, robust_db);\r
+\r
+ math::detail::equals_factor_policy<robust_coordinate_type>\r
+ policy(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b);\r
+ robust_coordinate_type const zero = 0;\r
+ if (math::detail::equals_by_policy(robust_da0, zero, policy)\r
+ || math::detail::equals_by_policy(robust_db0, zero, policy))\r
+ {\r
+ // If this is the case, no rescaling is done for FP precision.\r
+ // We set it to collinear, but it indicates a robustness issue.\r
+ sides.set<0>(0,0);\r
+ sides.set<1>(0,0);\r
+ collinear = true;\r
+ }\r
+ else\r
+ {\r
+ sinfo.robust_ra.assign(robust_da, robust_da0);\r
+ sinfo.robust_rb.assign(robust_db, robust_db0);\r
+ }\r
+ }\r
+\r
+ if (collinear)\r
+ {\r
+ std::pair<bool, bool> const collinear_use_first\r
+ = is_x_more_significant(geometry::math::abs(robust_dx_a),\r
+ geometry::math::abs(robust_dy_a),\r
+ geometry::math::abs(robust_dx_b),\r
+ geometry::math::abs(robust_dy_b),\r
+ a_is_point, b_is_point);\r
+\r
+ if (collinear_use_first.second)\r
+ {\r
+ // Degenerate cases: segments of single point, lying on other segment, are not disjoint\r
+ // This situation is collinear too\r
+\r
+ if (collinear_use_first.first)\r
+ {\r
+ return relate_collinear<0, ratio_type>(a, b,\r
+ robust_a1, robust_a2, robust_b1, robust_b2,\r
+ a_is_point, b_is_point);\r
+ }\r
+ else\r
+ {\r
+ // Y direction contains larger segments (maybe dx is zero)\r
+ return relate_collinear<1, ratio_type>(a, b,\r
+ robust_a1, robust_a2, robust_b1, robust_b2,\r
+ a_is_point, b_is_point);\r
+ }\r
+ }\r
+ }\r
+\r
+ return Policy::segments_crosses(sides, sinfo, a, b);\r
+ }\r
+\r
+private:\r
+ // first is true if x is more significant\r
+ // second is true if the more significant difference is not 0\r
+ template <typename RobustCoordinateType>\r
+ static inline std::pair<bool, bool>\r
+ is_x_more_significant(RobustCoordinateType const& abs_robust_dx_a,\r
+ RobustCoordinateType const& abs_robust_dy_a,\r
+ RobustCoordinateType const& abs_robust_dx_b,\r
+ RobustCoordinateType const& abs_robust_dy_b,\r
+ bool const a_is_point,\r
+ bool const b_is_point)\r
+ {\r
+ //BOOST_GEOMETRY_ASSERT_MSG(!(a_is_point && b_is_point), "both segments shouldn't be degenerated");\r
+\r
+ // for degenerated segments the second is always true because this function\r
+ // shouldn't be called if both segments were degenerated\r
+\r
+ if (a_is_point)\r
+ {\r
+ return std::make_pair(abs_robust_dx_b >= abs_robust_dy_b, true);\r
+ }\r
+ else if (b_is_point)\r
+ {\r
+ return std::make_pair(abs_robust_dx_a >= abs_robust_dy_a, true);\r
+ }\r
+ else\r
+ {\r
+ RobustCoordinateType const min_dx = (std::min)(abs_robust_dx_a, abs_robust_dx_b);\r
+ RobustCoordinateType const min_dy = (std::min)(abs_robust_dy_a, abs_robust_dy_b);\r
+ return min_dx == min_dy ?\r
+ std::make_pair(true, min_dx > RobustCoordinateType(0)) :\r
+ std::make_pair(min_dx > min_dy, true);\r
+ }\r
+ }\r
+\r
+ template\r
+ <\r
+ std::size_t Dimension,\r
+ typename RatioType,\r
+ typename Segment1,\r
+ typename Segment2,\r
+ typename RobustPoint1,\r
+ typename RobustPoint2\r
+ >\r
+ static inline return_type relate_collinear(Segment1 const& a,\r
+ Segment2 const& b,\r
+ RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,\r
+ RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,\r
+ bool a_is_point, bool b_is_point)\r
+ {\r
+ if (a_is_point)\r
+ {\r
+ return relate_one_degenerate<RatioType>(a,\r
+ get<Dimension>(robust_a1),\r
+ get<Dimension>(robust_b1), get<Dimension>(robust_b2),\r
+ true);\r
+ }\r
+ if (b_is_point)\r
+ {\r
+ return relate_one_degenerate<RatioType>(b,\r
+ get<Dimension>(robust_b1),\r
+ get<Dimension>(robust_a1), get<Dimension>(robust_a2),\r
+ false);\r
+ }\r
+ return relate_collinear<RatioType>(a, b,\r
+ get<Dimension>(robust_a1),\r
+ get<Dimension>(robust_a2),\r
+ get<Dimension>(robust_b1),\r
+ get<Dimension>(robust_b2));\r
+ }\r
+\r
+ /// Relate segments known collinear\r
+ template\r
+ <\r
+ typename RatioType,\r
+ typename Segment1,\r
+ typename Segment2,\r
+ typename RobustType1,\r
+ typename RobustType2\r
+ >\r
+ static inline return_type relate_collinear(Segment1 const& a\r
+ , Segment2 const& b\r
+ , RobustType1 oa_1, RobustType1 oa_2\r
+ , RobustType2 ob_1, RobustType2 ob_2\r
+ )\r
+ {\r
+ // Calculate the ratios where a starts in b, b starts in a\r
+ // a1--------->a2 (2..7)\r
+ // b1----->b2 (5..8)\r
+ // length_a: 7-2=5\r
+ // length_b: 8-5=3\r
+ // b1 is located w.r.t. a at ratio: (5-2)/5=3/5 (on a)\r
+ // b2 is located w.r.t. a at ratio: (8-2)/5=6/5 (right of a)\r
+ // a1 is located w.r.t. b at ratio: (2-5)/3=-3/3 (left of b)\r
+ // a2 is located w.r.t. b at ratio: (7-5)/3=2/3 (on b)\r
+ // A arrives (a2 on b), B departs (b1 on a)\r
+\r
+ // If both are reversed:\r
+ // a2<---------a1 (7..2)\r
+ // b2<-----b1 (8..5)\r
+ // length_a: 2-7=-5\r
+ // length_b: 5-8=-3\r
+ // b1 is located w.r.t. a at ratio: (8-7)/-5=-1/5 (before a starts)\r
+ // b2 is located w.r.t. a at ratio: (5-7)/-5=2/5 (on a)\r
+ // a1 is located w.r.t. b at ratio: (7-8)/-3=1/3 (on b)\r
+ // a2 is located w.r.t. b at ratio: (2-8)/-3=6/3 (after b ends)\r
+\r
+ // If both one is reversed:\r
+ // a1--------->a2 (2..7)\r
+ // b2<-----b1 (8..5)\r
+ // length_a: 7-2=+5\r
+ // length_b: 5-8=-3\r
+ // b1 is located w.r.t. a at ratio: (8-2)/5=6/5 (after a ends)\r
+ // b2 is located w.r.t. a at ratio: (5-2)/5=3/5 (on a)\r
+ // a1 is located w.r.t. b at ratio: (2-8)/-3=6/3 (after b ends)\r
+ // a2 is located w.r.t. b at ratio: (7-8)/-3=1/3 (on b)\r
+ RobustType1 const length_a = oa_2 - oa_1; // no abs, see above\r
+ RobustType2 const length_b = ob_2 - ob_1;\r
+\r
+ RatioType ra_from(oa_1 - ob_1, length_b);\r
+ RatioType ra_to(oa_2 - ob_1, length_b);\r
+ RatioType rb_from(ob_1 - oa_1, length_a);\r
+ RatioType rb_to(ob_2 - oa_1, length_a);\r
+\r
+ // use absolute measure to detect endpoints intersection\r
+ // NOTE: it'd be possible to calculate bx_wrt_a using ax_wrt_b values\r
+ int const a1_wrt_b = position_value(oa_1, ob_1, ob_2);\r
+ int const a2_wrt_b = position_value(oa_2, ob_1, ob_2);\r
+ int const b1_wrt_a = position_value(ob_1, oa_1, oa_2);\r
+ int const b2_wrt_a = position_value(ob_2, oa_1, oa_2);\r
+ \r
+ // fix the ratios if necessary\r
+ // CONSIDER: fixing ratios also in other cases, if they're inconsistent\r
+ // e.g. if ratio == 1 or 0 (so IP at the endpoint)\r
+ // but position value indicates that the IP is in the middle of the segment\r
+ // because one of the segments is very long\r
+ // In such case the ratios could be moved into the middle direction\r
+ // by some small value (e.g. EPS+1ULP)\r
+ if (a1_wrt_b == 1)\r
+ {\r
+ ra_from.assign(0, 1);\r
+ rb_from.assign(0, 1);\r
+ }\r
+ else if (a1_wrt_b == 3)\r
+ {\r
+ ra_from.assign(1, 1);\r
+ rb_to.assign(0, 1);\r
+ } \r
+\r
+ if (a2_wrt_b == 1)\r
+ {\r
+ ra_to.assign(0, 1);\r
+ rb_from.assign(1, 1);\r
+ }\r
+ else if (a2_wrt_b == 3)\r
+ {\r
+ ra_to.assign(1, 1);\r
+ rb_to.assign(1, 1);\r
+ }\r
+\r
+ if ((a1_wrt_b < 1 && a2_wrt_b < 1) || (a1_wrt_b > 3 && a2_wrt_b > 3))\r
+ //if ((ra_from.left() && ra_to.left()) || (ra_from.right() && ra_to.right()))\r
+ {\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ bool const opposite = math::sign(length_a) != math::sign(length_b);\r
+\r
+ return Policy::segments_collinear(a, b, opposite,\r
+ a1_wrt_b, a2_wrt_b, b1_wrt_a, b2_wrt_a,\r
+ ra_from, ra_to, rb_from, rb_to);\r
+ }\r
+\r
+ /// Relate segments where one is degenerate\r
+ template\r
+ <\r
+ typename RatioType,\r
+ typename DegenerateSegment,\r
+ typename RobustType1,\r
+ typename RobustType2\r
+ >\r
+ static inline return_type relate_one_degenerate(\r
+ DegenerateSegment const& degenerate_segment\r
+ , RobustType1 d\r
+ , RobustType2 s1, RobustType2 s2\r
+ , bool a_degenerate\r
+ )\r
+ {\r
+ // Calculate the ratios where ds starts in s\r
+ // a1--------->a2 (2..6)\r
+ // b1/b2 (4..4)\r
+ // Ratio: (4-2)/(6-2)\r
+ RatioType const ratio(d - s1, s2 - s1);\r
+\r
+ if (!ratio.on_segment())\r
+ {\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ return Policy::one_degenerate(degenerate_segment, ratio, a_degenerate);\r
+ }\r
+\r
+ template <typename ProjCoord1, typename ProjCoord2>\r
+ static inline int position_value(ProjCoord1 const& ca1,\r
+ ProjCoord2 const& cb1,\r
+ ProjCoord2 const& cb2)\r
+ {\r
+ // S1x 0 1 2 3 4\r
+ // S2 |---------->\r
+ return math::equals(ca1, cb1) ? 1\r
+ : math::equals(ca1, cb2) ? 3\r
+ : cb1 < cb2 ?\r
+ ( ca1 < cb1 ? 0\r
+ : ca1 > cb2 ? 4\r
+ : 2 )\r
+ : ( ca1 > cb1 ? 0\r
+ : ca1 < cb2 ? 4\r
+ : 2 );\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename Policy, typename CalculationType>\r
+struct default_strategy<cartesian_tag, Policy, CalculationType>\r
+{\r
+ typedef relate_cartesian_segments<Policy, CalculationType> type;\r
+};\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::intersection\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/strategies/centroid.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace centroid\r
+{\r
+\r
+\r
+/*!\r
+\brief Centroid calculation taking average of points\r
+\ingroup strategies\r
+*/\r
+template\r
+<\r
+ typename PointCentroid,\r
+ typename Point = PointCentroid\r
+>\r
+class average\r
+{\r
+private :\r
+\r
+ /*! subclass to keep state */\r
+ class sum\r
+ {\r
+ friend class average;\r
+ std::size_t count;\r
+ PointCentroid centroid;\r
+\r
+ public :\r
+ inline sum()\r
+ : count(0)\r
+ {\r
+ assign_zero(centroid);\r
+ }\r
+ };\r
+\r
+public :\r
+ typedef sum state_type;\r
+ typedef PointCentroid centroid_point_type;\r
+ typedef Point point_type;\r
+\r
+ static inline void apply(Point const& p, sum& state)\r
+ {\r
+ add_point(state.centroid, p);\r
+ state.count++;\r
+ }\r
+\r
+ static inline bool result(sum const& state, PointCentroid& centroid)\r
+ {\r
+ centroid = state.centroid;\r
+ if ( state.count > 0 )\r
+ {\r
+ divide_value(centroid, state.count);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+namespace services\r
+{\r
+\r
+template <typename Point, std::size_t DimensionCount, typename Geometry>\r
+struct default_strategy\r
+<\r
+ cartesian_tag,\r
+ pointlike_tag,\r
+ DimensionCount,\r
+ Point,\r
+ Geometry\r
+>\r
+{\r
+ typedef average\r
+ <\r
+ Point,\r
+ typename point_type<Geometry>::type\r
+ > type;\r
+};\r
+\r
+} // namespace services\r
+\r
+#endif\r
+\r
+\r
+}} // namespace strategy::centroid\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/strategies/centroid.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Note: when calling the namespace "centroid", it sometimes,\r
+// somehow, in gcc, gives compilation problems (confusion with function centroid).\r
+\r
+namespace strategy { namespace centroid\r
+{\r
+\r
+\r
+\r
+/*!\r
+\brief Centroid calculation using algorithm Bashein / Detmer\r
+\ingroup strategies\r
+\details Calculates centroid using triangulation method published by\r
+ Bashein / Detmer\r
+\tparam Point point type of centroid to calculate\r
+\tparam PointOfSegment point type of segments, defaults to Point\r
+\tparam CalculationType \tparam_calculation\r
+\r
+\author Adapted from "Centroid of a Polygon" by\r
+ Gerard Bashein and Paul R. Detmer<em>,\r
+in "Graphics Gems IV", Academic Press, 1994</em>\r
+\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.centroid.centroid_3_with_strategy centroid (with strategy)]\r
+}\r
+*/\r
+\r
+/*\r
+\par Research notes\r
+The algorithm gives the same results as Oracle and PostGIS but\r
+ differs from MySQL\r
+(tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).\r
+\r
+Without holes:\r
+- this: POINT(4.06923363095238 1.65055803571429)\r
+- geolib: POINT(4.07254 1.66819)\r
+- MySQL: POINT(3.6636363636364 1.6272727272727)'\r
+- PostGIS: POINT(4.06923363095238 1.65055803571429)\r
+- Oracle: 4.06923363095238 1.65055803571429\r
+- SQL Server: POINT(4.06923362245959 1.65055804168294)\r
+\r
+Statements:\r
+- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(\r
+ 'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6\r
+ ,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))')))\r
+- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null,\r
+ sdo_elem_info_array(1, 1003, 1), sdo_ordinate_array(\r
+ 2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3,2.6\r
+ ,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3))\r
+ , mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)\r
+ ,mdsys.sdo_dim_element('y',0,10,.00000005)))\r
+ from dual\r
+- \b SQL Server 2008: select geometry::STGeomFromText(\r
+ 'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6\r
+ ,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))',0)\r
+ .STCentroid()\r
+ .STAsText()\r
+\r
+With holes:\r
+- this: POINT(4.04663 1.6349)\r
+- geolib: POINT(4.04675 1.65735)\r
+- MySQL: POINT(3.6090580503834 1.607573932092)\r
+- PostGIS: POINT(4.0466265060241 1.63489959839357)\r
+- Oracle: 4.0466265060241 1.63489959839357\r
+- SQL Server: POINT(4.0466264962959677 1.6348996057331333)\r
+\r
+Statements:\r
+- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(\r
+ 'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2\r
+ ,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)\r
+ ,(4 2,4.2 1.4,4.8 1.9,4.4 2.2,4 2))')));\r
+- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null\r
+ , sdo_elem_info_array(1, 1003, 1, 25, 2003, 1)\r
+ , sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,\r
+ 2,4.1,3,5.3,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3,4,2, 4.2,1.4,\r
+ 4.8,1.9, 4.4,2.2, 4,2))\r
+ , mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)\r
+ ,mdsys.sdo_dim_element('y',0,10,.00000005)))\r
+ from dual\r
+ */\r
+template\r
+<\r
+ typename Point,\r
+ typename PointOfSegment = Point,\r
+ typename CalculationType = void\r
+>\r
+class bashein_detmer\r
+{\r
+private :\r
+ // If user specified a calculation type, use that type,\r
+ // whatever it is and whatever the point-type(s) are.\r
+ // Else, use the most appropriate coordinate type\r
+ // of the two points, but at least double\r
+ typedef typename\r
+ boost::mpl::if_c\r
+ <\r
+ boost::is_void<CalculationType>::type::value,\r
+ typename select_most_precise\r
+ <\r
+ typename select_coordinate_type\r
+ <\r
+ Point,\r
+ PointOfSegment\r
+ >::type,\r
+ double\r
+ >::type,\r
+ CalculationType\r
+ >::type calculation_type;\r
+\r
+ /*! subclass to keep state */\r
+ class sums\r
+ {\r
+ friend class bashein_detmer;\r
+ std::size_t count;\r
+ calculation_type sum_a2;\r
+ calculation_type sum_x;\r
+ calculation_type sum_y;\r
+\r
+ public :\r
+ inline sums()\r
+ : count(0)\r
+ , sum_a2(calculation_type())\r
+ , sum_x(calculation_type())\r
+ , sum_y(calculation_type())\r
+ {}\r
+ };\r
+\r
+public :\r
+ typedef sums state_type;\r
+\r
+ static inline void apply(PointOfSegment const& p1,\r
+ PointOfSegment const& p2, sums& state)\r
+ {\r
+ /* Algorithm:\r
+ For each segment:\r
+ begin\r
+ ai = x1 * y2 - x2 * y1;\r
+ sum_a2 += ai;\r
+ sum_x += ai * (x1 + x2);\r
+ sum_y += ai * (y1 + y2);\r
+ end\r
+ return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )\r
+ */\r
+\r
+ // Get coordinates and promote them to calculation_type\r
+ calculation_type const x1 = boost::numeric_cast<calculation_type>(get<0>(p1));\r
+ calculation_type const y1 = boost::numeric_cast<calculation_type>(get<1>(p1));\r
+ calculation_type const x2 = boost::numeric_cast<calculation_type>(get<0>(p2));\r
+ calculation_type const y2 = boost::numeric_cast<calculation_type>(get<1>(p2));\r
+ calculation_type const ai = geometry::detail::determinant<calculation_type>(p1, p2);\r
+ state.count++;\r
+ state.sum_a2 += ai;\r
+ state.sum_x += ai * (x1 + x2);\r
+ state.sum_y += ai * (y1 + y2);\r
+ }\r
+\r
+ static inline bool result(sums const& state, Point& centroid)\r
+ {\r
+ calculation_type const zero = calculation_type();\r
+ if (state.count > 0 && ! math::equals(state.sum_a2, zero))\r
+ {\r
+ calculation_type const v3 = 3;\r
+ calculation_type const a3 = v3 * state.sum_a2;\r
+\r
+ typedef typename geometry::coordinate_type\r
+ <\r
+ Point\r
+ >::type coordinate_type;\r
+\r
+ // Prevent NaN centroid coordinates\r
+ if (boost::math::isfinite(a3))\r
+ {\r
+ // NOTE: above calculation_type is checked, not the centroid coordinate_type\r
+ // which means that the centroid can still be filled with INF\r
+ // if e.g. calculation_type is double and centroid contains floats\r
+ set<0>(centroid,\r
+ boost::numeric_cast<coordinate_type>(state.sum_x / a3));\r
+ set<1>(centroid,\r
+ boost::numeric_cast<coordinate_type>(state.sum_y / a3));\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+// Register this strategy for rings and (multi)polygons, in two dimensions\r
+template <typename Point, typename Geometry>\r
+struct default_strategy<cartesian_tag, areal_tag, 2, Point, Geometry>\r
+{\r
+ typedef bashein_detmer\r
+ <\r
+ Point,\r
+ typename point_type<Geometry>::type\r
+ > type;\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::centroid\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP\r
+\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/interface.hpp>\r
+#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/util/for_each_coordinate.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+#include <boost/geometry/strategies/centroid.hpp>\r
+#include <boost/geometry/strategies/default_distance_result.hpp>\r
+\r
+// Helper geometry\r
+#include <boost/geometry/geometries/point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace centroid\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+template <typename Type, std::size_t DimensionCount>\r
+struct weighted_length_sums\r
+{\r
+ typedef typename geometry::model::point\r
+ <\r
+ Type, DimensionCount,\r
+ cs::cartesian\r
+ > work_point;\r
+\r
+ Type length;\r
+ work_point average_sum;\r
+\r
+ inline weighted_length_sums()\r
+ : length(Type())\r
+ {\r
+ geometry::assign_zero(average_sum);\r
+ }\r
+};\r
+}\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename PointOfSegment = Point\r
+>\r
+class weighted_length\r
+{\r
+private :\r
+ typedef typename select_most_precise\r
+ <\r
+ typename default_distance_result<Point>::type,\r
+ typename default_distance_result<PointOfSegment>::type\r
+ >::type distance_type;\r
+\r
+public :\r
+ typedef detail::weighted_length_sums\r
+ <\r
+ distance_type,\r
+ geometry::dimension<Point>::type::value\r
+ > state_type;\r
+\r
+ static inline void apply(PointOfSegment const& p1,\r
+ PointOfSegment const& p2, state_type& state)\r
+ {\r
+ distance_type const d = geometry::distance(p1, p2);\r
+ state.length += d;\r
+\r
+ typename state_type::work_point weighted_median;\r
+ geometry::assign_zero(weighted_median);\r
+ geometry::add_point(weighted_median, p1);\r
+ geometry::add_point(weighted_median, p2);\r
+ geometry::multiply_value(weighted_median, d/2);\r
+ geometry::add_point(state.average_sum, weighted_median);\r
+ }\r
+\r
+ static inline bool result(state_type const& state, Point& centroid)\r
+ {\r
+ distance_type const zero = distance_type();\r
+ if (! geometry::math::equals(state.length, zero)\r
+ && boost::math::isfinite(state.length)) // Prevent NaN centroid coordinates\r
+ {\r
+ // NOTE: above distance_type is checked, not the centroid coordinate_type\r
+ // which means that the centroid can still be filled with INF\r
+ // if e.g. distance_type is double and centroid contains floats\r
+ geometry::for_each_coordinate(centroid, set_sum_div_length(state));\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ struct set_sum_div_length\r
+ {\r
+ state_type const& m_state;\r
+ set_sum_div_length(state_type const& state)\r
+ : m_state(state)\r
+ {}\r
+ template <typename Pt, std::size_t Dimension>\r
+ void apply(Pt & centroid) const\r
+ {\r
+ typedef typename geometry::coordinate_type<Pt>::type coordinate_type;\r
+ geometry::set<Dimension>(\r
+ centroid,\r
+ boost::numeric_cast<coordinate_type>(\r
+ geometry::get<Dimension>(m_state.average_sum) / m_state.length\r
+ )\r
+ );\r
+ }\r
+ };\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+\r
+// Register this strategy for linear geometries, in all dimensions\r
+\r
+template <std::size_t N, typename Point, typename Geometry>\r
+struct default_strategy\r
+<\r
+ cartesian_tag,\r
+ linear_tag,\r
+ N,\r
+ Point,\r
+ Geometry\r
+>\r
+{\r
+ typedef weighted_length\r
+ <\r
+ Point,\r
+ typename point_type<Geometry>::type\r
+ > type;\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::centroid\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/arithmetic/dot_product.hpp>\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/default_distance_result.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>\r
+\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+// Helper geometry (projected point on line)\r
+#include <boost/geometry/geometries/point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+/*!\r
+\brief Strategy for distance point to segment\r
+\ingroup strategies\r
+\details Calculates distance using projected-point method, and (optionally) Pythagoras\r
+\author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm\r
+\tparam CalculationType \tparam_calculation\r
+\tparam Strategy underlying point-point distance strategy\r
+\par Concepts for Strategy:\r
+- cartesian_distance operator(Point,Point)\r
+\note If the Strategy is a "comparable::pythagoras", this strategy\r
+ automatically is a comparable projected_point strategy (so without sqrt)\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename CalculationType = void,\r
+ typename Strategy = pythagoras<CalculationType>\r
+>\r
+class projected_point\r
+{\r
+public :\r
+ // The three typedefs below are necessary to calculate distances\r
+ // from segments defined in integer coordinates.\r
+\r
+ // Integer coordinates can still result in FP distances.\r
+ // There is a division, which must be represented in FP.\r
+ // So promote.\r
+ template <typename Point, typename PointOfSegment>\r
+ struct calculation_type\r
+ : promote_floating_point\r
+ <\r
+ typename strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ Point,\r
+ PointOfSegment\r
+ >::type\r
+ >\r
+ {};\r
+\r
+public :\r
+\r
+ template <typename Point, typename PointOfSegment>\r
+ inline typename calculation_type<Point, PointOfSegment>::type\r
+ apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const\r
+ {\r
+ assert_dimension_equal<Point, PointOfSegment>();\r
+\r
+ typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;\r
+\r
+ // A projected point of points in Integer coordinates must be able to be\r
+ // represented in FP.\r
+ typedef model::point\r
+ <\r
+ calculation_type,\r
+ dimension<PointOfSegment>::value,\r
+ typename coordinate_system<PointOfSegment>::type\r
+ > fp_point_type;\r
+\r
+ // For convenience\r
+ typedef fp_point_type fp_vector_type;\r
+\r
+ /*\r
+ Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]\r
+ VECTOR v(x2 - x1, y2 - y1)\r
+ VECTOR w(px - x1, py - y1)\r
+ c1 = w . v\r
+ c2 = v . v\r
+ b = c1 / c2\r
+ RETURN POINT(x1 + b * vx, y1 + b * vy)\r
+ */\r
+\r
+ // v is multiplied below with a (possibly) FP-value, so should be in FP\r
+ // For consistency we define w also in FP\r
+ fp_vector_type v, w, projected;\r
+\r
+ geometry::convert(p2, v);\r
+ geometry::convert(p, w);\r
+ geometry::convert(p1, projected);\r
+ subtract_point(v, projected);\r
+ subtract_point(w, projected);\r
+\r
+ Strategy strategy;\r
+ boost::ignore_unused_variable_warning(strategy);\r
+\r
+ calculation_type const zero = calculation_type();\r
+ calculation_type const c1 = dot_product(w, v);\r
+ if (c1 <= zero)\r
+ {\r
+ return strategy.apply(p, p1);\r
+ }\r
+ calculation_type const c2 = dot_product(v, v);\r
+ if (c2 <= c1)\r
+ {\r
+ return strategy.apply(p, p2);\r
+ }\r
+\r
+ // See above, c1 > 0 AND c2 > c1 so: c2 != 0\r
+ calculation_type const b = c1 / c2;\r
+\r
+ multiply_value(v, b);\r
+ add_point(projected, v);\r
+\r
+ return strategy.apply(p, projected);\r
+ }\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct tag<projected_point<CalculationType, Strategy> >\r
+{\r
+ typedef strategy_tag_distance_point_segment type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename PS>\r
+struct return_type<projected_point<CalculationType, Strategy>, P, PS>\r
+ : projected_point<CalculationType, Strategy>::template calculation_type<P, PS>\r
+{};\r
+\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct comparable_type<projected_point<CalculationType, Strategy> >\r
+{\r
+ // Define a projected_point strategy with its underlying point-point-strategy\r
+ // being comparable\r
+ typedef projected_point\r
+ <\r
+ CalculationType,\r
+ typename comparable_type<Strategy>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct get_comparable<projected_point<CalculationType, Strategy> >\r
+{\r
+ typedef typename comparable_type\r
+ <\r
+ projected_point<CalculationType, Strategy>\r
+ >::type comparable_type;\r
+public :\r
+ static inline comparable_type apply(projected_point<CalculationType, Strategy> const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename PS>\r
+struct result_from_distance<projected_point<CalculationType, Strategy>, P, PS>\r
+{\r
+private :\r
+ typedef typename return_type<projected_point<CalculationType, Strategy>, P, PS>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(projected_point<CalculationType, Strategy> const& , T const& value)\r
+ {\r
+ Strategy s;\r
+ return result_from_distance<Strategy, P, PS>::apply(s, value);\r
+ }\r
+};\r
+\r
+\r
+// Get default-strategy for point-segment distance calculation\r
+// while still have the possibility to specify point-point distance strategy (PPS)\r
+// It is used in algorithms/distance.hpp where users specify PPS for distance\r
+// of point-to-segment or point-to-linestring.\r
+// Convenient for geographic coordinate systems especially.\r
+template <typename Point, typename PointOfSegment, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ point_tag, segment_tag, Point, PointOfSegment,\r
+ cartesian_tag, cartesian_tag, Strategy\r
+ >\r
+{\r
+ typedef strategy::distance::projected_point\r
+ <\r
+ void,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_void<Strategy>,\r
+ typename default_strategy\r
+ <\r
+ point_tag, point_tag, Point, PointOfSegment,\r
+ cartesian_tag, cartesian_tag\r
+ >::type,\r
+ Strategy\r
+ >::type\r
+ > type;\r
+};\r
+\r
+template <typename PointOfSegment, typename Point, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ segment_tag, point_tag, PointOfSegment, Point,\r
+ cartesian_tag, cartesian_tag, Strategy\r
+ >\r
+{\r
+ typedef typename default_strategy\r
+ <\r
+ point_tag, segment_tag, Point, PointOfSegment,\r
+ cartesian_tag, cartesian_tag, Strategy\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP\r
+\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/arithmetic/dot_product.hpp>\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/default_distance_result.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>\r
+\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+// Helper geometry (projected point on line)\r
+#include <boost/geometry/geometries/point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename T>\r
+struct projected_point_ax_result\r
+{\r
+ typedef T value_type;\r
+\r
+ projected_point_ax_result(T const& c = T(0))\r
+ : atd(c), xtd(c)\r
+ {}\r
+\r
+ projected_point_ax_result(T const& a, T const& x)\r
+ : atd(a), xtd(x)\r
+ {}\r
+\r
+ friend inline bool operator<(projected_point_ax_result const& left,\r
+ projected_point_ax_result const& right)\r
+ {\r
+ return left.xtd < right.xtd || left.atd < right.atd;\r
+ }\r
+\r
+ T atd, xtd;\r
+};\r
+\r
+// This less-comparator may be used as a parameter of detail::douglas_peucker.\r
+// In this simplify strategy distances are compared in 2 places\r
+// 1. to choose the furthest candidate (md < dist)\r
+// 2. to check if the candidate is further than max_distance (max_distance < md)\r
+template <typename Distance>\r
+class projected_point_ax_less\r
+{\r
+public:\r
+ projected_point_ax_less(Distance const& max_distance)\r
+ : m_max_distance(max_distance)\r
+ {}\r
+\r
+ inline bool operator()(Distance const& left, Distance const& right) const\r
+ {\r
+ //return left.xtd < right.xtd && right.atd < m_max_distance.atd;\r
+\r
+ typedef typename Distance::value_type value_type;\r
+\r
+ value_type const lx = left.xtd > m_max_distance.xtd ? left.xtd - m_max_distance.xtd : 0;\r
+ value_type const rx = right.xtd > m_max_distance.xtd ? right.xtd - m_max_distance.xtd : 0;\r
+ value_type const la = left.atd > m_max_distance.atd ? left.atd - m_max_distance.atd : 0;\r
+ value_type const ra = right.atd > m_max_distance.atd ? right.atd - m_max_distance.atd : 0;\r
+\r
+ value_type const l = (std::max)(lx, la);\r
+ value_type const r = (std::max)(rx, ra);\r
+\r
+ return l < r;\r
+ }\r
+private:\r
+ Distance const& m_max_distance;\r
+};\r
+\r
+// This strategy returns 2-component Point/Segment distance.\r
+// The ATD (along track distance) is parallel to the Segment\r
+// and is a distance between Point projected into a line defined by a Segment and the nearest Segment's endpoint.\r
+// If the projected Point intersects the Segment the ATD is equal to 0.\r
+// The XTD (cross track distance) is perpendicular to the Segment\r
+// and is a distance between input Point and its projection.\r
+// If the Segment has length equal to 0, ATD and XTD has value equal\r
+// to the distance between the input Point and one of the Segment's endpoints.\r
+//\r
+// p3 p4\r
+// ^ 7\r
+// | /\r
+// p1<-----e========e----->p2\r
+//\r
+// p1: atd=D, xtd=0\r
+// p2: atd=D, xtd=0\r
+// p3: atd=0, xtd=D\r
+// p4: atd=D/2, xtd=D\r
+template\r
+<\r
+ typename CalculationType = void,\r
+ typename Strategy = pythagoras<CalculationType>\r
+>\r
+class projected_point_ax\r
+{\r
+public :\r
+ template <typename Point, typename PointOfSegment>\r
+ struct calculation_type\r
+ : public projected_point<CalculationType, Strategy>\r
+ ::template calculation_type<Point, PointOfSegment>\r
+ {};\r
+\r
+ template <typename Point, typename PointOfSegment>\r
+ struct result_type\r
+ {\r
+ typedef projected_point_ax_result\r
+ <\r
+ typename calculation_type<Point, PointOfSegment>::type\r
+ > type;\r
+ };\r
+\r
+public :\r
+\r
+ template <typename Point, typename PointOfSegment>\r
+ inline typename result_type<Point, PointOfSegment>::type\r
+ apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const\r
+ {\r
+ assert_dimension_equal<Point, PointOfSegment>();\r
+\r
+ typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;\r
+\r
+ // A projected point of points in Integer coordinates must be able to be\r
+ // represented in FP.\r
+ typedef model::point\r
+ <\r
+ calculation_type,\r
+ dimension<PointOfSegment>::value,\r
+ typename coordinate_system<PointOfSegment>::type\r
+ > fp_point_type;\r
+\r
+ // For convenience\r
+ typedef fp_point_type fp_vector_type;\r
+\r
+ /*\r
+ Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]\r
+ VECTOR v(x2 - x1, y2 - y1)\r
+ VECTOR w(px - x1, py - y1)\r
+ c1 = w . v\r
+ c2 = v . v\r
+ b = c1 / c2\r
+ RETURN POINT(x1 + b * vx, y1 + b * vy)\r
+ */\r
+\r
+ // v is multiplied below with a (possibly) FP-value, so should be in FP\r
+ // For consistency we define w also in FP\r
+ fp_vector_type v, w, projected;\r
+\r
+ geometry::convert(p2, v);\r
+ geometry::convert(p, w);\r
+ geometry::convert(p1, projected);\r
+ subtract_point(v, projected);\r
+ subtract_point(w, projected);\r
+\r
+ Strategy strategy;\r
+ boost::ignore_unused_variable_warning(strategy);\r
+\r
+ typename result_type<Point, PointOfSegment>::type result;\r
+\r
+ calculation_type const zero = calculation_type();\r
+ calculation_type const c2 = dot_product(v, v);\r
+ if ( math::equals(c2, zero) )\r
+ {\r
+ result.xtd = strategy.apply(p, projected);\r
+ // assume that the 0-length segment is perpendicular to the Pt->ProjPt vector\r
+ result.atd = 0;\r
+ return result;\r
+ }\r
+\r
+ calculation_type const c1 = dot_product(w, v);\r
+ calculation_type const b = c1 / c2;\r
+ multiply_value(v, b);\r
+ add_point(projected, v);\r
+\r
+ result.xtd = strategy.apply(p, projected);\r
+\r
+ if (c1 <= zero)\r
+ {\r
+ result.atd = strategy.apply(p1, projected);\r
+ }\r
+ else if (c2 <= c1)\r
+ {\r
+ result.atd = strategy.apply(p2, projected);\r
+ }\r
+ else\r
+ {\r
+ result.atd = 0;\r
+ }\r
+\r
+ return result;\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct tag<detail::projected_point_ax<CalculationType, Strategy> >\r
+{\r
+ typedef strategy_tag_distance_point_segment type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename PS>\r
+struct return_type<detail::projected_point_ax<CalculationType, Strategy>, P, PS>\r
+{\r
+ typedef typename detail::projected_point_ax<CalculationType, Strategy>\r
+ ::template result_type<P, PS>::type type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct comparable_type<detail::projected_point_ax<CalculationType, Strategy> >\r
+{\r
+ // Define a projected_point strategy with its underlying point-point-strategy\r
+ // being comparable\r
+ typedef detail::projected_point_ax\r
+ <\r
+ CalculationType,\r
+ typename comparable_type<Strategy>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct get_comparable<detail::projected_point_ax<CalculationType, Strategy> >\r
+{\r
+ typedef typename comparable_type\r
+ <\r
+ detail::projected_point_ax<CalculationType, Strategy>\r
+ >::type comparable_type;\r
+public :\r
+ static inline comparable_type apply(detail::projected_point_ax<CalculationType, Strategy> const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename PS>\r
+struct result_from_distance<detail::projected_point_ax<CalculationType, Strategy>, P, PS>\r
+{\r
+private :\r
+ typedef typename return_type<detail::projected_point_ax<CalculationType, Strategy>, P, PS>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(detail::projected_point_ax<CalculationType, Strategy> const& , T const& value)\r
+ {\r
+ Strategy s;\r
+ return_type ret;\r
+ ret.atd = result_from_distance<Strategy, P, PS>::apply(s, value.atd);\r
+ ret.xtd = result_from_distance<Strategy, P, PS>::apply(s, value.xtd);\r
+ return ret;\r
+ }\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/calculation_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <size_t I, typename T>\r
+struct compute_pythagoras\r
+{\r
+ template <typename Point1, typename Point2>\r
+ static inline T apply(Point1 const& p1, Point2 const& p2)\r
+ {\r
+ T const c1 = boost::numeric_cast<T>(get<I-1>(p1));\r
+ T const c2 = boost::numeric_cast<T>(get<I-1>(p2));\r
+ T const d = c1 - c2;\r
+ return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct compute_pythagoras<0, T>\r
+{\r
+ template <typename Point1, typename Point2>\r
+ static inline T apply(Point1 const&, Point2 const&)\r
+ {\r
+ return boost::numeric_cast<T>(0);\r
+ }\r
+};\r
+\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+namespace comparable\r
+{\r
+\r
+/*!\r
+\brief Strategy to calculate comparable distance between two points\r
+\ingroup strategies\r
+\tparam Point1 \tparam_first_point\r
+\tparam Point2 \tparam_second_point\r
+\tparam CalculationType \tparam_calculation\r
+*/\r
+template <typename CalculationType = void>\r
+class pythagoras\r
+{\r
+public :\r
+\r
+ template <typename Point1, typename Point2>\r
+ struct calculation_type\r
+ : util::calculation_type::geometric::binary\r
+ <\r
+ Point1,\r
+ Point2,\r
+ CalculationType,\r
+ double,\r
+ double\r
+ >\r
+ {};\r
+\r
+ template <typename Point1, typename Point2>\r
+ static inline typename calculation_type<Point1, Point2>::type\r
+ apply(Point1 const& p1, Point2 const& p2)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );\r
+\r
+ // Calculate distance using Pythagoras\r
+ // (Leave comment above for Doxygen)\r
+\r
+ assert_dimension_equal<Point1, Point2>();\r
+\r
+ return detail::compute_pythagoras\r
+ <\r
+ dimension<Point1>::value,\r
+ typename calculation_type<Point1, Point2>::type\r
+ >::apply(p1, p2);\r
+ }\r
+};\r
+\r
+} // namespace comparable\r
+\r
+\r
+/*!\r
+\brief Strategy to calculate the distance between two points\r
+\ingroup strategies\r
+\tparam CalculationType \tparam_calculation\r
+\r
+\qbk{\r
+[heading Notes]\r
+[note Can be used for points with two\, three or more dimensions]\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename CalculationType = void\r
+>\r
+class pythagoras\r
+{\r
+public :\r
+\r
+ template <typename P1, typename P2>\r
+ struct calculation_type\r
+ : util::calculation_type::geometric::binary\r
+ <\r
+ P1,\r
+ P2,\r
+ CalculationType,\r
+ double,\r
+ double // promote integer to double\r
+ >\r
+ {};\r
+\r
+ /*!\r
+ \brief applies the distance calculation using pythagoras\r
+ \return the calculated distance (including taking the square root)\r
+ \param p1 first point\r
+ \param p2 second point\r
+ */\r
+ template <typename P1, typename P2>\r
+ static inline typename calculation_type<P1, P2>::type\r
+ apply(P1 const& p1, P2 const& p2)\r
+ {\r
+ // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call\r
+ return math::sqrt\r
+ (\r
+ boost::numeric_cast<typename calculation_type<P1, P2>::type>\r
+ (\r
+ comparable::pythagoras<CalculationType>::apply(p1, p2)\r
+ )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType>\r
+struct tag<pythagoras<CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename P1, typename P2>\r
+struct return_type<distance::pythagoras<CalculationType>, P1, P2>\r
+ : pythagoras<CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+template <typename CalculationType>\r
+struct comparable_type<pythagoras<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras<CalculationType> type;\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+struct get_comparable<pythagoras<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras<CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type apply(pythagoras<CalculationType> const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Point1, typename Point2>\r
+struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>\r
+{\r
+private :\r
+ typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(pythagoras<CalculationType> const& , T const& value)\r
+ {\r
+ return return_type(value);\r
+ }\r
+};\r
+\r
+\r
+// Specializations for comparable::pythagoras\r
+template <typename CalculationType>\r
+struct tag<comparable::pythagoras<CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename P1, typename P2>\r
+struct return_type<comparable::pythagoras<CalculationType>, P1, P2>\r
+ : comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+\r
+\r
+template <typename CalculationType>\r
+struct comparable_type<comparable::pythagoras<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras<CalculationType> type;\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+struct get_comparable<comparable::pythagoras<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras<CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Point1, typename Point2>\r
+struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>\r
+{\r
+private :\r
+ typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)\r
+ {\r
+ return_type const v = value;\r
+ return v * v;\r
+ }\r
+};\r
+\r
+\r
+template <typename Point1, typename Point2>\r
+struct default_strategy\r
+ <\r
+ point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag\r
+ >\r
+{\r
+ typedef pythagoras<> type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/calculation_type.hpp>\r
+\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <std::size_t I>\r
+struct compute_pythagoras_box_box\r
+{\r
+ template <typename Box1, typename Box2, typename T>\r
+ static inline void apply(Box1 const& box1, Box2 const& box2, T& result)\r
+ {\r
+ T const b1_min_coord =\r
+ boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box1));\r
+ T const b1_max_coord =\r
+ boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box1));\r
+\r
+ T const b2_min_coord =\r
+ boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box2));\r
+ T const b2_max_coord =\r
+ boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box2));\r
+\r
+ if ( b1_max_coord < b2_min_coord )\r
+ {\r
+ T diff = b2_min_coord - b1_max_coord;\r
+ result += diff * diff;\r
+ }\r
+ if ( b1_min_coord > b2_max_coord )\r
+ {\r
+ T diff = b1_min_coord - b2_max_coord;\r
+ result += diff * diff;\r
+ }\r
+\r
+ compute_pythagoras_box_box<I-1>::apply(box1, box2, result);\r
+ }\r
+};\r
+\r
+template <>\r
+struct compute_pythagoras_box_box<0>\r
+{\r
+ template <typename Box1, typename Box2, typename T>\r
+ static inline void apply(Box1 const&, Box2 const&, T&)\r
+ {\r
+ }\r
+};\r
+\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+namespace comparable\r
+{\r
+\r
+/*!\r
+\brief Strategy to calculate comparable distance between two boxes\r
+\ingroup strategies\r
+\tparam Box1 \tparam_first_box\r
+\tparam Box2 \tparam_second_box\r
+\tparam CalculationType \tparam_calculation\r
+*/\r
+template <typename CalculationType = void>\r
+class pythagoras_box_box\r
+{\r
+public :\r
+\r
+ template <typename Box1, typename Box2>\r
+ struct calculation_type\r
+ {\r
+ typedef typename util::calculation_type::geometric::binary\r
+ <\r
+ Box1,\r
+ Box2,\r
+ CalculationType\r
+ >::type type;\r
+ };\r
+\r
+ template <typename Box1, typename Box2>\r
+ static inline typename calculation_type<Box1, Box2>::type\r
+ apply(Box1 const& box1, Box2 const& box2)\r
+ {\r
+ BOOST_CONCEPT_ASSERT\r
+ ( (concepts::ConstPoint<typename point_type<Box1>::type>) );\r
+ BOOST_CONCEPT_ASSERT\r
+ ( (concepts::ConstPoint<typename point_type<Box2>::type>) );\r
+\r
+ // Calculate distance using Pythagoras\r
+ // (Leave comment above for Doxygen)\r
+\r
+ assert_dimension_equal<Box1, Box2>();\r
+\r
+ typename calculation_type<Box1, Box2>::type result(0);\r
+ \r
+ detail::compute_pythagoras_box_box\r
+ <\r
+ dimension<Box1>::value\r
+ >::apply(box1, box2, result);\r
+\r
+ return result;\r
+ }\r
+};\r
+\r
+} // namespace comparable\r
+\r
+\r
+/*!\r
+\brief Strategy to calculate the distance between two boxes\r
+\ingroup strategies\r
+\tparam CalculationType \tparam_calculation\r
+\r
+\qbk{\r
+[heading Notes]\r
+[note Can be used for boxes with two\, three or more dimensions]\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename CalculationType = void\r
+>\r
+class pythagoras_box_box\r
+{\r
+public :\r
+\r
+ template <typename Box1, typename Box2>\r
+ struct calculation_type\r
+ : util::calculation_type::geometric::binary\r
+ <\r
+ Box1,\r
+ Box2,\r
+ CalculationType,\r
+ double,\r
+ double // promote integer to double\r
+ >\r
+ {};\r
+\r
+ /*!\r
+ \brief applies the distance calculation using pythagoras_box_box\r
+ \return the calculated distance (including taking the square root)\r
+ \param box1 first box\r
+ \param box2 second box\r
+ */\r
+ template <typename Box1, typename Box2>\r
+ static inline typename calculation_type<Box1, Box2>::type\r
+ apply(Box1 const& box1, Box2 const& box2)\r
+ {\r
+ // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call\r
+ return math::sqrt\r
+ (\r
+ boost::numeric_cast<typename calculation_type\r
+ <\r
+ Box1, Box2\r
+ >::type>\r
+ (\r
+ comparable::pythagoras_box_box\r
+ <\r
+ CalculationType\r
+ >::apply(box1, box2)\r
+ )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType>\r
+struct tag<pythagoras_box_box<CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_box_box type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Box1, typename Box2>\r
+struct return_type<distance::pythagoras_box_box<CalculationType>, Box1, Box2>\r
+ : pythagoras_box_box<CalculationType>::template calculation_type<Box1, Box2>\r
+{};\r
+\r
+\r
+template <typename CalculationType>\r
+struct comparable_type<pythagoras_box_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_box_box<CalculationType> type;\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+struct get_comparable<pythagoras_box_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_box_box<CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type\r
+ apply(pythagoras_box_box<CalculationType> const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Box1, typename Box2>\r
+struct result_from_distance<pythagoras_box_box<CalculationType>, Box1, Box2>\r
+{\r
+private:\r
+ typedef typename return_type\r
+ <\r
+ pythagoras_box_box<CalculationType>, Box1, Box2\r
+ >::type return_type;\r
+public:\r
+ template <typename T>\r
+ static inline return_type\r
+ apply(pythagoras_box_box<CalculationType> const& , T const& value)\r
+ {\r
+ return return_type(value);\r
+ }\r
+};\r
+\r
+\r
+// Specializations for comparable::pythagoras_box_box\r
+template <typename CalculationType>\r
+struct tag<comparable::pythagoras_box_box<CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_box_box type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Box1, typename Box2>\r
+struct return_type<comparable::pythagoras_box_box<CalculationType>, Box1, Box2>\r
+ : comparable::pythagoras_box_box\r
+ <\r
+ CalculationType\r
+ >::template calculation_type<Box1, Box2>\r
+{};\r
+\r
+\r
+\r
+\r
+template <typename CalculationType>\r
+struct comparable_type<comparable::pythagoras_box_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_box_box<CalculationType> type;\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+struct get_comparable<comparable::pythagoras_box_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_box_box<CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type apply(comparable_type const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Box1, typename Box2>\r
+struct result_from_distance\r
+ <\r
+ comparable::pythagoras_box_box<CalculationType>, Box1, Box2\r
+ >\r
+{\r
+private :\r
+ typedef typename return_type\r
+ <\r
+ comparable::pythagoras_box_box<CalculationType>, Box1, Box2\r
+ >::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type\r
+ apply(comparable::pythagoras_box_box<CalculationType> const&,\r
+ T const& value)\r
+ {\r
+ return_type const v = value;\r
+ return v * v;\r
+ }\r
+};\r
+\r
+\r
+template <typename BoxPoint1, typename BoxPoint2>\r
+struct default_strategy\r
+ <\r
+ box_tag, box_tag, BoxPoint1, BoxPoint2, cartesian_tag, cartesian_tag\r
+ >\r
+{\r
+ typedef pythagoras_box_box<> type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/calculation_type.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <size_t I>\r
+struct compute_pythagoras_point_box\r
+{\r
+ template <typename Point, typename Box, typename T>\r
+ static inline void apply(Point const& point, Box const& box, T& result)\r
+ {\r
+ T const p_coord = boost::numeric_cast<T>(geometry::get<I-1>(point));\r
+ T const b_min_coord =\r
+ boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box));\r
+ T const b_max_coord =\r
+ boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box));\r
+\r
+ if ( p_coord < b_min_coord )\r
+ {\r
+ T diff = b_min_coord - p_coord;\r
+ result += diff * diff;\r
+ }\r
+ if ( p_coord > b_max_coord )\r
+ {\r
+ T diff = p_coord - b_max_coord;\r
+ result += diff * diff;\r
+ }\r
+\r
+ compute_pythagoras_point_box<I-1>::apply(point, box, result);\r
+ }\r
+};\r
+\r
+template <>\r
+struct compute_pythagoras_point_box<0>\r
+{\r
+ template <typename Point, typename Box, typename T>\r
+ static inline void apply(Point const&, Box const&, T&)\r
+ {\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+namespace comparable\r
+{\r
+\r
+/*!\r
+ \brief Strategy to calculate comparable distance between a point\r
+ and a box\r
+ \ingroup strategies\r
+ \tparam Point \tparam_first_point\r
+ \tparam Box \tparam_second_box\r
+ \tparam CalculationType \tparam_calculation\r
+*/\r
+template <typename CalculationType = void>\r
+class pythagoras_point_box\r
+{\r
+public :\r
+\r
+ template <typename Point, typename Box>\r
+ struct calculation_type\r
+ {\r
+ typedef typename util::calculation_type::geometric::binary\r
+ <\r
+ Point, Box, CalculationType\r
+ >::type type;\r
+ };\r
+\r
+ template <typename Point, typename Box>\r
+ static inline typename calculation_type<Point, Box>::type\r
+ apply(Point const& point, Box const& box)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point>) );\r
+ BOOST_CONCEPT_ASSERT\r
+ ( (concepts::ConstPoint<typename point_type<Box>::type>) );\r
+\r
+ // Calculate distance using Pythagoras\r
+ // (Leave comment above for Doxygen)\r
+\r
+ assert_dimension_equal<Point, Box>();\r
+\r
+ typename calculation_type<Point, Box>::type result(0);\r
+ \r
+ detail::compute_pythagoras_point_box\r
+ <\r
+ dimension<Point>::value\r
+ >::apply(point, box, result);\r
+\r
+ return result;\r
+ }\r
+};\r
+\r
+} // namespace comparable\r
+\r
+\r
+/*!\r
+\brief Strategy to calculate the distance between a point and a box\r
+\ingroup strategies\r
+\tparam CalculationType \tparam_calculation\r
+\r
+\qbk{\r
+[heading Notes]\r
+[note Can be used for points and boxes with two\, three or more dimensions]\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename CalculationType = void\r
+>\r
+class pythagoras_point_box\r
+{\r
+public :\r
+\r
+ template <typename Point, typename Box>\r
+ struct calculation_type\r
+ : util::calculation_type::geometric::binary\r
+ <\r
+ Point,\r
+ Box,\r
+ CalculationType,\r
+ double,\r
+ double // promote integer to double\r
+ >\r
+ {};\r
+\r
+ /*!\r
+ \brief applies the distance calculation using pythagoras\r
+ \return the calculated distance (including taking the square root)\r
+ \param point point\r
+ \param box box\r
+ */\r
+ template <typename Point, typename Box>\r
+ static inline typename calculation_type<Point, Box>::type\r
+ apply(Point const& point, Box const& box)\r
+ {\r
+ // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call\r
+ return math::sqrt\r
+ (\r
+ boost::numeric_cast<typename calculation_type\r
+ <\r
+ Point, Box\r
+ >::type>\r
+ (\r
+ comparable::pythagoras_point_box\r
+ <\r
+ CalculationType\r
+ >::apply(point, box)\r
+ )\r
+ );\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType>\r
+struct tag<pythagoras_point_box<CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_box type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Point, typename Box>\r
+struct return_type<distance::pythagoras_point_box<CalculationType>, Point, Box>\r
+ : pythagoras_point_box\r
+ <\r
+ CalculationType\r
+ >::template calculation_type<Point, Box>\r
+{};\r
+\r
+\r
+template <typename CalculationType>\r
+struct comparable_type<pythagoras_point_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_point_box<CalculationType> type;\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+struct get_comparable<pythagoras_point_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_point_box<CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type\r
+ apply(pythagoras_point_box<CalculationType> const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Point, typename Box>\r
+struct result_from_distance<pythagoras_point_box<CalculationType>, Point, Box>\r
+{\r
+private :\r
+ typedef typename return_type\r
+ <\r
+ pythagoras_point_box<CalculationType>, Point, Box\r
+ >::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type\r
+ apply(pythagoras_point_box<CalculationType> const& , T const& value)\r
+ {\r
+ return return_type(value);\r
+ }\r
+};\r
+\r
+\r
+// Specializations for comparable::pythagoras_point_box\r
+template <typename CalculationType>\r
+struct tag<comparable::pythagoras_point_box<CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_box type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Point, typename Box>\r
+struct return_type\r
+ <\r
+ comparable::pythagoras_point_box<CalculationType>, Point, Box\r
+ > : comparable::pythagoras_point_box\r
+ <\r
+ CalculationType\r
+ >::template calculation_type<Point, Box>\r
+{};\r
+\r
+\r
+\r
+\r
+template <typename CalculationType>\r
+struct comparable_type<comparable::pythagoras_point_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_point_box<CalculationType> type;\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+struct get_comparable<comparable::pythagoras_point_box<CalculationType> >\r
+{\r
+ typedef comparable::pythagoras_point_box<CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type apply(comparable_type const& )\r
+ {\r
+ return comparable_type();\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Point, typename Box>\r
+struct result_from_distance\r
+ <\r
+ comparable::pythagoras_point_box<CalculationType>, Point, Box\r
+ >\r
+{\r
+private :\r
+ typedef typename return_type\r
+ <\r
+ comparable::pythagoras_point_box<CalculationType>, Point, Box\r
+ >::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type\r
+ apply(comparable::pythagoras_point_box<CalculationType> const& ,\r
+ T const& value)\r
+ {\r
+ return_type const v = value;\r
+ return v * v;\r
+ }\r
+};\r
+\r
+\r
+template <typename Point, typename BoxPoint>\r
+struct default_strategy\r
+ <\r
+ point_tag, box_tag, Point, BoxPoint, cartesian_tag, cartesian_tag\r
+ >\r
+{\r
+ typedef pythagoras_point_box<> type;\r
+};\r
+\r
+template <typename BoxPoint, typename Point>\r
+struct default_strategy\r
+ <\r
+ box_tag, point_tag, BoxPoint, Point, cartesian_tag, cartesian_tag\r
+ >\r
+{\r
+ typedef typename default_strategy\r
+ <\r
+ point_tag, box_tag, Point, BoxPoint, cartesian_tag, cartesian_tag\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015-2016.\r
+// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP\r
+\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/strategies/covered_by.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace strategy\r
+{\r
+\r
+namespace within\r
+{\r
+\r
+\r
+template <typename Geometry, std::size_t Dimension, typename CSTag>\r
+struct within_range\r
+{\r
+ template <typename Value1, typename Value2>\r
+ static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)\r
+ {\r
+ return value > min_value && value < max_value;\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry, std::size_t Dimension, typename CSTag>\r
+struct covered_by_range\r
+{\r
+ template <typename Value1, typename Value2>\r
+ static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)\r
+ {\r
+ return value >= min_value && value <= max_value;\r
+ }\r
+};\r
+\r
+\r
+// NOTE: the result would be the same if instead of structs defined below\r
+// the above xxx_range were used with the following arguments:\r
+// (min_value + diff_min, min_value, max_value)\r
+struct within_longitude_range\r
+{\r
+ template <typename CalcT>\r
+ static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)\r
+ {\r
+ CalcT const c0 = 0;\r
+ return diff_min > c0 && min_value + diff_min < max_value;\r
+ }\r
+};\r
+\r
+struct covered_by_longitude_range\r
+{\r
+ template <typename CalcT>\r
+ static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)\r
+ {\r
+ return min_value + diff_min <= max_value;\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry,\r
+ typename ResultCheck>\r
+struct longitude_range\r
+{\r
+ template <typename Value1, typename Value2>\r
+ static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)\r
+ {\r
+ typedef typename select_most_precise\r
+ <\r
+ Value1, Value2\r
+ >::type calc_t;\r
+ typedef typename coordinate_system<Geometry>::type::units units_t;\r
+ typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;\r
+\r
+ // min <= max <=> diff >= 0\r
+ calc_t const diff_ing = max_value - min_value;\r
+\r
+ // if containing covers the whole globe it contains all\r
+ if (diff_ing >= constants::period())\r
+ {\r
+ return true;\r
+ }\r
+\r
+ // calculate positive longitude translation with min_value as origin\r
+ calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value);\r
+\r
+ return ResultCheck::template apply<calc_t>(diff_min, min_value, max_value);\r
+ }\r
+};\r
+\r
+\r
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag\r
+template <typename Geometry>\r
+struct within_range<Geometry, 0, spherical_tag>\r
+ : longitude_range<Geometry, within_longitude_range>\r
+{};\r
+\r
+\r
+template <typename Geometry>\r
+struct covered_by_range<Geometry, 0, spherical_tag>\r
+ : longitude_range<Geometry, covered_by_longitude_range>\r
+{};\r
+\r
+\r
+template\r
+<\r
+ template <typename, std::size_t, typename> class SubStrategy,\r
+ typename Point,\r
+ typename Box,\r
+ std::size_t Dimension,\r
+ std::size_t DimensionCount\r
+>\r
+struct relate_point_box_loop\r
+{\r
+ static inline bool apply(Point const& point, Box const& box)\r
+ {\r
+ typedef typename tag_cast<typename cs_tag<Point>::type, spherical_tag>::type cs_tag_t;\r
+\r
+ if (! SubStrategy<Point, Dimension, cs_tag_t>::apply(get<Dimension>(point),\r
+ get<min_corner, Dimension>(box),\r
+ get<max_corner, Dimension>(box))\r
+ )\r
+ {\r
+ return false;\r
+ }\r
+\r
+ return relate_point_box_loop\r
+ <\r
+ SubStrategy,\r
+ Point, Box,\r
+ Dimension + 1, DimensionCount\r
+ >::apply(point, box);\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ template <typename, std::size_t, typename> class SubStrategy,\r
+ typename Point,\r
+ typename Box,\r
+ std::size_t DimensionCount\r
+>\r
+struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount>\r
+{\r
+ static inline bool apply(Point const& , Box const& )\r
+ {\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Box,\r
+ template <typename, std::size_t, typename> class SubStrategy = within_range\r
+>\r
+struct point_in_box\r
+{\r
+ static inline bool apply(Point const& point, Box const& box)\r
+ {\r
+ return relate_point_box_loop\r
+ <\r
+ SubStrategy,\r
+ Point, Box,\r
+ 0, dimension<Point>::type::value\r
+ >::apply(point, box);\r
+ }\r
+};\r
+\r
+\r
+} // namespace within\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+namespace within { namespace services\r
+{\r
+\r
+template <typename Point, typename Box>\r
+struct default_strategy\r
+ <\r
+ point_tag, box_tag,\r
+ point_tag, areal_tag,\r
+ cartesian_tag, cartesian_tag,\r
+ Point, Box\r
+ >\r
+{\r
+ typedef within::point_in_box<Point, Box> type;\r
+};\r
+\r
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag\r
+template <typename Point, typename Box>\r
+struct default_strategy\r
+ <\r
+ point_tag, box_tag,\r
+ point_tag, areal_tag,\r
+ spherical_tag, spherical_tag,\r
+ Point, Box\r
+ >\r
+{\r
+ typedef within::point_in_box<Point, Box> type;\r
+};\r
+\r
+\r
+}} // namespace within::services\r
+\r
+\r
+namespace covered_by { namespace services\r
+{\r
+\r
+\r
+template <typename Point, typename Box>\r
+struct default_strategy\r
+ <\r
+ point_tag, box_tag,\r
+ point_tag, areal_tag,\r
+ cartesian_tag, cartesian_tag,\r
+ Point, Box\r
+ >\r
+{\r
+ typedef within::point_in_box\r
+ <\r
+ Point, Box,\r
+ within::covered_by_range\r
+ > type;\r
+};\r
+\r
+// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag\r
+template <typename Point, typename Box>\r
+struct default_strategy\r
+ <\r
+ point_tag, box_tag,\r
+ point_tag, areal_tag,\r
+ spherical_tag, spherical_tag,\r
+ Point, Box\r
+ >\r
+{\r
+ typedef within::point_in_box\r
+ <\r
+ Point, Box,\r
+ within::covered_by_range\r
+ > type;\r
+};\r
+\r
+\r
+}} // namespace covered_by::services\r
+\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}}} // namespace boost::geometry::strategy\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP\r
+\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace within\r
+{\r
+\r
+/*!\r
+\brief Within detection using cross counting,\r
+\ingroup strategies\r
+\tparam Point \tparam_point\r
+\tparam PointOfSegment \tparam_segment_point\r
+\tparam CalculationType \tparam_calculation\r
+\see http://tog.acm.org/resources/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c\r
+\note Does NOT work correctly for point ON border\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]\r
+}\r
+ */\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename PointOfSegment = Point,\r
+ typename CalculationType = void\r
+>\r
+class crossings_multiply\r
+{\r
+ typedef typename select_calculation_type\r
+ <\r
+ Point,\r
+ PointOfSegment,\r
+ CalculationType\r
+ >::type calculation_type;\r
+\r
+ class flags\r
+ {\r
+ bool inside_flag;\r
+ bool first;\r
+ bool yflag0;\r
+\r
+ public :\r
+\r
+ friend class crossings_multiply;\r
+\r
+ inline flags()\r
+ : inside_flag(false)\r
+ , first(true)\r
+ , yflag0(false)\r
+ {}\r
+ };\r
+\r
+public :\r
+\r
+ typedef Point point_type;\r
+ typedef PointOfSegment segment_point_type;\r
+ typedef flags state_type;\r
+\r
+ static inline bool apply(Point const& point,\r
+ PointOfSegment const& seg1, PointOfSegment const& seg2,\r
+ flags& state)\r
+ {\r
+ calculation_type const tx = get<0>(point);\r
+ calculation_type const ty = get<1>(point);\r
+ calculation_type const x0 = get<0>(seg1);\r
+ calculation_type const y0 = get<1>(seg1);\r
+ calculation_type const x1 = get<0>(seg2);\r
+ calculation_type const y1 = get<1>(seg2);\r
+\r
+ if (state.first)\r
+ {\r
+ state.first = false;\r
+ state.yflag0 = y0 >= ty;\r
+ }\r
+\r
+\r
+ bool yflag1 = y1 >= ty;\r
+ if (state.yflag0 != yflag1)\r
+ {\r
+ if ( ((y1-ty) * (x0-x1) >= (x1-tx) * (y0-y1)) == yflag1 )\r
+ {\r
+ state.inside_flag = ! state.inside_flag;\r
+ }\r
+ }\r
+ state.yflag0 = yflag1;\r
+ return true;\r
+ }\r
+\r
+ static inline int result(flags const& state)\r
+ {\r
+ return state.inside_flag ? 1 : -1;\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP\r
+\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace within\r
+{\r
+\r
+/*!\r
+\brief Within detection using cross counting\r
+\ingroup strategies\r
+\tparam Point \tparam_point\r
+\tparam PointOfSegment \tparam_segment_point\r
+\tparam CalculationType \tparam_calculation\r
+\author adapted from Randolph Franklin algorithm\r
+\author Barend and Maarten, 1995\r
+\author Revised for templatized library, Barend Gehrels, 2007\r
+\return true if point is in ring, works for closed rings in both directions\r
+\note Does NOT work correctly for point ON border\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]\r
+}\r
+ */\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename PointOfSegment = Point,\r
+ typename CalculationType = void\r
+>\r
+class franklin\r
+{\r
+ typedef typename select_calculation_type\r
+ <\r
+ Point,\r
+ PointOfSegment,\r
+ CalculationType\r
+ >::type calculation_type;\r
+\r
+ /*! subclass to keep state */\r
+ class crossings\r
+ {\r
+ bool crosses;\r
+\r
+ public :\r
+\r
+ friend class franklin;\r
+ inline crossings()\r
+ : crosses(false)\r
+ {}\r
+ };\r
+\r
+public :\r
+\r
+ typedef Point point_type;\r
+ typedef PointOfSegment segment_point_type;\r
+ typedef crossings state_type;\r
+\r
+ static inline bool apply(Point const& point,\r
+ PointOfSegment const& seg1, PointOfSegment const& seg2,\r
+ crossings& state)\r
+ {\r
+ calculation_type const& px = get<0>(point);\r
+ calculation_type const& py = get<1>(point);\r
+ calculation_type const& x1 = get<0>(seg1);\r
+ calculation_type const& y1 = get<1>(seg1);\r
+ calculation_type const& x2 = get<0>(seg2);\r
+ calculation_type const& y2 = get<1>(seg2);\r
+\r
+ if (\r
+ ( (y2 <= py && py < y1) || (y1 <= py && py < y2) )\r
+ && (px < (x1 - x2) * (py - y2) / (y1 - y2) + x2)\r
+ )\r
+ {\r
+ state.crosses = ! state.crosses;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ static inline int result(crossings const& state)\r
+ {\r
+ return state.crosses ? 1 : -1;\r
+ }\r
+};\r
+\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_integral.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/relate/less.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+/*!\r
+\brief Check at which side of a segment a point lies:\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename CalculationType = void>\r
+class side_by_triangle\r
+{\r
+ template <typename Policy>\r
+ struct eps_policy\r
+ {\r
+ eps_policy() {}\r
+ template <typename Type>\r
+ eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)\r
+ : policy(a, b, c, d)\r
+ {}\r
+ Policy policy;\r
+ };\r
+\r
+ struct eps_empty\r
+ {\r
+ eps_empty() {}\r
+ template <typename Type>\r
+ eps_empty(Type const&, Type const&, Type const&, Type const&) {}\r
+ };\r
+\r
+public :\r
+\r
+ // Template member function, because it is not always trivial\r
+ // or convenient to explicitly mention the typenames in the\r
+ // strategy-struct itself.\r
+\r
+ // Types can be all three different. Therefore it is\r
+ // not implemented (anymore) as "segment"\r
+\r
+ template\r
+ <\r
+ typename CoordinateType,\r
+ typename PromotedType,\r
+ typename P1,\r
+ typename P2,\r
+ typename P,\r
+ typename EpsPolicy\r
+ >\r
+ static inline\r
+ PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)\r
+ {\r
+ CoordinateType const x = get<0>(p);\r
+ CoordinateType const y = get<1>(p);\r
+\r
+ CoordinateType const sx1 = get<0>(p1);\r
+ CoordinateType const sy1 = get<1>(p1);\r
+ CoordinateType const sx2 = get<0>(p2);\r
+ CoordinateType const sy2 = get<1>(p2);\r
+\r
+ PromotedType const dx = sx2 - sx1;\r
+ PromotedType const dy = sy2 - sy1;\r
+ PromotedType const dpx = x - sx1;\r
+ PromotedType const dpy = y - sy1;\r
+\r
+ eps_policy = EpsPolicy(dx, dy, dpx, dpy);\r
+\r
+ return geometry::detail::determinant<PromotedType>\r
+ (\r
+ dx, dy,\r
+ dpx, dpy\r
+ );\r
+\r
+ }\r
+\r
+ template\r
+ <\r
+ typename CoordinateType,\r
+ typename PromotedType,\r
+ typename P1,\r
+ typename P2,\r
+ typename P\r
+ >\r
+ static inline\r
+ PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ eps_empty dummy;\r
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);\r
+ }\r
+\r
+\r
+ template\r
+ <\r
+ typename CoordinateType,\r
+ typename PromotedType,\r
+ bool AreAllIntegralCoordinates\r
+ >\r
+ struct compute_side_value\r
+ {\r
+ template <typename P1, typename P2, typename P, typename EpsPolicy>\r
+ static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)\r
+ {\r
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);\r
+ }\r
+ };\r
+\r
+ template <typename CoordinateType, typename PromotedType>\r
+ struct compute_side_value<CoordinateType, PromotedType, false>\r
+ {\r
+ template <typename P1, typename P2, typename P, typename EpsPolicy>\r
+ static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)\r
+ {\r
+ // For robustness purposes, first check if any two points are\r
+ // the same; in this case simply return that the points are\r
+ // collinear\r
+ if (geometry::detail::equals::equals_point_point(p1, p2)\r
+ || geometry::detail::equals::equals_point_point(p1, p)\r
+ || geometry::detail::equals::equals_point_point(p2, p))\r
+ {\r
+ return PromotedType(0);\r
+ }\r
+\r
+ // The side_by_triangle strategy computes the signed area of\r
+ // the point triplet (p1, p2, p); as such it is (in theory)\r
+ // invariant under cyclic permutations of its three arguments.\r
+ //\r
+ // In the context of numerical errors that arise in\r
+ // floating-point computations, and in order to make the strategy\r
+ // consistent with respect to cyclic permutations of its three\r
+ // arguments, we cyclically permute them so that the first\r
+ // argument is always the lexicographically smallest point.\r
+\r
+ geometry::detail::relate::less less;\r
+ if (less(p, p1))\r
+ {\r
+ if (less(p, p2))\r
+ {\r
+ // p is the lexicographically smallest\r
+ return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);\r
+ }\r
+ else\r
+ {\r
+ // p2 is the lexicographically smallest\r
+ return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);\r
+ }\r
+ }\r
+\r
+ if (less(p1, p2))\r
+ {\r
+ // p1 is the lexicographically smallest\r
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);\r
+ }\r
+ else\r
+ {\r
+ // p2 is the lexicographically smallest\r
+ return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);\r
+ }\r
+ }\r
+ };\r
+\r
+\r
+ template <typename P1, typename P2, typename P>\r
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ typedef typename coordinate_type<P1>::type coordinate_type1;\r
+ typedef typename coordinate_type<P2>::type coordinate_type2;\r
+ typedef typename coordinate_type<P>::type coordinate_type3;\r
+\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ boost::is_void<CalculationType>::type::value,\r
+ typename select_most_precise\r
+ <\r
+ typename select_most_precise\r
+ <\r
+ coordinate_type1, coordinate_type2\r
+ >::type,\r
+ coordinate_type3\r
+ >::type,\r
+ CalculationType\r
+ >::type coordinate_type;\r
+\r
+ // Promote float->double, small int->int\r
+ typedef typename select_most_precise\r
+ <\r
+ coordinate_type,\r
+ double\r
+ >::type promoted_type;\r
+\r
+ bool const are_all_integral_coordinates =\r
+ boost::is_integral<coordinate_type1>::value\r
+ && boost::is_integral<coordinate_type2>::value\r
+ && boost::is_integral<coordinate_type3>::value;\r
+\r
+ eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;\r
+ promoted_type s = compute_side_value\r
+ <\r
+ coordinate_type, promoted_type, are_all_integral_coordinates\r
+ >::apply(p1, p2, p, epsp);\r
+\r
+ promoted_type const zero = promoted_type();\r
+ return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0\r
+ : s > zero ? 1\r
+ : -1;\r
+ }\r
+\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType>\r
+struct default_strategy<cartesian_tag, CalculationType>\r
+{\r
+ typedef side_by_triangle<CalculationType> type;\r
+};\r
+\r
+}\r
+#endif\r
+\r
+}} // namespace strategy::side\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP\r
+\r
+\r
+#include <limits>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/type_traits/is_integral.hpp>\r
+#include <boost/type_traits/make_unsigned.hpp>\r
+\r
+#include <boost/geometry/arithmetic/determinant.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG\r
+#include <boost/math/common_factor_ct.hpp>\r
+#include <boost/math/common_factor_rt.hpp>\r
+#include <boost/multiprecision/cpp_int.hpp>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+// A tool for multiplication of integers avoiding overflow\r
+// It's a temporary workaround until we can use Multiprecision\r
+// The algorithm is based on Karatsuba algorithm\r
+// see: http://en.wikipedia.org/wiki/Karatsuba_algorithm\r
+template <typename T>\r
+struct multiplicable_integral\r
+{\r
+ // Currently this tool can't be used with non-integral coordinate types.\r
+ // Also side_of_intersection strategy sign_of_product() and sign_of_compare()\r
+ // functions would have to be modified to properly support floating-point\r
+ // types (comparisons and multiplication).\r
+ BOOST_STATIC_ASSERT(boost::is_integral<T>::value);\r
+\r
+ static const std::size_t bits = CHAR_BIT * sizeof(T);\r
+ static const std::size_t half_bits = bits / 2;\r
+ typedef typename boost::make_unsigned<T>::type unsigned_type;\r
+ static const unsigned_type base = unsigned_type(1) << half_bits; // 2^half_bits\r
+\r
+ int m_sign;\r
+ unsigned_type m_ms;\r
+ unsigned_type m_ls;\r
+\r
+ multiplicable_integral(int sign, unsigned_type ms, unsigned_type ls)\r
+ : m_sign(sign), m_ms(ms), m_ls(ls)\r
+ {}\r
+\r
+ explicit multiplicable_integral(T const& val)\r
+ {\r
+ unsigned_type val_u = val > 0 ?\r
+ unsigned_type(val)\r
+ : val == (std::numeric_limits<T>::min)() ?\r
+ unsigned_type((std::numeric_limits<T>::max)()) + 1\r
+ : unsigned_type(-val);\r
+ // MMLL -> S 00MM 00LL\r
+ m_sign = math::sign(val);\r
+ m_ms = val_u >> half_bits; // val_u / base\r
+ m_ls = val_u - m_ms * base;\r
+ }\r
+ \r
+ friend multiplicable_integral operator*(multiplicable_integral const& a,\r
+ multiplicable_integral const& b)\r
+ {\r
+ // (S 00MM 00LL) * (S 00MM 00LL) -> (S Z2MM 00LL)\r
+ unsigned_type z2 = a.m_ms * b.m_ms;\r
+ unsigned_type z0 = a.m_ls * b.m_ls;\r
+ unsigned_type z1 = (a.m_ms + a.m_ls) * (b.m_ms + b.m_ls) - z2 - z0;\r
+ // z0 may be >= base so it must be normalized to allow comparison\r
+ unsigned_type z0_ms = z0 >> half_bits; // z0 / base\r
+ return multiplicable_integral(a.m_sign * b.m_sign,\r
+ z2 * base + z1 + z0_ms,\r
+ z0 - base * z0_ms);\r
+ }\r
+\r
+ friend bool operator<(multiplicable_integral const& a,\r
+ multiplicable_integral const& b)\r
+ {\r
+ if ( a.m_sign == b.m_sign )\r
+ {\r
+ bool u_less = a.m_ms < b.m_ms\r
+ || (a.m_ms == b.m_ms && a.m_ls < b.m_ls);\r
+ return a.m_sign > 0 ? u_less : (! u_less);\r
+ }\r
+ else\r
+ {\r
+ return a.m_sign < b.m_sign;\r
+ }\r
+ }\r
+\r
+ friend bool operator>(multiplicable_integral const& a,\r
+ multiplicable_integral const& b)\r
+ {\r
+ return b < a;\r
+ }\r
+\r
+ template <typename CmpVal>\r
+ void check_value(CmpVal const& cmp_val) const\r
+ {\r
+ unsigned_type b = base; // a workaround for MinGW - undefined reference base\r
+ CmpVal val = CmpVal(m_sign) * (CmpVal(m_ms) * CmpVal(b) + CmpVal(m_ls));\r
+ BOOST_GEOMETRY_ASSERT(cmp_val == val);\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+\r
+// Calculates the side of the intersection-point (if any) of\r
+// of segment a//b w.r.t. segment c\r
+// This is calculated without (re)calculating the IP itself again and fully\r
+// based on integer mathematics; there are no divisions\r
+// It can be used for either integer (rescaled) points, and also for FP\r
+class side_of_intersection\r
+{\r
+private :\r
+ template <typename T, typename U>\r
+ static inline\r
+ int sign_of_product(T const& a, U const& b)\r
+ {\r
+ return a == 0 || b == 0 ? 0\r
+ : a > 0 && b > 0 ? 1\r
+ : a < 0 && b < 0 ? 1\r
+ : -1;\r
+ }\r
+\r
+ template <typename T>\r
+ static inline\r
+ int sign_of_compare(T const& a, T const& b, T const& c, T const& d)\r
+ {\r
+ // Both a*b and c*d are positive\r
+ // We have to judge if a*b > c*d\r
+\r
+ using side::detail::multiplicable_integral;\r
+ multiplicable_integral<T> ab = multiplicable_integral<T>(a)\r
+ * multiplicable_integral<T>(b);\r
+ multiplicable_integral<T> cd = multiplicable_integral<T>(c)\r
+ * multiplicable_integral<T>(d);\r
+ \r
+ int result = ab > cd ? 1\r
+ : ab < cd ? -1\r
+ : 0\r
+ ;\r
+\r
+#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG\r
+ using namespace boost::multiprecision;\r
+ cpp_int const lab = cpp_int(a) * cpp_int(b);\r
+ cpp_int const lcd = cpp_int(c) * cpp_int(d);\r
+\r
+ ab.check_value(lab);\r
+ cd.check_value(lcd);\r
+\r
+ int result2 = lab > lcd ? 1\r
+ : lab < lcd ? -1\r
+ : 0\r
+ ;\r
+ BOOST_GEOMETRY_ASSERT(result == result2);\r
+#endif\r
+\r
+ return result;\r
+ }\r
+\r
+ template <typename T>\r
+ static inline\r
+ int sign_of_addition_of_two_products(T const& a, T const& b, T const& c, T const& d)\r
+ {\r
+ // sign of a*b+c*d, 1 if positive, -1 if negative, else 0\r
+ int const ab = sign_of_product(a, b);\r
+ int const cd = sign_of_product(c, d);\r
+ if (ab == 0)\r
+ {\r
+ return cd;\r
+ }\r
+ if (cd == 0)\r
+ {\r
+ return ab;\r
+ }\r
+\r
+ if (ab == cd)\r
+ {\r
+ // Both positive or both negative\r
+ return ab;\r
+ }\r
+\r
+ // One is positive, one is negative, both are non zero\r
+ // If ab is positive, we have to judge if a*b > -c*d (then 1 because sum is positive)\r
+ // If ab is negative, we have to judge if c*d > -a*b (idem)\r
+ return ab == 1\r
+ ? sign_of_compare(a, b, -c, d)\r
+ : sign_of_compare(c, d, -a, b);\r
+ }\r
+\r
+\r
+public :\r
+\r
+ // Calculates the side of the intersection-point (if any) of\r
+ // of segment a//b w.r.t. segment c\r
+ // This is calculated without (re)calculating the IP itself again and fully\r
+ // based on integer mathematics\r
+ template <typename T, typename Segment, typename Point>\r
+ static inline T side_value(Segment const& a, Segment const& b,\r
+ Segment const& c, Point const& fallback_point)\r
+ {\r
+ // The first point of the three segments is reused several times\r
+ T const ax = get<0, 0>(a);\r
+ T const ay = get<0, 1>(a);\r
+ T const bx = get<0, 0>(b);\r
+ T const by = get<0, 1>(b);\r
+ T const cx = get<0, 0>(c);\r
+ T const cy = get<0, 1>(c);\r
+\r
+ T const dx_a = get<1, 0>(a) - ax;\r
+ T const dy_a = get<1, 1>(a) - ay;\r
+\r
+ T const dx_b = get<1, 0>(b) - bx;\r
+ T const dy_b = get<1, 1>(b) - by;\r
+\r
+ T const dx_c = get<1, 0>(c) - cx;\r
+ T const dy_c = get<1, 1>(c) - cy;\r
+\r
+ // Cramer's rule: d (see cart_intersect.hpp)\r
+ T const d = geometry::detail::determinant<T>\r
+ (\r
+ dx_a, dy_a,\r
+ dx_b, dy_b\r
+ );\r
+\r
+ T const zero = T();\r
+ if (d == zero)\r
+ {\r
+ // There is no IP of a//b, they are collinear or parallel\r
+ // Assuming they intersect (this method should be called for\r
+ // segments known to intersect), they are collinear and overlap.\r
+ // They have one or two intersection points - we don't know and\r
+ // have to rely on the fallback intersection point\r
+\r
+ Point c1, c2;\r
+ geometry::detail::assign_point_from_index<0>(c, c1);\r
+ geometry::detail::assign_point_from_index<1>(c, c2);\r
+ return side_by_triangle<>::apply(c1, c2, fallback_point);\r
+ }\r
+\r
+ // Cramer's rule: da (see cart_intersect.hpp)\r
+ T const da = geometry::detail::determinant<T>\r
+ (\r
+ dx_b, dy_b,\r
+ ax - bx, ay - by\r
+ );\r
+\r
+ // IP is at (ax + (da/d) * dx_a, ay + (da/d) * dy_a)\r
+ // Side of IP is w.r.t. c is: determinant(dx_c, dy_c, ipx-cx, ipy-cy)\r
+ // We replace ipx by expression above and multiply each term by d\r
+\r
+#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG\r
+ T const result1 = geometry::detail::determinant<T>\r
+ (\r
+ dx_c * d, dy_c * d,\r
+ d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da\r
+ );\r
+\r
+ // Note: result / (d * d)\r
+ // is identical to the side_value of side_by_triangle\r
+ // Therefore, the sign is always the same as that result, and the\r
+ // resulting side (left,right,collinear) is the same\r
+\r
+ // The first row we divide again by d because of determinant multiply rule\r
+ T const result2 = d * geometry::detail::determinant<T>\r
+ (\r
+ dx_c, dy_c,\r
+ d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da\r
+ );\r
+ // Write out:\r
+ T const result3 = d * (dx_c * (d * (ay - cy) + dy_a * da)\r
+ - dy_c * (d * (ax - cx) + dx_a * da));\r
+ // Write out in braces:\r
+ T const result4 = d * (dx_c * d * (ay - cy) + dx_c * dy_a * da\r
+ - dy_c * d * (ax - cx) - dy_c * dx_a * da);\r
+ // Write in terms of d * XX + da * YY\r
+ T const result5 = d * (d * (dx_c * (ay - cy) - dy_c * (ax - cx))\r
+ + da * (dx_c * dy_a - dy_c * dx_a));\r
+\r
+ boost::ignore_unused(result1, result2, result3, result4, result5);\r
+ //return result;\r
+#endif\r
+\r
+ // We consider the results separately\r
+ // (in the end we only have to return the side-value 1,0 or -1)\r
+\r
+ // To avoid multiplications we judge the product (easy, avoids *d)\r
+ // and the sign of p*q+r*s (more elaborate)\r
+ T const result = sign_of_product\r
+ (\r
+ d,\r
+ sign_of_addition_of_two_products\r
+ (\r
+ d, dx_c * (ay - cy) - dy_c * (ax - cx),\r
+ da, dx_c * dy_a - dy_c * dx_a\r
+ )\r
+ );\r
+ return result;\r
+\r
+\r
+ }\r
+\r
+ template <typename Segment, typename Point>\r
+ static inline int apply(Segment const& a, Segment const& b,\r
+ Segment const& c,\r
+ Point const& fallback_point)\r
+ {\r
+ typedef typename geometry::coordinate_type<Segment>::type coordinate_type;\r
+ coordinate_type const s = side_value<coordinate_type>(a, b, c, fallback_point);\r
+ coordinate_type const zero = coordinate_type();\r
+ return math::equals(s, zero) ? 0\r
+ : s > zero ? 1\r
+ : -1;\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace strategy::side\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace centroid\r
+{\r
+\r
+struct not_applicable_strategy\r
+{\r
+};\r
+\r
+\r
+namespace services\r
+{\r
+\r
+/*!\r
+ \brief Traits class binding a centroid calculation strategy to a coordinate system\r
+ \ingroup centroid\r
+ \tparam CsTag tag of coordinate system, for specialization\r
+ \tparam GeometryTag tag of geometry, for specialization\r
+ \tparam Dimension dimension of geometry, for specialization\r
+ \tparam Point point-type\r
+ \tparam Geometry\r
+*/\r
+template\r
+<\r
+ typename CsTag,\r
+ typename GeometryTag,\r
+ std::size_t Dimension,\r
+ typename Point,\r
+ typename Geometry\r
+>\r
+struct default_strategy\r
+{\r
+ typedef not_applicable_strategy type;\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+}} // namespace strategy::centroid\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP\r
+\r
+#include <boost/mpl/always.hpp>\r
+#include <boost/mpl/bool.hpp>\r
+#include <boost/mpl/vector.hpp>\r
+\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/compress_variant.hpp>\r
+#include <boost/geometry/util/transform_variant.hpp>\r
+#include <boost/geometry/util/combine_if.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+struct comparable_distance_result\r
+ : strategy::distance::services::return_type\r
+ <\r
+ typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type,\r
+ typename point_type<Geometry1>::type,\r
+ typename point_type<Geometry2>::type\r
+ >\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct comparable_distance_result<Geometry1, Geometry2, default_strategy>\r
+ : comparable_distance_result\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename detail::distance::default_strategy\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ >\r
+{};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+struct comparable_distance_result\r
+ : resolve_strategy::comparable_distance_result\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ Strategy\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T),\r
+ typename Strategy\r
+>\r
+struct comparable_distance_result\r
+ <\r
+ Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy\r
+ >\r
+{\r
+ // A set of all variant type combinations that are compatible and\r
+ // implemented\r
+ typedef typename util::combine_if<\r
+ typename boost::mpl::vector1<Geometry1>,\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ boost::mpl::always<boost::mpl::true_>\r
+ >::type possible_input_types;\r
+\r
+ // The (possibly variant) result type resulting from these combinations\r
+ typedef typename compress_variant<\r
+ typename transform_variant<\r
+ possible_input_types,\r
+ resolve_strategy::comparable_distance_result<\r
+ boost::mpl::first<boost::mpl::_>,\r
+ boost::mpl::second<boost::mpl::_>,\r
+ Strategy\r
+ >,\r
+ boost::mpl::back_inserter<boost::mpl::vector0<> >\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+\r
+// Distance arguments are commutative\r
+template\r
+<\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T),\r
+ typename Geometry2,\r
+ typename Strategy\r
+>\r
+struct comparable_distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2,\r
+ Strategy\r
+ > : public comparable_distance_result\r
+ <\r
+ Geometry2, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>\r
+struct comparable_distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Strategy\r
+ >\r
+{\r
+ // A set of all variant type combinations that are compatible and\r
+ // implemented\r
+ typedef typename util::combine_if\r
+ <\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ boost::mpl::always<boost::mpl::true_>\r
+ >::type possible_input_types;\r
+\r
+ // The (possibly variant) result type resulting from these combinations\r
+ typedef typename compress_variant<\r
+ typename transform_variant<\r
+ possible_input_types,\r
+ resolve_strategy::comparable_distance_result<\r
+ boost::mpl::first<boost::mpl::_>,\r
+ boost::mpl::second<boost::mpl::_>,\r
+ Strategy\r
+ >,\r
+ boost::mpl::back_inserter<boost::mpl::vector0<> >\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+\r
+\r
+\r
+/*!\r
+\brief Meta-function defining return type of comparable_distance function\r
+\ingroup distance\r
+*/\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2 = Geometry1,\r
+ typename Strategy = void\r
+>\r
+struct comparable_distance_result\r
+ : resolve_variant::comparable_distance_result\r
+ <\r
+ Geometry1, Geometry2, Strategy\r
+ >\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct comparable_distance_result<Geometry1, Geometry2, void>\r
+ : comparable_distance_result<Geometry1, Geometry2, default_strategy>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP\r
+\r
+#include <cstddef>\r
+#include <functional>\r
+\r
+#include <boost/mpl/if.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Traits class binding a comparing strategy to a coordinate system\r
+ \ingroup util\r
+ \tparam Tag tag of coordinate system of point-type\r
+ \tparam Direction direction to compare on: 1 for less (-> ascending order)\r
+ and -1 for greater (-> descending order)\r
+ \tparam Point point-type\r
+ \tparam CoordinateSystem coordinate sytem of point\r
+ \tparam Dimension: the dimension to compare on\r
+*/\r
+template\r
+<\r
+ typename Tag,\r
+ int Direction,\r
+ typename Point,\r
+ typename CoordinateSystem,\r
+ std::size_t Dimension\r
+>\r
+struct strategy_compare\r
+{\r
+ typedef strategy::not_implemented type;\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+// For compare we add defaults specializations,\r
+// because they defaultly redirect to std::less / greater / equal_to\r
+template\r
+<\r
+ typename Tag,\r
+ typename Point,\r
+ typename CoordinateSystem,\r
+ std::size_t Dimension\r
+>\r
+struct strategy_compare<Tag, 1, Point, CoordinateSystem, Dimension>\r
+{\r
+ typedef std::less<typename coordinate_type<Point>::type> type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Point,\r
+ typename CoordinateSystem,\r
+ std::size_t Dimension\r
+>\r
+struct strategy_compare<Tag, -1, Point, CoordinateSystem, Dimension>\r
+{\r
+ typedef std::greater<typename coordinate_type<Point>::type> type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename Tag,\r
+ typename Point,\r
+ typename CoordinateSystem,\r
+ std::size_t Dimension\r
+>\r
+struct strategy_compare<Tag, 0, Point, CoordinateSystem, Dimension>\r
+{\r
+ typedef std::equal_to<typename coordinate_type<Point>::type> type;\r
+};\r
+\r
+\r
+#endif\r
+\r
+\r
+namespace strategy { namespace compare\r
+{\r
+\r
+\r
+/*!\r
+ \brief Default strategy, indicates the default strategy for comparisons\r
+ \details The default strategy for comparisons defer in most cases\r
+ to std::less (for ascending) and std::greater (for descending).\r
+ However, if a spherical coordinate system is used, and comparison\r
+ is done on longitude, it will take another strategy handling circular\r
+*/\r
+struct default_strategy {};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Type>\r
+struct is_default : boost::false_type\r
+{};\r
+\r
+\r
+template <>\r
+struct is_default<default_strategy> : boost::true_type\r
+{};\r
+\r
+\r
+/*!\r
+ \brief Meta-function to select strategy\r
+ \details If "default_strategy" is specified, it will take the\r
+ traits-registered class for the specified coordinate system.\r
+ If another strategy is explicitly specified, it takes that one.\r
+*/\r
+template\r
+<\r
+ typename Strategy,\r
+ int Direction,\r
+ typename Point,\r
+ std::size_t Dimension\r
+>\r
+struct select_strategy\r
+{\r
+ typedef typename\r
+ boost::mpl::if_\r
+ <\r
+ is_default<Strategy>,\r
+ typename strategy_compare\r
+ <\r
+ typename cs_tag<Point>::type,\r
+ Direction,\r
+ Point,\r
+ typename coordinate_system<Point>::type,\r
+ Dimension\r
+ >::type,\r
+ Strategy\r
+ >::type type;\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace strategy::compare\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for area\r
+ \ingroup area\r
+*/\r
+template <typename Strategy>\r
+class AreaStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ // 1) must define state_type,\r
+ typedef typename Strategy::state_type state_type;\r
+\r
+ // 2) must define return_type,\r
+ typedef typename Strategy::return_type return_type;\r
+\r
+ // 3) must define point_type, of polygon (segments)\r
+ typedef typename Strategy::segment_point_type spoint_type;\r
+\r
+ struct check_methods\r
+ {\r
+ static void apply()\r
+ {\r
+ Strategy const* str = 0;\r
+ state_type *st = 0;\r
+\r
+ // 4) must implement a method apply with the following signature\r
+ spoint_type const* sp = 0;\r
+ str->apply(*sp, *sp, *st);\r
+\r
+ // 5) must implement a static method result with the following signature\r
+ return_type r = str->result(*st);\r
+\r
+ boost::ignore_unused_variable_warning(r);\r
+ boost::ignore_unused_variable_warning(str);\r
+ }\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(AreaStrategy)\r
+ {\r
+ check_methods::apply();\r
+ }\r
+\r
+#endif\r
+};\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP\r
+\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for centroid\r
+ \ingroup centroid\r
+*/\r
+template <typename Strategy>\r
+class CentroidStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ // 1) must define state_type,\r
+ typedef typename Strategy::state_type state_type;\r
+\r
+ // 2) must define point_type,\r
+ typedef typename Strategy::point_type point_type;\r
+\r
+ // 3) must define point_type, of polygon (segments)\r
+ typedef typename Strategy::segment_point_type spoint_type;\r
+\r
+ struct check_methods\r
+ {\r
+ static void apply()\r
+ {\r
+ Strategy *str = 0;\r
+ state_type *st = 0;\r
+\r
+ // 4) must implement a static method apply,\r
+ // getting two segment-points\r
+ spoint_type const* sp = 0;\r
+ str->apply(*sp, *sp, *st);\r
+\r
+ // 5) must implement a static method result\r
+ // getting the centroid\r
+ point_type *c = 0;\r
+ bool r = str->result(*st, *c);\r
+\r
+ boost::ignore_unused_variable_warning(str);\r
+ boost::ignore_unused_variable_warning(r);\r
+ }\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(CentroidStrategy)\r
+ {\r
+ check_methods::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP\r
+\r
+\r
+#include <vector>\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for convex_hull\r
+ \ingroup convex_hull\r
+*/\r
+template <typename Strategy>\r
+class ConvexHullStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ // 1) must define state_type\r
+ typedef typename Strategy::state_type state_type;\r
+\r
+ // 2) must define point_type\r
+ typedef typename Strategy::point_type point_type;\r
+\r
+ // 3) must define geometry_type\r
+ typedef typename Strategy::geometry_type geometry_type;\r
+\r
+ struct check_methods\r
+ {\r
+ static void apply()\r
+ {\r
+ Strategy const* str = 0;\r
+\r
+ state_type* st = 0;\r
+ geometry_type* sp = 0;\r
+ std::vector<point_type> *v = 0;\r
+\r
+ // 4) must implement a method apply, iterating over a range\r
+ str->apply(*sp, *st);\r
+\r
+ // 5) must implement a method result, with an output iterator\r
+ str->result(*st, std::back_inserter(*v), true, true);\r
+ }\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(ConvexHullStrategy)\r
+ {\r
+ check_methods::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP\r
+\r
+#include <vector>\r
+#include <iterator>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/core/ignore_unused.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/type_traits/is_same.hpp>\r
+\r
+#include <boost/geometry/util/parameter_type_of.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+#include <boost/geometry/geometries/point.hpp>\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for point-point or point-box or box-box distance\r
+ \ingroup distance\r
+*/\r
+template <typename Strategy, typename Point1, typename Point2>\r
+struct PointDistanceStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+private :\r
+\r
+ struct checker\r
+ {\r
+ template <typename ApplyMethod>\r
+ static void apply(ApplyMethod)\r
+ {\r
+ // 1: inspect and define both arguments of apply\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 0\r
+ >::type ptype1;\r
+\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 1\r
+ >::type ptype2;\r
+\r
+ // 2) must define meta-function "return_type"\r
+ typedef typename strategy::distance::services::return_type\r
+ <\r
+ Strategy, ptype1, ptype2\r
+ >::type rtype;\r
+\r
+ // 3) must define meta-function "comparable_type"\r
+ typedef typename strategy::distance::services::comparable_type\r
+ <\r
+ Strategy\r
+ >::type ctype;\r
+\r
+ // 4) must define meta-function "tag"\r
+ typedef typename strategy::distance::services::tag\r
+ <\r
+ Strategy\r
+ >::type tag;\r
+\r
+ static const bool is_correct_strategy_tag =\r
+ boost::is_same<tag, strategy_tag_distance_point_point>::value\r
+ || boost::is_same<tag, strategy_tag_distance_point_box>::value\r
+ || boost::is_same<tag, strategy_tag_distance_box_box>::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG\r
+ ((is_correct_strategy_tag),\r
+ INCORRECT_STRATEGY_TAG,\r
+ (types<tag>));\r
+\r
+ // 5) must implement apply with arguments\r
+ Strategy* str = 0;\r
+ ptype1 *p1 = 0;\r
+ ptype2 *p2 = 0;\r
+ rtype r = str->apply(*p1, *p2);\r
+\r
+ // 6) must define (meta)struct "get_comparable" with apply\r
+ ctype c = strategy::distance::services::get_comparable\r
+ <\r
+ Strategy\r
+ >::apply(*str);\r
+\r
+ // 7) must define (meta)struct "result_from_distance" with apply\r
+ r = strategy::distance::services::result_from_distance\r
+ <\r
+ Strategy,\r
+ ptype1, ptype2\r
+ >::apply(*str, 1.0);\r
+\r
+ boost::ignore_unused<tag>();\r
+ boost::ignore_unused(str, c, r);\r
+ }\r
+ };\r
+\r
+\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(PointDistanceStrategy)\r
+ {\r
+ checker::apply(&Strategy::template apply<Point1, Point2>);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for point-segment distance\r
+ \ingroup strategy_concepts\r
+*/\r
+template <typename Strategy, typename Point, typename PointOfSegment>\r
+struct PointSegmentDistanceStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+private :\r
+\r
+ struct checker\r
+ {\r
+ template <typename ApplyMethod>\r
+ static void apply(ApplyMethod)\r
+ {\r
+ // 1) inspect and define both arguments of apply\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 0\r
+ >::type ptype;\r
+\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 1\r
+ >::type sptype;\r
+\r
+ namespace services = strategy::distance::services;\r
+ // 2) must define meta-function "tag"\r
+ typedef typename services::tag<Strategy>::type tag;\r
+\r
+ BOOST_MPL_ASSERT_MSG\r
+ ((boost::is_same\r
+ <\r
+ tag, strategy_tag_distance_point_segment\r
+ >::value),\r
+ INCORRECT_STRATEGY_TAG,\r
+ (types<tag>));\r
+\r
+ // 3) must define meta-function "return_type"\r
+ typedef typename services::return_type\r
+ <\r
+ Strategy, ptype, sptype\r
+ >::type rtype;\r
+\r
+ // 4) must define meta-function "comparable_type"\r
+ typedef typename services::comparable_type<Strategy>::type ctype;\r
+\r
+ // 5) must implement apply with arguments\r
+ Strategy *str = 0;\r
+ ptype *p = 0;\r
+ sptype *sp1 = 0;\r
+ sptype *sp2 = 0;\r
+\r
+ rtype r = str->apply(*p, *sp1, *sp2);\r
+\r
+ // 6) must define (meta-)struct "get_comparable" with apply\r
+ ctype cstrategy = services::get_comparable<Strategy>::apply(*str);\r
+\r
+ // 7) must define (meta-)struct "result_from_distance" with apply\r
+ r = services::result_from_distance\r
+ <\r
+ Strategy, ptype, sptype\r
+ >::apply(*str, rtype(1.0));\r
+\r
+ boost::ignore_unused(str, r, cstrategy);\r
+ }\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)\r
+ {\r
+ checker::apply(&Strategy::template apply<Point, PointOfSegment>);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP\r
+\r
+\r
+//NOT FINISHED!\r
+\r
+#include <boost/concept_check.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for segment intersection\r
+ \ingroup segment_intersection\r
+*/\r
+template <typename Strategy>\r
+class SegmentIntersectStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ // 1) must define return_type\r
+ typedef typename Strategy::return_type return_type;\r
+\r
+ // 2) must define point_type (of segment points)\r
+ //typedef typename Strategy::point_type point_type;\r
+\r
+ // 3) must define segment_type 1 and 2 (of segment points)\r
+ typedef typename Strategy::segment_type1 segment_type1;\r
+ typedef typename Strategy::segment_type2 segment_type2;\r
+\r
+\r
+ struct check_methods\r
+ {\r
+ static void apply()\r
+ {\r
+ Strategy const* str;\r
+\r
+ return_type* rt;\r
+ //point_type const* p;\r
+ segment_type1 const* s1;\r
+ segment_type2 const* s2;\r
+\r
+ // 4) must implement a method apply\r
+ // having two segments\r
+ *rt = str->apply(*s1, *s2);\r
+\r
+ }\r
+ };\r
+\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(SegmentIntersectStrategy)\r
+ {\r
+ check_methods::apply();\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP\r
+\r
+#include <vector>\r
+#include <iterator>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/geometries/point.hpp>\r
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+ \brief Checks strategy for simplify\r
+ \ingroup simplify\r
+*/\r
+template <typename Strategy, typename Point>\r
+struct SimplifyStrategy\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+private :\r
+\r
+ // 1) must define distance_strategy_type,\r
+ // defining point-segment distance strategy (to be checked)\r
+ typedef typename Strategy::distance_strategy_type ds_type;\r
+\r
+\r
+ struct checker\r
+ {\r
+ template <typename ApplyMethod>\r
+ static void apply(ApplyMethod)\r
+ {\r
+ namespace ft = boost::function_types;\r
+ typedef typename ft::parameter_types\r
+ <\r
+ ApplyMethod\r
+ >::type parameter_types;\r
+\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ ft::is_member_function_pointer<ApplyMethod>,\r
+ boost::mpl::int_<1>,\r
+ boost::mpl::int_<0>\r
+ >::type base_index;\r
+\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::PointSegmentDistanceStrategy<ds_type, Point, Point>)\r
+ );\r
+\r
+ Strategy *str = 0;\r
+ std::vector<Point> const* v1 = 0;\r
+ std::vector<Point> * v2 = 0;\r
+\r
+ // 2) must implement method apply with arguments\r
+ // - Range\r
+ // - OutputIterator\r
+ // - floating point value\r
+ str->apply(*v1, std::back_inserter(*v2), 1.0);\r
+\r
+ boost::ignore_unused<parameter_types, base_index>();\r
+ boost::ignore_unused(str);\r
+ }\r
+ };\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(SimplifyStrategy)\r
+ {\r
+ checker::apply(&ds_type::template apply<Point, Point>);\r
+ }\r
+#endif\r
+};\r
+\r
+\r
+\r
+}}} // namespace boost::geometry::concepts\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP\r
+\r
+\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/function_types/result_type.hpp>\r
+\r
+#include <boost/geometry/util/parameter_type_of.hpp>\r
+\r
+\r
+namespace boost { namespace geometry { namespace concepts\r
+{\r
+\r
+\r
+/*!\r
+\brief Checks strategy for within (point-in-polygon)\r
+\ingroup within\r
+*/\r
+template <typename Strategy>\r
+class WithinStrategyPolygonal\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ // 1) must define state_type\r
+ typedef typename Strategy::state_type state_type;\r
+\r
+ struct checker\r
+ {\r
+ template <typename ApplyMethod, typename ResultMethod>\r
+ static void apply(ApplyMethod const&, ResultMethod const& )\r
+ {\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 0\r
+ >::type point_type;\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 1\r
+ >::type segment_point_type;\r
+\r
+ // CHECK: apply-arguments should both fulfill point concept\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::ConstPoint<point_type>)\r
+ );\r
+\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::ConstPoint<segment_point_type>)\r
+ );\r
+\r
+ // CHECK: return types (result: int, apply: bool)\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ (boost::is_same\r
+ <\r
+ bool, typename boost::function_types::result_type<ApplyMethod>::type\r
+ >::type::value),\r
+ WRONG_RETURN_TYPE_OF_APPLY\r
+ , (bool)\r
+ );\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ (boost::is_same\r
+ <\r
+ int, typename boost::function_types::result_type<ResultMethod>::type\r
+ >::type::value),\r
+ WRONG_RETURN_TYPE_OF_RESULT\r
+ , (int)\r
+ );\r
+\r
+\r
+ // CHECK: calling method apply and result\r
+ Strategy const* str = 0;\r
+ state_type* st = 0;\r
+ point_type const* p = 0;\r
+ segment_point_type const* sp = 0;\r
+\r
+ bool b = str->apply(*p, *sp, *sp, *st);\r
+ int r = str->result(*st);\r
+\r
+ boost::ignore_unused_variable_warning(r);\r
+ boost::ignore_unused_variable_warning(b);\r
+ boost::ignore_unused_variable_warning(str);\r
+ }\r
+ };\r
+\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)\r
+ {\r
+ checker::apply(&Strategy::apply, &Strategy::result);\r
+ }\r
+#endif\r
+};\r
+\r
+template <typename Strategy>\r
+class WithinStrategyPointBox\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ struct checker\r
+ {\r
+ template <typename ApplyMethod>\r
+ static void apply(ApplyMethod const&)\r
+ {\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 0\r
+ >::type point_type;\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 1\r
+ >::type box_type;\r
+\r
+ // CHECK: apply-arguments should fulfill point/box concept\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::ConstPoint<point_type>)\r
+ );\r
+\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::ConstBox<box_type>)\r
+ );\r
+\r
+ // CHECK: return types (apply: bool)\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ (boost::is_same\r
+ <\r
+ bool,\r
+ typename boost::function_types::result_type<ApplyMethod>::type\r
+ >::type::value),\r
+ WRONG_RETURN_TYPE\r
+ , (bool)\r
+ );\r
+\r
+\r
+ // CHECK: calling method apply\r
+ Strategy const* str = 0;\r
+ point_type const* p = 0;\r
+ box_type const* bx = 0;\r
+\r
+ bool b = str->apply(*p, *bx);\r
+\r
+ boost::ignore_unused_variable_warning(b);\r
+ boost::ignore_unused_variable_warning(str);\r
+ }\r
+ };\r
+\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(WithinStrategyPointBox)\r
+ {\r
+ checker::apply(&Strategy::apply);\r
+ }\r
+#endif\r
+};\r
+\r
+template <typename Strategy>\r
+class WithinStrategyBoxBox\r
+{\r
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS\r
+\r
+ struct checker\r
+ {\r
+ template <typename ApplyMethod>\r
+ static void apply(ApplyMethod const&)\r
+ {\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 0\r
+ >::type box_type1;\r
+ typedef typename parameter_type_of\r
+ <\r
+ ApplyMethod, 1\r
+ >::type box_type2;\r
+\r
+ // CHECK: apply-arguments should both fulfill box concept\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::ConstBox<box_type1>)\r
+ );\r
+\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::ConstBox<box_type2>)\r
+ );\r
+\r
+ // CHECK: return types (apply: bool)\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ (boost::is_same\r
+ <\r
+ bool,\r
+ typename boost::function_types::result_type<ApplyMethod>::type\r
+ >::type::value),\r
+ WRONG_RETURN_TYPE\r
+ , (bool)\r
+ );\r
+\r
+\r
+ // CHECK: calling method apply\r
+ Strategy const* str = 0;\r
+ box_type1 const* b1 = 0;\r
+ box_type2 const* b2 = 0;\r
+\r
+ bool b = str->apply(*b1, *b2);\r
+\r
+ boost::ignore_unused_variable_warning(b);\r
+ boost::ignore_unused_variable_warning(str);\r
+ }\r
+ };\r
+\r
+\r
+public :\r
+ BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)\r
+ {\r
+ checker::apply(&Strategy::apply);\r
+ }\r
+#endif\r
+};\r
+\r
+// So now: boost::geometry::concepts::within\r
+namespace within\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>\r
+struct check_within\r
+{};\r
+\r
+\r
+template <typename AnyTag, typename Strategy>\r
+struct check_within<point_tag, AnyTag, areal_tag, Strategy>\r
+{\r
+ BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) );\r
+};\r
+\r
+\r
+template <typename Strategy>\r
+struct check_within<point_tag, box_tag, areal_tag, Strategy>\r
+{\r
+ BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Strategy>) );\r
+};\r
+\r
+template <typename Strategy>\r
+struct check_within<box_tag, box_tag, areal_tag, Strategy>\r
+{\r
+ BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) );\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif\r
+\r
+\r
+/*!\r
+\brief Checks, in compile-time, the concept of any within-strategy\r
+\ingroup concepts\r
+*/\r
+template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>\r
+inline void check()\r
+{\r
+ dispatch::check_within<FirstTag, SecondTag, CastedTag, Strategy> c;\r
+ boost::ignore_unused_variable_warning(c);\r
+}\r
+\r
+\r
+}}}} // namespace boost::geometry::concepts::within\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+\r
+\r
+/*!\r
+ \brief Traits class binding a convex hull calculation strategy to a coordinate system\r
+ \ingroup convex_hull\r
+ \tparam Tag tag of coordinate system\r
+ \tparam Geometry the geometry type (hull operates internally per hull over geometry)\r
+ \tparam Point point-type of output points\r
+*/\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Point,\r
+ typename CsTag = typename cs_tag<Point>::type\r
+>\r
+struct strategy_convex_hull\r
+{\r
+ typedef strategy::not_implemented type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace covered_by\r
+{\r
+\r
+\r
+namespace services\r
+{\r
+\r
+/*!\r
+\brief Traits class binding a covered_by determination strategy to a coordinate system\r
+\ingroup covered_by\r
+\tparam TagContained tag (possibly casted) of point-type\r
+\tparam TagContained tag (possibly casted) of (possibly) containing type\r
+\tparam CsTagContained tag of coordinate system of point-type\r
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type\r
+\tparam Geometry geometry-type of input (often point, or box)\r
+\tparam GeometryContaining geometry-type of input (possibly) containing type\r
+*/\r
+template\r
+<\r
+ typename TagContained,\r
+ typename TagContaining,\r
+ typename CastedTagContained,\r
+ typename CastedTagContaining,\r
+ typename CsTagContained,\r
+ typename CsTagContaining,\r
+ typename GeometryContained,\r
+ typename GeometryContaining\r
+>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES\r
+ , (types<GeometryContained, GeometryContaining>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+}} // namespace strategy::covered_by\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP\r
+\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/strategies/area.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Meta-function defining return type of area function, using the default strategy\r
+\ingroup area\r
+\note The strategy defines the return-type (so this situation is different\r
+ from length, where distance is sqr/sqrt, but length always squared)\r
+ */\r
+\r
+template <typename Geometry>\r
+struct default_area_result\r
+{\r
+ typedef typename point_type<Geometry>::type point_type;\r
+ typedef typename strategy::area::services::default_strategy\r
+ <\r
+ typename cs_tag<point_type>::type,\r
+ point_type\r
+ >::type strategy_type;\r
+\r
+ typedef typename strategy_type::return_type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_COMPARABLE_DISTANCE_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_COMPARABLE_DISTANCE_RESULT_HPP\r
+\r
+#include <boost/geometry/strategies/comparable_distance_result.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Meta-function defining return type of comparable_distance function\r
+\ingroup distance\r
+\note The strategy defines the return-type (so this situation is different\r
+ from length, where distance is sqr/sqrt, but length always squared)\r
+ */\r
+template <typename Geometry1, typename Geometry2 = Geometry1>\r
+struct default_comparable_distance_result\r
+ : comparable_distance_result<Geometry1, Geometry2, void>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_COMPARABLE_DISTANCE_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP\r
+\r
+#include <boost/geometry/strategies/distance_result.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Meta-function defining return type of distance function\r
+\ingroup distance\r
+\note The strategy defines the return-type (so this situation is different\r
+ from length, where distance is sqr/sqrt, but length always squared)\r
+ */\r
+template <typename Geometry1, typename Geometry2 = Geometry1>\r
+struct default_distance_result\r
+ : distance_result<Geometry1, Geometry2, void>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP\r
+\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+#include <boost/geometry/util/compress_variant.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+#include <boost/geometry/util/transform_variant.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+template <typename Geometry>\r
+struct default_length_result\r
+{\r
+ typedef typename select_most_precise\r
+ <\r
+ typename coordinate_type<Geometry>::type,\r
+ long double\r
+ >::type type;\r
+};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry>\r
+struct default_length_result\r
+ : resolve_strategy::default_length_result<Geometry>\r
+{};\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>\r
+struct default_length_result<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >\r
+{\r
+ typedef typename compress_variant<\r
+ typename transform_variant<\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ resolve_strategy::default_length_result<boost::mpl::placeholders::_>\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+ \brief Meta-function defining return type of length function\r
+ \ingroup length\r
+ \note Length of a line of integer coordinates can be double.\r
+ So we take at least a double. If Big Number types are used,\r
+ we take that type.\r
+\r
+ */\r
+template <typename Geometry>\r
+struct default_length_result\r
+ : resolve_variant::default_length_result<Geometry>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_STRATEGY_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_STRATEGY_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// This is a strategy placeholder type, which is passed by the algorithm free\r
+// functions to the multi-stage resolving process. It's resolved into an actual\r
+// strategy type during the resolve_strategy stage, possibly depending on the\r
+// input geometry type(s). This typically happens after the resolve_variant\r
+// stage, as it needs to be based on concrete geometry types - as opposed to\r
+// variant geometry types.\r
+\r
+struct default_strategy {};\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_STRATEGY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace distance { namespace services\r
+{\r
+\r
+\r
+template <typename Strategy> struct tag {};\r
+\r
+template <typename Strategy, typename P1, typename P2>\r
+struct return_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy, P1, P2>)\r
+ );\r
+};\r
+\r
+\r
+template <typename Strategy> struct comparable_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)\r
+ );\r
+};\r
+\r
+template <typename Strategy> struct get_comparable\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)\r
+ );\r
+};\r
+\r
+template <typename Strategy, typename P1, typename P2>\r
+struct result_from_distance {};\r
+\r
+\r
+\r
+\r
+// Default strategy\r
+\r
+\r
+/*!\r
+ \brief Traits class binding a default strategy for distance\r
+ to one (or possibly two) coordinate system(s)\r
+ \ingroup distance\r
+ \tparam GeometryTag1 tag (point/segment/box) for which this strategy is the default\r
+ \tparam GeometryTag2 tag (point/segment/box) for which this strategy is the default\r
+ \tparam Point1 first point-type\r
+ \tparam Point2 second point-type\r
+ \tparam CsTag1 tag of coordinate system of first point type\r
+ \tparam CsTag2 tag of coordinate system of second point type\r
+*/\r
+template\r
+<\r
+ typename GeometryTag1,\r
+ typename GeometryTag2,\r
+ typename Point1,\r
+ typename Point2 = Point1,\r
+ typename CsTag1 = typename cs_tag<Point1>::type,\r
+ typename CsTag2 = typename cs_tag<Point2>::type,\r
+ typename UnderlyingStrategy = void\r
+>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE_COMBINATION\r
+ , (types<Point1, Point2, CsTag1, CsTag2>)\r
+ );\r
+};\r
+\r
+\r
+}}} // namespace strategy::distance::services\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP\r
+\r
+#include <boost/mpl/always.hpp>\r
+#include <boost/mpl/bool.hpp>\r
+#include <boost/mpl/vector.hpp>\r
+\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+\r
+#include <boost/geometry/strategies/default_strategy.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/compress_variant.hpp>\r
+#include <boost/geometry/util/transform_variant.hpp>\r
+#include <boost/geometry/util/combine_if.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace resolve_strategy\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+struct distance_result\r
+ : strategy::distance::services::return_type\r
+ <\r
+ Strategy,\r
+ typename point_type<Geometry1>::type,\r
+ typename point_type<Geometry2>::type\r
+ >\r
+{};\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct distance_result<Geometry1, Geometry2, default_strategy>\r
+ : distance_result\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ typename detail::distance::default_strategy\r
+ <\r
+ Geometry1, Geometry2\r
+ >::type\r
+ >\r
+{};\r
+\r
+} // namespace resolve_strategy\r
+\r
+\r
+namespace resolve_variant\r
+{\r
+\r
+template <typename Geometry1, typename Geometry2, typename Strategy>\r
+struct distance_result\r
+ : resolve_strategy::distance_result\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ Strategy\r
+ >\r
+{};\r
+\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T),\r
+ typename Strategy\r
+>\r
+struct distance_result\r
+ <\r
+ Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy\r
+ >\r
+{\r
+ // A set of all variant type combinations that are compatible and\r
+ // implemented\r
+ typedef typename util::combine_if<\r
+ typename boost::mpl::vector1<Geometry1>,\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ // Here we want should remove most of the combinations that\r
+ // are not valid, mostly to limit the size of the resulting MPL set.\r
+ // But is_implementedn is not ready for prime time\r
+ //\r
+ // util::is_implemented2<boost::mpl::_1, boost::mpl::_2, dispatch::distance<boost::mpl::_1, boost::mpl::_2> >\r
+ boost::mpl::always<boost::mpl::true_>\r
+ >::type possible_input_types;\r
+\r
+ // The (possibly variant) result type resulting from these combinations\r
+ typedef typename compress_variant<\r
+ typename transform_variant<\r
+ possible_input_types,\r
+ resolve_strategy::distance_result<\r
+ boost::mpl::first<boost::mpl::_>,\r
+ boost::mpl::second<boost::mpl::_>,\r
+ Strategy\r
+ >,\r
+ boost::mpl::back_inserter<boost::mpl::vector0<> >\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+\r
+// Distance arguments are commutative\r
+template\r
+<\r
+ BOOST_VARIANT_ENUM_PARAMS(typename T),\r
+ typename Geometry2,\r
+ typename Strategy\r
+>\r
+struct distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Geometry2,\r
+ Strategy\r
+ > : public distance_result\r
+ <\r
+ Geometry2, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy\r
+ >\r
+{};\r
+\r
+\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>\r
+struct distance_result\r
+ <\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,\r
+ Strategy\r
+ >\r
+{\r
+ // A set of all variant type combinations that are compatible and\r
+ // implemented\r
+ typedef typename util::combine_if\r
+ <\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ // Here we want to try to remove most of the combinations\r
+ // that are not valid, mostly to limit the size of the\r
+ // resulting MPL vector.\r
+ // But is_implemented is not ready for prime time\r
+ //\r
+ // util::is_implemented2<boost::mpl::_1, boost::mpl::_2, dispatch::distance<boost::mpl::_1, boost::mpl::_2> >\r
+ boost::mpl::always<boost::mpl::true_>\r
+ >::type possible_input_types;\r
+\r
+ // The (possibly variant) result type resulting from these combinations\r
+ typedef typename compress_variant<\r
+ typename transform_variant<\r
+ possible_input_types,\r
+ resolve_strategy::distance_result<\r
+ boost::mpl::first<boost::mpl::_>,\r
+ boost::mpl::second<boost::mpl::_>,\r
+ Strategy\r
+ >,\r
+ boost::mpl::back_inserter<boost::mpl::vector0<> >\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+} // namespace resolve_variant\r
+\r
+\r
+/*!\r
+\brief Meta-function defining return type of distance function\r
+\ingroup distance\r
+\note The strategy defines the return-type (so this situation is different\r
+ from length, where distance is sqr/sqrt, but length always squared)\r
+ */\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2 = Geometry1,\r
+ typename Strategy = void\r
+>\r
+struct distance_result\r
+ : resolve_variant::distance_result<Geometry1, Geometry2, Strategy>\r
+{};\r
+\r
+\r
+template <typename Geometry1, typename Geometry2>\r
+struct distance_result<Geometry1, Geometry2, void>\r
+ : distance_result<Geometry1, Geometry2, default_strategy>\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014, 2016.\r
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP\r
+\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/radius.hpp>\r
+#include <boost/geometry/core/srs.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>\r
+#include <boost/geometry/algorithms/detail/flattening.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+\r
+/*!\r
+\brief Point-point distance approximation taking flattening into account\r
+\ingroup distance\r
+\tparam Spheroid The reference spheroid model\r
+\tparam CalculationType \tparam_calculation\r
+\author After Andoyer, 19xx, republished 1950, republished by Meeus, 1999\r
+\note Although not so well-known, the approximation is very good: in all cases the results\r
+are about the same as Vincenty. In my (Barend's) testcases the results didn't differ more than 6 m\r
+\see http://nacc.upc.es/tierra/node16.html\r
+\see http://sci.tech-archive.net/Archive/sci.geo.satellite-nav/2004-12/2724.html\r
+\see http://home.att.net/~srschmitt/great_circle_route.html (implementation)\r
+\see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)\r
+\see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)\r
+\see http://www.voidware.com/earthdist.htm (implementation)\r
+\see http://www.dtic.mil/docs/citations/AD0627893\r
+\see http://www.dtic.mil/docs/citations/AD703541\r
+*/\r
+template\r
+<\r
+ typename Spheroid,\r
+ typename CalculationType = void\r
+>\r
+class andoyer\r
+{\r
+public :\r
+ template <typename Point1, typename Point2>\r
+ struct calculation_type\r
+ : promote_floating_point\r
+ <\r
+ typename select_calculation_type\r
+ <\r
+ Point1,\r
+ Point2,\r
+ CalculationType\r
+ >::type\r
+ >\r
+ {};\r
+\r
+ typedef Spheroid model_type;\r
+\r
+ inline andoyer()\r
+ : m_spheroid()\r
+ {}\r
+\r
+ explicit inline andoyer(Spheroid const& spheroid)\r
+ : m_spheroid(spheroid)\r
+ {}\r
+\r
+ template <typename Point1, typename Point2>\r
+ inline typename calculation_type<Point1, Point2>::type\r
+ apply(Point1 const& point1, Point2 const& point2) const\r
+ {\r
+ return geometry::detail::andoyer_inverse\r
+ <\r
+ typename calculation_type<Point1, Point2>::type,\r
+ true, false\r
+ >::apply(get_as_radian<0>(point1), get_as_radian<1>(point1),\r
+ get_as_radian<0>(point2), get_as_radian<1>(point2),\r
+ m_spheroid).distance;\r
+ }\r
+\r
+ inline Spheroid const& model() const\r
+ {\r
+ return m_spheroid;\r
+ }\r
+\r
+private :\r
+ Spheroid m_spheroid;\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct tag<andoyer<Spheroid, CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>\r
+struct return_type<andoyer<Spheroid, CalculationType>, P1, P2>\r
+ : andoyer<Spheroid, CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct comparable_type<andoyer<Spheroid, CalculationType> >\r
+{\r
+ typedef andoyer<Spheroid, CalculationType> type;\r
+};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct get_comparable<andoyer<Spheroid, CalculationType> >\r
+{\r
+ static inline andoyer<Spheroid, CalculationType> apply(andoyer<Spheroid, CalculationType> const& input)\r
+ {\r
+ return input;\r
+ }\r
+};\r
+\r
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>\r
+struct result_from_distance<andoyer<Spheroid, CalculationType>, P1, P2>\r
+{\r
+ template <typename T>\r
+ static inline typename return_type<andoyer<Spheroid, CalculationType>, P1, P2>::type\r
+ apply(andoyer<Spheroid, CalculationType> const& , T const& value)\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+\r
+template <typename Point1, typename Point2>\r
+struct default_strategy<point_tag, point_tag, Point1, Point2, geographic_tag, geographic_tag>\r
+{\r
+ typedef strategy::distance::andoyer\r
+ <\r
+ srs::spheroid\r
+ <\r
+ typename select_coordinate_type<Point1, Point2>::type\r
+ >\r
+ > type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_ANDOYER_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP\r
+\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/thomas_inverse.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+/*!\r
+\brief The solution of the inverse problem of geodesics on latlong coordinates,\r
+ Forsyth-Andoyer-Lambert type approximation with second order terms.\r
+\ingroup distance\r
+\tparam Spheroid The reference spheroid model\r
+\tparam CalculationType \tparam_calculation\r
+\author See\r
+ - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965\r
+ http://www.dtic.mil/docs/citations/AD0627893\r
+ - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970\r
+ http://www.dtic.mil/docs/citations/AD703541\r
+*/\r
+template\r
+<\r
+ typename Spheroid,\r
+ typename CalculationType = void\r
+>\r
+class thomas\r
+{\r
+public :\r
+ template <typename Point1, typename Point2>\r
+ struct calculation_type\r
+ : promote_floating_point\r
+ <\r
+ typename select_calculation_type\r
+ <\r
+ Point1,\r
+ Point2,\r
+ CalculationType\r
+ >::type\r
+ >\r
+ {};\r
+\r
+ typedef Spheroid model_type;\r
+\r
+ inline thomas()\r
+ : m_spheroid()\r
+ {}\r
+\r
+ explicit inline thomas(Spheroid const& spheroid)\r
+ : m_spheroid(spheroid)\r
+ {}\r
+\r
+ template <typename Point1, typename Point2>\r
+ inline typename calculation_type<Point1, Point2>::type\r
+ apply(Point1 const& point1, Point2 const& point2) const\r
+ {\r
+ return geometry::detail::thomas_inverse\r
+ <\r
+ typename calculation_type<Point1, Point2>::type,\r
+ true, false\r
+ >::apply(get_as_radian<0>(point1),\r
+ get_as_radian<1>(point1),\r
+ get_as_radian<0>(point2),\r
+ get_as_radian<1>(point2),\r
+ m_spheroid).distance;\r
+ }\r
+\r
+ inline Spheroid const& model() const\r
+ {\r
+ return m_spheroid;\r
+ }\r
+\r
+private :\r
+ Spheroid m_spheroid;\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct tag<thomas<Spheroid, CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>\r
+struct return_type<thomas<Spheroid, CalculationType>, P1, P2>\r
+ : thomas<Spheroid, CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct comparable_type<thomas<Spheroid, CalculationType> >\r
+{\r
+ typedef thomas<Spheroid, CalculationType> type;\r
+};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct get_comparable<thomas<Spheroid, CalculationType> >\r
+{\r
+ static inline thomas<Spheroid, CalculationType> apply(thomas<Spheroid, CalculationType> const& input)\r
+ {\r
+ return input;\r
+ }\r
+};\r
+\r
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>\r
+struct result_from_distance<thomas<Spheroid, CalculationType>, P1, P2 >\r
+{\r
+ template <typename T>\r
+ static inline typename return_type<thomas<Spheroid, CalculationType>, P1, P2>::type\r
+ apply(thomas<Spheroid, CalculationType> const& , T const& value)\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_THOMAS_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP\r
+\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+/*!\r
+\brief Distance calculation formulae on latlong coordinates, after Vincenty, 1975\r
+\ingroup distance\r
+\tparam Spheroid The reference spheroid model\r
+\tparam CalculationType \tparam_calculation\r
+\author See\r
+ - http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf\r
+ - http://www.icsm.gov.au/gda/gdav2.3.pdf\r
+\author Adapted from various implementations to get it close to the original document\r
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html\r
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html\r
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink\r
+\r
+*/\r
+template\r
+<\r
+ typename Spheroid,\r
+ typename CalculationType = void\r
+>\r
+class vincenty\r
+{\r
+public :\r
+ template <typename Point1, typename Point2>\r
+ struct calculation_type\r
+ : promote_floating_point\r
+ <\r
+ typename select_calculation_type\r
+ <\r
+ Point1,\r
+ Point2,\r
+ CalculationType\r
+ >::type\r
+ >\r
+ {};\r
+\r
+ typedef Spheroid model_type;\r
+\r
+ inline vincenty()\r
+ : m_spheroid()\r
+ {}\r
+\r
+ explicit inline vincenty(Spheroid const& spheroid)\r
+ : m_spheroid(spheroid)\r
+ {}\r
+\r
+ template <typename Point1, typename Point2>\r
+ inline typename calculation_type<Point1, Point2>::type\r
+ apply(Point1 const& point1, Point2 const& point2) const\r
+ {\r
+ return geometry::detail::vincenty_inverse\r
+ <\r
+ typename calculation_type<Point1, Point2>::type,\r
+ true, false\r
+ >::apply(get_as_radian<0>(point1),\r
+ get_as_radian<1>(point1),\r
+ get_as_radian<0>(point2),\r
+ get_as_radian<1>(point2),\r
+ m_spheroid).distance;\r
+ }\r
+\r
+ inline Spheroid const& model() const\r
+ {\r
+ return m_spheroid;\r
+ }\r
+\r
+private :\r
+ Spheroid m_spheroid;\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct tag<vincenty<Spheroid, CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>\r
+struct return_type<vincenty<Spheroid, CalculationType>, P1, P2>\r
+ : vincenty<Spheroid, CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct comparable_type<vincenty<Spheroid, CalculationType> >\r
+{\r
+ typedef vincenty<Spheroid, CalculationType> type;\r
+};\r
+\r
+\r
+template <typename Spheroid, typename CalculationType>\r
+struct get_comparable<vincenty<Spheroid, CalculationType> >\r
+{\r
+ static inline vincenty<Spheroid, CalculationType> apply(vincenty<Spheroid, CalculationType> const& input)\r
+ {\r
+ return input;\r
+ }\r
+};\r
+\r
+template <typename Spheroid, typename CalculationType, typename P1, typename P2>\r
+struct result_from_distance<vincenty<Spheroid, CalculationType>, P1, P2 >\r
+{\r
+ template <typename T>\r
+ static inline typename return_type<vincenty<Spheroid, CalculationType>, P1, P2>::type\r
+ apply(vincenty<Spheroid, CalculationType> const& , T const& value)\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+// We might add a vincenty-like strategy also for point-segment distance, but to calculate the projected point is not trivial\r
+\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_VINCENTY_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP\r
+\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/geometry/core/radius.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/spherical/ssf.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+\r
+// An enumeration type defining types of mapping of geographical\r
+// latitude to spherical latitude.\r
+// See: http://en.wikipedia.org/wiki/Great_ellipse\r
+// http://en.wikipedia.org/wiki/Latitude#Auxiliary_latitudes\r
+enum mapping_type { mapping_geodetic, mapping_reduced, mapping_geocentric };\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Spheroid, mapping_type Mapping>\r
+struct mapper\r
+{\r
+ explicit inline mapper(Spheroid const& /*spheroid*/) {}\r
+\r
+ template <typename CalculationType>\r
+ static inline CalculationType const& apply(CalculationType const& lat)\r
+ {\r
+ return lat;\r
+ }\r
+};\r
+\r
+template <typename Spheroid>\r
+struct mapper<Spheroid, mapping_reduced>\r
+{\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename radius_type<Spheroid>::type\r
+ >::type fraction_type;\r
+\r
+ explicit inline mapper(Spheroid const& spheroid)\r
+ {\r
+ fraction_type const a = geometry::get_radius<0>(spheroid);\r
+ fraction_type const b = geometry::get_radius<2>(spheroid);\r
+ b_div_a = b / a;\r
+ }\r
+\r
+ template <typename CalculationType>\r
+ inline CalculationType apply(CalculationType const& lat) const\r
+ {\r
+ return atan(static_cast<CalculationType>(b_div_a) * tan(lat));\r
+ }\r
+\r
+ fraction_type b_div_a;\r
+};\r
+\r
+template <typename Spheroid>\r
+struct mapper<Spheroid, mapping_geocentric>\r
+{\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename radius_type<Spheroid>::type\r
+ >::type fraction_type;\r
+\r
+ explicit inline mapper(Spheroid const& spheroid)\r
+ {\r
+ fraction_type const a = geometry::get_radius<0>(spheroid);\r
+ fraction_type const b = geometry::get_radius<2>(spheroid);\r
+ sqr_b_div_a = b / a;\r
+ sqr_b_div_a *= sqr_b_div_a;\r
+ }\r
+\r
+ template <typename CalculationType>\r
+ inline CalculationType apply(CalculationType const& lat) const\r
+ {\r
+ return atan(static_cast<CalculationType>(sqr_b_div_a) * tan(lat));\r
+ }\r
+\r
+ fraction_type sqr_b_div_a;\r
+};\r
+\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Check at which side of a geographical segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0).\r
+ The check is performed by mapping the geographical coordinates\r
+ to spherical coordinates and using spherical_side_formula.\r
+\ingroup strategies\r
+\tparam Spheroid The reference spheroid model\r
+\tparam Mapping The type of mapping of geographical to spherical latitude\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename Spheroid,\r
+ mapping_type Mapping = mapping_geodetic,\r
+ typename CalculationType = void>\r
+class mapping_spherical_side_formula\r
+{\r
+\r
+public :\r
+ inline mapping_spherical_side_formula()\r
+ : m_mapper(Spheroid())\r
+ {}\r
+\r
+ explicit inline mapping_spherical_side_formula(Spheroid const& spheroid)\r
+ : m_mapper(spheroid)\r
+ {}\r
+\r
+ template <typename P1, typename P2, typename P>\r
+ inline int apply(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename select_calculation_type_alt\r
+ <\r
+ CalculationType,\r
+ P1, P2, P\r
+ >::type\r
+ >::type calculation_type;\r
+\r
+ calculation_type lon1 = get_as_radian<0>(p1);\r
+ calculation_type lat1 = m_mapper.template apply<calculation_type>(get_as_radian<1>(p1));\r
+ calculation_type lon2 = get_as_radian<0>(p2);\r
+ calculation_type lat2 = m_mapper.template apply<calculation_type>(get_as_radian<1>(p2));\r
+ calculation_type lon = get_as_radian<0>(p);\r
+ calculation_type lat = m_mapper.template apply<calculation_type>(get_as_radian<1>(p));\r
+\r
+ return detail::spherical_side_formula(lon1, lat1, lon2, lat2, lon, lat);\r
+ }\r
+\r
+private:\r
+ side::detail::mapper<Spheroid, Mapping> const m_mapper;\r
+};\r
+\r
+// The specialization for geodetic latitude which can be used directly\r
+template <typename Spheroid,\r
+ typename CalculationType>\r
+class mapping_spherical_side_formula<Spheroid, mapping_geodetic, CalculationType>\r
+{\r
+\r
+public :\r
+ inline mapping_spherical_side_formula() {}\r
+ explicit inline mapping_spherical_side_formula(Spheroid const& /*spheroid*/) {}\r
+\r
+ template <typename P1, typename P2, typename P>\r
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ return spherical_side_formula<CalculationType>::apply(p1, p2, p);\r
+ }\r
+};\r
+\r
+}} // namespace strategy::side\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/andoyer_inverse.hpp>\r
+\r
+#include <boost/geometry/strategies/geographic/side_detail.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+/*!\r
+\brief Check at which side of a segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam Model Reference model of coordinate system.\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename Model, typename CalculationType = void>\r
+class andoyer\r
+ : public detail::by_azimuth<geometry::detail::andoyer_inverse, Model, CalculationType>\r
+{\r
+ typedef detail::by_azimuth<geometry::detail::andoyer_inverse, Model, CalculationType> base_t;\r
+\r
+public:\r
+ andoyer(Model const& model = Model())\r
+ : base_t(model)\r
+ {}\r
+};\r
+\r
+}} // namespace strategy::side\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_ANDOYER_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/radius.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+/*!\r
+\brief Check at which side of a segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam InverseFormula Geodesic inverse solution formula.\r
+\tparam Model Reference model of coordinate system.\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <template<typename, bool, bool> class InverseFormula,\r
+ typename Model,\r
+ typename CalculationType = void>\r
+class by_azimuth\r
+{\r
+public:\r
+ by_azimuth(Model const& model = Model())\r
+ : m_model(model)\r
+ {}\r
+\r
+ template <typename P1, typename P2, typename P>\r
+ inline int apply(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename select_calculation_type_alt\r
+ <\r
+ CalculationType,\r
+ P1, P2, P\r
+ >::type\r
+ >::type calc_t;\r
+\r
+ typedef InverseFormula<calc_t, false, true> inverse_formula;\r
+\r
+ calc_t a1p = azimuth<calc_t, inverse_formula>(p1, p, m_model);\r
+ calc_t a12 = azimuth<calc_t, inverse_formula>(p1, p2, m_model);\r
+\r
+ calc_t const pi = math::pi<calc_t>();\r
+\r
+ // instead of the formula from XTD\r
+ //calc_t a_diff = asin(sin(a1p - a12));\r
+\r
+ calc_t a_diff = a1p - a12;\r
+ // normalize, angle in [-pi, pi]\r
+ while ( a_diff > pi )\r
+ a_diff -= calc_t(2) * pi;\r
+ while ( a_diff < -pi )\r
+ a_diff += calc_t(2) * pi;\r
+\r
+ // NOTE: in general it shouldn't be required to support the pi/-pi case\r
+ // because in non-cartesian systems it makes sense to check the side\r
+ // only "between" the endpoints.\r
+ // However currently the winding strategy calls the side strategy\r
+ // for vertical segments to check if the point is "between the endpoints.\r
+ // This could be avoided since the side strategy is not required for that\r
+ // because meridian is the shortest path. So a difference of\r
+ // longitudes would be sufficient (of course normalized to [-pi, pi]).\r
+\r
+ // NOTE: with the above said, the pi/-pi check is temporary\r
+ // however in case if this was required\r
+ // the geodesics on ellipsoid aren't "symmetrical"\r
+ // therefore instead of comparing a_diff to pi and -pi\r
+ // one should probably use inverse azimuths and compare\r
+ // the difference to 0 as well\r
+\r
+ // positive azimuth is on the right side\r
+ return math::equals(a_diff, 0)\r
+ || math::equals(a_diff, pi)\r
+ || math::equals(a_diff, -pi) ? 0\r
+ : a_diff > 0 ? -1 // right\r
+ : 1; // left\r
+ }\r
+\r
+private:\r
+ template <typename ResultType,\r
+ typename InverseFormulaType,\r
+ typename Point1,\r
+ typename Point2,\r
+ typename ModelT>\r
+ static inline ResultType azimuth(Point1 const& point1, Point2 const& point2, ModelT const& model)\r
+ {\r
+ return InverseFormulaType::apply(get_as_radian<0>(point1),\r
+ get_as_radian<1>(point1),\r
+ get_as_radian<0>(point2),\r
+ get_as_radian<1>(point2),\r
+ model).azimuth;\r
+ }\r
+\r
+ Model m_model;\r
+};\r
+\r
+} // detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+}} // namespace strategy::side\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_DETAIL_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/thomas_inverse.hpp>\r
+\r
+#include <boost/geometry/strategies/geographic/side_detail.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+/*!\r
+\brief Check at which side of a segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam Model Reference model of coordinate system.\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename Model, typename CalculationType = void>\r
+class thomas\r
+ : public detail::by_azimuth<geometry::detail::thomas_inverse, Model, CalculationType>\r
+{\r
+ typedef detail::by_azimuth<geometry::detail::thomas_inverse, Model, CalculationType> base_t;\r
+\r
+public:\r
+ thomas(Model const& model = Model())\r
+ : base_t(model)\r
+ {}\r
+};\r
+\r
+}} // namespace strategy::side\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_THOMAS_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP\r
+\r
+\r
+#include <boost/geometry/algorithms/detail/vincenty_inverse.hpp>\r
+\r
+#include <boost/geometry/strategies/geographic/side_detail.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+/*!\r
+\brief Check at which side of a segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam Model Reference model of coordinate system.\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename Model, typename CalculationType = void>\r
+class vincenty\r
+ : public detail::by_azimuth<geometry::detail::vincenty_inverse, Model, CalculationType>\r
+{\r
+ typedef detail::by_azimuth<geometry::detail::vincenty_inverse, Model, CalculationType> base_t;\r
+\r
+public:\r
+ vincenty(Model const& model = Model())\r
+ : base_t(model)\r
+ {}\r
+};\r
+\r
+}} // namespace strategy::side\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_SIDE_VINCENTY_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2016, Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SEGMENT_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SEGMENT_INTERSECTION_HPP\r
+\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace intersection\r
+{\r
+\r
+namespace services\r
+{\r
+\r
+/*!\r
+\brief Traits class binding a segments intersection strategy to a coordinate system\r
+\ingroup util\r
+\tparam CSTag tag of coordinate system of point-type\r
+\tparam Policy intersection policy\r
+\tparam CalculationType \tparam_calculation\r
+*/\r
+template <typename CSTag, typename Policy, typename CalculationType = void>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE\r
+ , (types<CSTag>)\r
+ );\r
+};\r
+\r
+} // namespace services\r
+\r
+}} // namespace strategy::intersection\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SEGMENT_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015, 2016.\r
+// Modifications copyright (c) 2015-2016 Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP\r
+\r
+#if defined(HAVE_MATRIX_AS_STRING)\r
+#include <string>\r
+#endif\r
+\r
+#include <cstddef>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+template <typename SegmentRatio>\r
+struct fraction_type\r
+{\r
+ SegmentRatio robust_ra; // TODO this can be renamed now to "ra"\r
+ SegmentRatio robust_rb;\r
+\r
+ bool initialized;\r
+ inline fraction_type()\r
+ : initialized(false)\r
+ {}\r
+\r
+ template <typename Info>\r
+ inline void assign(Info const& info)\r
+ {\r
+ initialized = true;\r
+ robust_ra = info.robust_ra;\r
+ robust_rb = info.robust_rb;\r
+ }\r
+\r
+ inline void assign(SegmentRatio const& a, SegmentRatio const& b)\r
+ {\r
+ initialized = true;\r
+ robust_ra = a;\r
+ robust_rb = b;\r
+ }\r
+\r
+};\r
+\r
+//\r
+/*!\r
+\brief return-type for segment-intersection\r
+\note Set in intersection_points.hpp, from segment_intersection_info\r
+*/\r
+template <typename Point, typename SegmentRatio>\r
+struct segment_intersection_points\r
+{\r
+ std::size_t count; // The number of intersection points\r
+\r
+ // TODO: combine intersections and fractions in one struct\r
+ Point intersections[2];\r
+ fraction_type<SegmentRatio> fractions[2];\r
+ typedef Point point_type;\r
+\r
+ segment_intersection_points()\r
+ : count(0)\r
+ {}\r
+};\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP\r
+\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/geometries/segment.hpp>\r
+\r
+#include <boost/geometry/policies/relate/intersection_points.hpp>\r
+#include <boost/geometry/policies/relate/direction.hpp>\r
+#include <boost/geometry/policies/relate/tupled.hpp>\r
+\r
+#include <boost/geometry/strategies/intersection.hpp>\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/intersection_result.hpp>\r
+\r
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>\r
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>\r
+#include <boost/geometry/strategies/spherical/intersection.hpp>\r
+#include <boost/geometry/strategies/spherical/ssf.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+\brief "compound strategy", containing a segment-intersection-strategy\r
+ and a side-strategy\r
+ */\r
+template\r
+<\r
+ typename Tag,\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename IntersectionPoint,\r
+ typename RobustPolicy,\r
+ typename CalculationType = void\r
+>\r
+struct intersection_strategies\r
+{\r
+private :\r
+ // for development BOOST_STATIC_ASSERT((! boost::is_same<RobustPolicy, void>::type::value));\r
+\r
+ typedef typename geometry::point_type<Geometry1>::type point1_type;\r
+ typedef typename geometry::point_type<Geometry2>::type point2_type;\r
+ typedef typename model::referring_segment<point1_type const> segment1_type;\r
+ typedef typename model::referring_segment<point2_type const> segment2_type;\r
+\r
+ typedef segment_intersection_points\r
+ <\r
+ IntersectionPoint,\r
+ typename geometry::segment_ratio_type\r
+ <\r
+ IntersectionPoint, RobustPolicy\r
+ >::type\r
+ > ip_type;\r
+\r
+public:\r
+ typedef typename strategy::intersection::services::default_strategy\r
+ <\r
+ Tag,\r
+ policies::relate::segments_tupled\r
+ <\r
+ policies::relate::segments_intersection_points\r
+ <\r
+ ip_type\r
+ > ,\r
+ policies::relate::segments_direction\r
+ >,\r
+ CalculationType\r
+ >::type segment_intersection_strategy_type;\r
+\r
+ typedef typename strategy::side::services::default_strategy\r
+ <\r
+ Tag,\r
+ CalculationType\r
+ >::type side_strategy_type;\r
+\r
+ typedef RobustPolicy rescale_policy_type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SIDE_HPP\r
+\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+namespace services\r
+{\r
+\r
+/*!\r
+\brief Traits class binding a side determination strategy to a coordinate system\r
+\ingroup util\r
+\tparam Tag tag of coordinate system of point-type\r
+\tparam CalculationType \tparam_calculation\r
+*/\r
+template <typename Tag, typename CalculationType = void>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE\r
+ , (types<Tag>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+}} // namespace strategy::side\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP\r
+\r
+#include <cmath>\r
+#include <utility>\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)\r
+# include <iostream>\r
+#endif\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+/*!\r
+\brief Class side_info: small class wrapping for sides (-1,0,1)\r
+*/\r
+class side_info\r
+{\r
+public :\r
+ inline side_info(int side_a1 = 0, int side_a2 = 0,\r
+ int side_b1 = 0, int side_b2 = 0)\r
+ {\r
+ sides[0].first = side_a1;\r
+ sides[0].second = side_a2;\r
+ sides[1].first = side_b1;\r
+ sides[1].second = side_b2;\r
+ }\r
+\r
+ template <int Which>\r
+ inline void set(int first, int second)\r
+ {\r
+ sides[Which].first = first;\r
+ sides[Which].second = second;\r
+ }\r
+\r
+ template <int Which, int Index>\r
+ inline void correct_to_zero()\r
+ {\r
+ if (Index == 0)\r
+ {\r
+ sides[Which].first = 0;\r
+ }\r
+ else\r
+ {\r
+ sides[Which].second = 0;\r
+ }\r
+ }\r
+\r
+ template <int Which, int Index>\r
+ inline int get() const\r
+ {\r
+ return Index == 0 ? sides[Which].first : sides[Which].second;\r
+ }\r
+\r
+\r
+ // Returns true if both lying on the same side WRT the other\r
+ // (so either 1,1 or -1-1)\r
+ template <int Which>\r
+ inline bool same() const\r
+ {\r
+ return sides[Which].first * sides[Which].second == 1;\r
+ }\r
+\r
+ inline bool collinear() const\r
+ {\r
+ return sides[0].first == 0\r
+ && sides[0].second == 0\r
+ && sides[1].first == 0\r
+ && sides[1].second == 0;\r
+ }\r
+\r
+ inline bool crossing() const\r
+ {\r
+ return sides[0].first * sides[0].second == -1\r
+ && sides[1].first * sides[1].second == -1;\r
+ }\r
+\r
+ inline bool touching() const\r
+ {\r
+ return (sides[0].first * sides[1].first == -1\r
+ && sides[0].second == 0 && sides[1].second == 0)\r
+ || (sides[1].first * sides[0].first == -1\r
+ && sides[1].second == 0 && sides[0].second == 0);\r
+ }\r
+\r
+ template <int Which>\r
+ inline bool one_touching() const\r
+ {\r
+ // This is normally a situation which can't occur:\r
+ // If one is completely left or right, the other cannot touch\r
+ return one_zero<Which>()\r
+ && sides[1 - Which].first * sides[1 - Which].second == 1;\r
+ }\r
+\r
+ inline bool meeting() const\r
+ {\r
+ // Two of them (in each segment) zero, two not\r
+ return one_zero<0>() && one_zero<1>();\r
+ }\r
+\r
+ template <int Which>\r
+ inline bool zero() const\r
+ {\r
+ return sides[Which].first == 0 && sides[Which].second == 0;\r
+ }\r
+\r
+ template <int Which>\r
+ inline bool one_zero() const\r
+ {\r
+ return (sides[Which].first == 0 && sides[Which].second != 0)\r
+ || (sides[Which].first != 0 && sides[Which].second == 0);\r
+ }\r
+\r
+ inline bool one_of_all_zero() const\r
+ {\r
+ int const sum = std::abs(sides[0].first)\r
+ + std::abs(sides[0].second)\r
+ + std::abs(sides[1].first)\r
+ + std::abs(sides[1].second);\r
+ return sum == 3;\r
+ }\r
+\r
+\r
+ template <int Which>\r
+ inline int zero_index() const\r
+ {\r
+ return sides[Which].first == 0 ? 0 : 1;\r
+ }\r
+\r
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)\r
+ inline void debug() const\r
+ {\r
+ std::cout << sides[0].first << " "\r
+ << sides[0].second << " "\r
+ << sides[1].first << " "\r
+ << sides[1].second\r
+ << std::endl;\r
+ }\r
+#endif\r
+\r
+ inline void reverse()\r
+ {\r
+ std::swap(sides[0], sides[1]);\r
+ }\r
+\r
+//private :\r
+ std::pair<int, int> sides[2];\r
+\r
+};\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP\r
+\r
+\r
+\r
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>\r
+\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace area\r
+{\r
+\r
+\r
+\r
+/*!\r
+\brief Area calculation by spherical excess / Huiller's formula\r
+\ingroup strategies\r
+\tparam PointOfSegment point type of segments of rings/polygons\r
+\tparam CalculationType \tparam_calculation\r
+\author Barend Gehrels. Adapted from:\r
+- http://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsiv/sph_poly.c\r
+- http://tog.acm.org/resources/GraphicsGems/gemsiv/sph_poly.c\r
+- http://williams.best.vwh.net/avform.htm\r
+\note The version in Graphics Gems IV (page 132-137) didn't account for\r
+polygons crossing the 0 and 180 meridians. The fix for this algorithm\r
+can be found in Graphics Gems V (pages 45-46). See:\r
+- http://kysmykseka.net/koti/wizardry/Game%20Development/Programming/Graphics%20Gems%204.pdf\r
+- http://kysmykseka.net/koti/wizardry/Game%20Development/Programming/Graphics%20Gems%205.pdf\r
+\note This version works for convex and non-convex polygons, for 180 meridian\r
+crossing polygons and for polygons with holes. However, some cases (especially\r
+180 meridian cases) must still be checked.\r
+\note The version which sums angles, which is often seen, doesn't handle non-convex\r
+polygons correctly.\r
+\note The version which sums longitudes, see http://hdl.handle.net/2014/40409,\r
+is simple and works well in most cases but not in 180 meridian crossing cases.\r
+This probably could be solved.\r
+\r
+\note This version is made for spherical equatorial coordinate systems\r
+\r
+\qbk{\r
+\r
+[heading Example]\r
+[area_with_strategy]\r
+[area_with_strategy_output]\r
+\r
+\r
+[heading See also]\r
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename PointOfSegment,\r
+ typename CalculationType = void\r
+>\r
+class huiller\r
+{\r
+typedef typename boost::mpl::if_c\r
+ <\r
+ boost::is_void<CalculationType>::type::value,\r
+ typename select_most_precise\r
+ <\r
+ typename coordinate_type<PointOfSegment>::type,\r
+ double\r
+ >::type,\r
+ CalculationType\r
+ >::type calculation_type;\r
+\r
+protected :\r
+ struct excess_sum\r
+ {\r
+ calculation_type sum;\r
+\r
+ // Distances are calculated on unit sphere here\r
+ strategy::distance::haversine<calculation_type> distance_over_unit_sphere;\r
+\r
+\r
+ inline excess_sum()\r
+ : sum(0)\r
+ , distance_over_unit_sphere(1)\r
+ {}\r
+ inline calculation_type area(calculation_type radius) const\r
+ {\r
+ return - sum * radius * radius;\r
+ }\r
+ };\r
+\r
+public :\r
+ typedef calculation_type return_type;\r
+ typedef PointOfSegment segment_point_type;\r
+ typedef excess_sum state_type;\r
+\r
+ inline huiller(calculation_type radius = 1.0)\r
+ : m_radius(radius)\r
+ {}\r
+\r
+ inline void apply(PointOfSegment const& p1,\r
+ PointOfSegment const& p2,\r
+ excess_sum& state) const\r
+ {\r
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))\r
+ {\r
+ calculation_type const half = 0.5;\r
+ calculation_type const two = 2.0;\r
+ calculation_type const four = 4.0;\r
+ calculation_type const pi\r
+ = geometry::math::pi<calculation_type>();\r
+ calculation_type const two_pi\r
+ = geometry::math::two_pi<calculation_type>();\r
+ calculation_type const half_pi\r
+ = geometry::math::half_pi<calculation_type>();\r
+\r
+ // Distance p1 p2\r
+ calculation_type a = state.distance_over_unit_sphere.apply(p1, p2);\r
+\r
+ // Sides on unit sphere to south pole\r
+ calculation_type b = half_pi - geometry::get_as_radian<1>(p2);\r
+ calculation_type c = half_pi - geometry::get_as_radian<1>(p1);\r
+\r
+ // Semi parameter\r
+ calculation_type s = half * (a + b + c);\r
+\r
+ // E: spherical excess, using l'Huiller's formula\r
+ // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2]\r
+ calculation_type excess = four\r
+ * atan(geometry::math::sqrt(geometry::math::abs(tan(s / two)\r
+ * tan((s - a) / two)\r
+ * tan((s - b) / two)\r
+ * tan((s - c) / two))));\r
+\r
+ excess = geometry::math::abs(excess);\r
+\r
+ // In right direction: positive, add area. In left direction: negative, subtract area.\r
+ // Longitude comparisons are not so obvious. If one is negative and other is positive,\r
+ // we have to take the dateline into account.\r
+\r
+ calculation_type lon_diff = geometry::get_as_radian<0>(p2)\r
+ - geometry::get_as_radian<0>(p1);\r
+ if (lon_diff <= 0)\r
+ {\r
+ lon_diff += two_pi;\r
+ }\r
+\r
+ if (lon_diff > pi)\r
+ {\r
+ excess = -excess;\r
+ }\r
+\r
+ state.sum += excess;\r
+ }\r
+ }\r
+\r
+ inline return_type result(excess_sum const& state) const\r
+ {\r
+ return state.area(m_radius);\r
+ }\r
+\r
+private :\r
+ /// Radius of the sphere\r
+ calculation_type m_radius;\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+\r
+template <typename Point>\r
+struct default_strategy<spherical_equatorial_tag, Point>\r
+{\r
+ typedef strategy::area::huiller<Point> type;\r
+};\r
+\r
+// Note: spherical polar coordinate system requires "get_as_radian_equatorial"\r
+/***template <typename Point>\r
+struct default_strategy<spherical_polar_tag, Point>\r
+{\r
+ typedef strategy::area::huiller<Point> type;\r
+};***/\r
+\r
+} // namespace services\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::area\r
+\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/strategies/compare.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace compare\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Units>\r
+struct shift\r
+{\r
+};\r
+\r
+template <>\r
+struct shift<degree>\r
+{\r
+ static inline double full() { return 360.0; }\r
+ static inline double half() { return 180.0; }\r
+};\r
+\r
+template <>\r
+struct shift<radian>\r
+{\r
+ static inline double full() { return 2.0 * boost::math::constants::pi<double>(); }\r
+ static inline double half() { return boost::math::constants::pi<double>(); }\r
+};\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+/*!\r
+\brief Compare (in one direction) strategy for spherical coordinates\r
+\ingroup strategies\r
+\tparam Point point-type\r
+\tparam Dimension dimension\r
+*/\r
+template <typename CoordinateType, typename Units, typename Compare>\r
+struct circular_comparator\r
+{\r
+ static inline CoordinateType put_in_range(CoordinateType const& c,\r
+ double min_border, double max_border)\r
+ {\r
+ CoordinateType value = c;\r
+ while (value < min_border)\r
+ {\r
+ value += detail::shift<Units>::full();\r
+ }\r
+ while (value > max_border)\r
+ {\r
+ value -= detail::shift<Units>::full();\r
+ }\r
+ return value;\r
+ }\r
+\r
+ inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const\r
+ {\r
+ Compare compare;\r
+\r
+ // Check situation that one of them is e.g. std::numeric_limits.\r
+ static const double full = detail::shift<Units>::full();\r
+ double mx = 10.0 * full;\r
+ if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)\r
+ {\r
+ // do normal comparison, using circular is not useful\r
+ return compare(c1, c2);\r
+ }\r
+\r
+ static const double half = full / 2.0;\r
+ CoordinateType v1 = put_in_range(c1, -half, half);\r
+ CoordinateType v2 = put_in_range(c2, -half, half);\r
+\r
+ // Two coordinates on a circle are\r
+ // at max <= half a circle away from each other.\r
+ // So if it is more, shift origin.\r
+ CoordinateType diff = geometry::math::abs(v1 - v2);\r
+ if (diff > half)\r
+ {\r
+ v1 = put_in_range(v1, 0, full);\r
+ v2 = put_in_range(v2, 0, full);\r
+ }\r
+\r
+ return compare(v1, v2);\r
+ }\r
+};\r
+\r
+}} // namespace strategy::compare\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+// Specialize for the longitude (dim 0)\r
+template\r
+<\r
+ typename Point,\r
+ template<typename> class CoordinateSystem,\r
+ typename Units\r
+>\r
+struct strategy_compare<spherical_polar_tag, 1, Point, CoordinateSystem<Units>, 0>\r
+{\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+ typedef strategy::compare::circular_comparator\r
+ <\r
+ coordinate_type,\r
+ Units,\r
+ std::less<coordinate_type>\r
+ > type;\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ template<typename> class CoordinateSystem,\r
+ typename Units\r
+>\r
+struct strategy_compare<spherical_polar_tag, -1, Point, CoordinateSystem<Units>, 0>\r
+{\r
+ typedef typename coordinate_type<Point>::type coordinate_type;\r
+ typedef strategy::compare::circular_comparator\r
+ <\r
+ coordinate_type,\r
+ Units,\r
+ std::greater<coordinate_type>\r
+ > type;\r
+};\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/course.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>\r
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK\r
+# include <boost/geometry/io/dsv/write.hpp>\r
+#endif\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+\r
+namespace comparable\r
+{\r
+\r
+/*\r
+ Given a spherical segment AB and a point D, we are interested in\r
+ computing the distance of D from AB. This is usually known as the\r
+ cross track distance.\r
+\r
+ If the projection (along great circles) of the point D lies inside\r
+ the segment AB, then the distance (cross track error) XTD is given\r
+ by the formula (see http://williams.best.vwh.net/avform.htm#XTE):\r
+\r
+ XTD = asin( sin(dist_AD) * sin(crs_AD-crs_AB) )\r
+\r
+ where dist_AD is the great circle distance between the points A and\r
+ B, and crs_AD, crs_AB is the course (bearing) between the points A,\r
+ D and A, B, respectively.\r
+\r
+ If the point D does not project inside the arc AB, then the distance\r
+ of D from AB is the minimum of the two distances dist_AD and dist_BD.\r
+\r
+ Our reference implementation for this procedure is listed below\r
+ (this was the old Boost.Geometry implementation of the cross track distance),\r
+ where:\r
+ * The member variable m_strategy is the underlying haversine strategy.\r
+ * p stands for the point D.\r
+ * sp1 stands for the segment endpoint A.\r
+ * sp2 stands for the segment endpoint B.\r
+\r
+ ================= reference implementation -- start =================\r
+\r
+ return_type d1 = m_strategy.apply(sp1, p);\r
+ return_type d3 = m_strategy.apply(sp1, sp2);\r
+\r
+ if (geometry::math::equals(d3, 0.0))\r
+ {\r
+ // "Degenerate" segment, return either d1 or d2\r
+ return d1;\r
+ }\r
+\r
+ return_type d2 = m_strategy.apply(sp2, p);\r
+\r
+ return_type crs_AD = geometry::detail::course<return_type>(sp1, p);\r
+ return_type crs_AB = geometry::detail::course<return_type>(sp1, sp2);\r
+ return_type crs_BA = crs_AB - geometry::math::pi<return_type>();\r
+ return_type crs_BD = geometry::detail::course<return_type>(sp2, p);\r
+ return_type d_crs1 = crs_AD - crs_AB;\r
+ return_type d_crs2 = crs_BD - crs_BA;\r
+\r
+ // d1, d2, d3 are in principle not needed, only the sign matters\r
+ return_type projection1 = cos( d_crs1 ) * d1 / d3;\r
+ return_type projection2 = cos( d_crs2 ) * d2 / d3;\r
+\r
+ if (projection1 > 0.0 && projection2 > 0.0)\r
+ {\r
+ return_type XTD\r
+ = radius() * math::abs( asin( sin( d1 / radius() ) * sin( d_crs1 ) ));\r
+\r
+ // Return shortest distance, projected point on segment sp1-sp2\r
+ return return_type(XTD);\r
+ }\r
+ else\r
+ {\r
+ // Return shortest distance, project either on point sp1 or sp2\r
+ return return_type( (std::min)( d1 , d2 ) );\r
+ }\r
+\r
+ ================= reference implementation -- end =================\r
+\r
+\r
+ Motivation\r
+ ----------\r
+ In what follows we develop a comparable version of the cross track\r
+ distance strategy, that meets the following goals:\r
+ * It is more efficient than the original cross track strategy (less\r
+ operations and less calls to mathematical functions).\r
+ * Distances using the comparable cross track strategy can not only\r
+ be compared with other distances using the same strategy, but also with\r
+ distances computed with the comparable version of the haversine strategy.\r
+ * It can serve as the basis for the computation of the cross track distance,\r
+ as it is more efficient to compute its comparable version and\r
+ transform that to the actual cross track distance, rather than\r
+ follow/use the reference implementation listed above.\r
+\r
+ Major idea\r
+ ----------\r
+ The idea here is to use the comparable haversine strategy to compute\r
+ the distances d1, d2 and d3 in the above listing. Once we have done\r
+ that we need also to make sure that instead of returning XTD (as\r
+ computed above) that we return a distance CXTD that is compatible\r
+ with the comparable haversine distance. To achieve this CXTD must satisfy\r
+ the relation:\r
+ XTD = 2 * R * asin( sqrt(XTD) )\r
+ where R is the sphere's radius.\r
+\r
+ Below we perform the mathematical analysis that show how to compute CXTD.\r
+\r
+\r
+ Mathematical analysis\r
+ ---------------------\r
+ Below we use the following trigonometric identities:\r
+ sin(2 * x) = 2 * sin(x) * cos(x)\r
+ cos(asin(x)) = sqrt(1 - x^2)\r
+\r
+ Observation:\r
+ The distance d1 needed when the projection of the point D is within the\r
+ segment must be the true distance. However, comparable::haversine<>\r
+ returns a comparable distance instead of the one needed.\r
+ To remedy this, we implicitly compute what is needed. \r
+ More precisely, we need to compute sin(true_d1):\r
+\r
+ sin(true_d1) = sin(2 * asin(sqrt(d1)))\r
+ = 2 * sin(asin(sqrt(d1)) * cos(asin(sqrt(d1)))\r
+ = 2 * sqrt(d1) * sqrt(1-(sqrt(d1))^2)\r
+ = 2 * sqrt(d1 - d1 * d1)\r
+ This relation is used below.\r
+\r
+ As we mentioned above the goal is to find CXTD (named "a" below for\r
+ brevity) such that ("b" below stands for "d1", and "c" for "d_crs1"):\r
+\r
+ 2 * R * asin(sqrt(a)) == R * asin(2 * sqrt(b-b^2) * sin(c))\r
+\r
+ Analysis:\r
+ 2 * R * asin(sqrt(a)) == R * asin(2 * sqrt(b-b^2) * sin(c))\r
+ <=> 2 * asin(sqrt(a)) == asin(sqrt(b-b^2) * sin(c))\r
+ <=> sin(2 * asin(sqrt(a))) == 2 * sqrt(b-b^2) * sin(c)\r
+ <=> 2 * sin(asin(sqrt(a))) * cos(asin(sqrt(a))) == 2 * sqrt(b-b^2) * sin(c)\r
+ <=> 2 * sqrt(a) * sqrt(1-a) == 2 * sqrt(b-b^2) * sin(c)\r
+ <=> sqrt(a) * sqrt(1-a) == sqrt(b-b^2) * sin(c)\r
+ <=> sqrt(a-a^2) == sqrt(b-b^2) * sin(c)\r
+ <=> a-a^2 == (b-b^2) * (sin(c))^2\r
+\r
+ Consider the quadratic equation: x^2-x+p^2 == 0,\r
+ where p = sqrt(b-b^2) * sin(c); its discriminant is:\r
+ d = 1 - 4 * p^2 = 1 - 4 * (b-b^2) * (sin(c))^2\r
+\r
+ The two solutions are:\r
+ a_1 = (1 - sqrt(d)) / 2\r
+ a_2 = (1 + sqrt(d)) / 2\r
+\r
+ Which one to choose?\r
+ "a" refers to the distance (on the unit sphere) of D from the\r
+ supporting great circle Circ(A,B) of the segment AB.\r
+ The two different values for "a" correspond to the lengths of the two\r
+ arcs delimited D and the points of intersection of Circ(A,B) and the\r
+ great circle perperdicular to Circ(A,B) passing through D.\r
+ Clearly, the value we want is the smallest among these two distances,\r
+ hence the root we must choose is the smallest root among the two.\r
+\r
+ So the answer is:\r
+ CXTD = ( 1 - sqrt(1 - 4 * (b-b^2) * (sin(c))^2) ) / 2\r
+\r
+ Therefore, in order to implement the comparable version of the cross\r
+ track strategy we need to:\r
+ (1) Use the comparable version of the haversine strategy instead of\r
+ the non-comparable one.\r
+ (2) Instead of return XTD when D projects inside the segment AB, we\r
+ need to return CXTD, given by the following formula:\r
+ CXTD = ( 1 - sqrt(1 - 4 * (d1-d1^2) * (sin(d_crs1))^2) ) / 2;\r
+\r
+\r
+ Complexity Analysis\r
+ -------------------\r
+ In the analysis that follows we refer to the actual implementation below.\r
+ In particular, instead of computing CXTD as above, we use the more\r
+ efficient (operation-wise) computation of CXTD shown here:\r
+\r
+ return_type sin_d_crs1 = sin(d_crs1);\r
+ return_type d1_x_sin = d1 * sin_d_crs1;\r
+ return_type d = d1_x_sin * (sin_d_crs1 - d1_x_sin);\r
+ return d / (0.5 + math::sqrt(0.25 - d));\r
+\r
+ Notice that instead of computing:\r
+ 0.5 - 0.5 * sqrt(1 - 4 * d) = 0.5 - sqrt(0.25 - d)\r
+ we use the following formula instead:\r
+ d / (0.5 + sqrt(0.25 - d)).\r
+ This is done for numerical robustness. The expression 0.5 - sqrt(0.25 - x)\r
+ has large numerical errors for values of x close to 0 (if using doubles\r
+ the error start to become large even when d is as large as 0.001).\r
+ To remedy that, we re-write 0.5 - sqrt(0.25 - x) as:\r
+ 0.5 - sqrt(0.25 - d)\r
+ = (0.5 - sqrt(0.25 - d) * (0.5 - sqrt(0.25 - d)) / (0.5 + sqrt(0.25 - d)).\r
+ The numerator is the difference of two squares:\r
+ (0.5 - sqrt(0.25 - d) * (0.5 - sqrt(0.25 - d))\r
+ = 0.5^2 - (sqrt(0.25 - d))^ = 0.25 - (0.25 - d) = d,\r
+ which gives the expression we use.\r
+\r
+ For the complexity analysis, we distinguish between two cases:\r
+ (A) The distance is realized between the point D and an\r
+ endpoint of the segment AB\r
+\r
+ Gains:\r
+ Since we are using comparable::haversine<> which is called\r
+ 3 times, we gain:\r
+ -> 3 calls to sqrt\r
+ -> 3 calls to asin\r
+ -> 6 multiplications\r
+\r
+ Loses: None\r
+\r
+ So the net gain is:\r
+ -> 6 function calls (sqrt/asin)\r
+ -> 6 arithmetic operations\r
+\r
+ If we use comparable::cross_track<> to compute\r
+ cross_track<> we need to account for a call to sqrt, a call\r
+ to asin and 2 multiplications. In this case the net gain is:\r
+ -> 4 function calls (sqrt/asin)\r
+ -> 4 arithmetic operations\r
+\r
+\r
+ (B) The distance is realized between the point D and an\r
+ interior point of the segment AB\r
+\r
+ Gains:\r
+ Since we are using comparable::haversine<> which is called\r
+ 3 times, we gain:\r
+ -> 3 calls to sqrt\r
+ -> 3 calls to asin\r
+ -> 6 multiplications\r
+ Also we gain the operations used to compute XTD:\r
+ -> 2 calls to sin\r
+ -> 1 call to asin\r
+ -> 1 call to abs\r
+ -> 2 multiplications\r
+ -> 1 division\r
+ So the total gains are:\r
+ -> 9 calls to sqrt/sin/asin\r
+ -> 1 call to abs\r
+ -> 8 multiplications\r
+ -> 1 division\r
+\r
+ Loses:\r
+ To compute a distance compatible with comparable::haversine<>\r
+ we need to perform a few more operations, namely:\r
+ -> 1 call to sin\r
+ -> 1 call to sqrt\r
+ -> 2 multiplications\r
+ -> 1 division\r
+ -> 1 addition\r
+ -> 2 subtractions\r
+\r
+ So roughly speaking the net gain is:\r
+ -> 8 fewer function calls and 3 fewer arithmetic operations\r
+\r
+ If we were to implement cross_track directly from the\r
+ comparable version (much like what haversine<> does using\r
+ comparable::haversine<>) we need additionally\r
+ -> 2 function calls (asin/sqrt)\r
+ -> 2 multiplications\r
+\r
+ So it pays off to re-implement cross_track<> to use\r
+ comparable::cross_track<>; in this case the net gain would be:\r
+ -> 6 function calls\r
+ -> 1 arithmetic operation\r
+\r
+ Summary/Conclusion\r
+ ------------------\r
+ Following the mathematical and complexity analysis above, the\r
+ comparable cross track strategy (as implemented below) satisfies\r
+ all the goal mentioned in the beginning:\r
+ * It is more efficient than its non-comparable counter-part.\r
+ * Comparable distances using this new strategy can also be compared\r
+ with comparable distances computed with the comparable haversine\r
+ strategy.\r
+ * It turns out to be more efficient to compute the actual cross\r
+ track distance XTD by first computing CXTD, and then computing\r
+ XTD by means of the formula:\r
+ XTD = 2 * R * asin( sqrt(CXTD) )\r
+*/\r
+\r
+template\r
+<\r
+ typename CalculationType = void,\r
+ typename Strategy = comparable::haversine<double, CalculationType>\r
+>\r
+class cross_track\r
+{\r
+public :\r
+ template <typename Point, typename PointOfSegment>\r
+ struct return_type\r
+ : promote_floating_point\r
+ <\r
+ typename select_calculation_type\r
+ <\r
+ Point,\r
+ PointOfSegment,\r
+ CalculationType\r
+ >::type\r
+ >\r
+ {};\r
+\r
+ typedef typename Strategy::radius_type radius_type;\r
+\r
+ inline cross_track()\r
+ {}\r
+\r
+ explicit inline cross_track(typename Strategy::radius_type const& r)\r
+ : m_strategy(r)\r
+ {}\r
+\r
+ inline cross_track(Strategy const& s)\r
+ : m_strategy(s)\r
+ {}\r
+\r
+\r
+ // It might be useful in the future\r
+ // to overload constructor with strategy info.\r
+ // crosstrack(...) {}\r
+\r
+\r
+ template <typename Point, typename PointOfSegment>\r
+ inline typename return_type<Point, PointOfSegment>::type\r
+ apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const\r
+ {\r
+\r
+#if !defined(BOOST_MSVC)\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::PointDistanceStrategy<Strategy, Point, PointOfSegment>)\r
+ );\r
+#endif\r
+\r
+ typedef typename return_type<Point, PointOfSegment>::type return_type;\r
+\r
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK\r
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "\r
+ << crs_AD * geometry::math::r2d<return_type>() << std::endl;\r
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " "\r
+ << crs_AB * geometry::math::r2d<return_type>() << std::endl;\r
+ std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " "\r
+ << crs_BD * geometry::math::r2d << std::endl;\r
+ std::cout << "Projection AD-AB " << projection1 << " : "\r
+ << d_crs1 * geometry::math::r2d<return_type>() << std::endl;\r
+ std::cout << "Projection BD-BA " << projection2 << " : "\r
+ << d_crs2 * geometry::math::r2d<return_type>() << std::endl;\r
+#endif\r
+\r
+ // http://williams.best.vwh.net/avform.htm#XTE\r
+ return_type d1 = m_strategy.apply(sp1, p);\r
+ return_type d3 = m_strategy.apply(sp1, sp2);\r
+\r
+ if (geometry::math::equals(d3, 0.0))\r
+ {\r
+ // "Degenerate" segment, return either d1 or d2\r
+ return d1;\r
+ }\r
+\r
+ return_type d2 = m_strategy.apply(sp2, p);\r
+\r
+ return_type crs_AD = geometry::detail::course<return_type>(sp1, p);\r
+ return_type crs_AB = geometry::detail::course<return_type>(sp1, sp2);\r
+ return_type crs_BA = crs_AB - geometry::math::pi<return_type>();\r
+ return_type crs_BD = geometry::detail::course<return_type>(sp2, p);\r
+ return_type d_crs1 = crs_AD - crs_AB;\r
+ return_type d_crs2 = crs_BD - crs_BA;\r
+\r
+ // d1, d2, d3 are in principle not needed, only the sign matters\r
+ return_type projection1 = cos( d_crs1 ) * d1 / d3;\r
+ return_type projection2 = cos( d_crs2 ) * d2 / d3;\r
+\r
+ if (projection1 > 0.0 && projection2 > 0.0)\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK\r
+ return_type XTD = radius() * geometry::math::abs( asin( sin( d1 ) * sin( d_crs1 ) ));\r
+\r
+ std::cout << "Projection ON the segment" << std::endl;\r
+ std::cout << "XTD: " << XTD\r
+ << " d1: " << (d1 * radius())\r
+ << " d2: " << (d2 * radius())\r
+ << std::endl;\r
+#endif\r
+ return_type const half(0.5);\r
+ return_type const quarter(0.25);\r
+\r
+ return_type sin_d_crs1 = sin(d_crs1);\r
+ /*\r
+ This is the straightforward obvious way to continue:\r
+ \r
+ return_type discriminant\r
+ = 1.0 - 4.0 * (d1 - d1 * d1) * sin_d_crs1 * sin_d_crs1;\r
+ return 0.5 - 0.5 * math::sqrt(discriminant);\r
+ \r
+ Below we optimize the number of arithmetic operations\r
+ and account for numerical robustness:\r
+ */\r
+ return_type d1_x_sin = d1 * sin_d_crs1;\r
+ return_type d = d1_x_sin * (sin_d_crs1 - d1_x_sin);\r
+ return d / (half + math::sqrt(quarter - d));\r
+ }\r
+ else\r
+ {\r
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK\r
+ std::cout << "Projection OUTSIDE the segment" << std::endl;\r
+#endif\r
+\r
+ // Return shortest distance, project either on point sp1 or sp2\r
+ return return_type( (std::min)( d1 , d2 ) );\r
+ }\r
+ }\r
+\r
+ inline typename Strategy::radius_type radius() const\r
+ { return m_strategy.radius(); }\r
+\r
+private :\r
+ Strategy m_strategy;\r
+};\r
+\r
+} // namespace comparable\r
+\r
+\r
+/*!\r
+\brief Strategy functor for distance point to segment calculation\r
+\ingroup strategies\r
+\details Class which calculates the distance of a point to a segment, for points on a sphere or globe\r
+\see http://williams.best.vwh.net/avform.htm\r
+\tparam CalculationType \tparam_calculation\r
+\tparam Strategy underlying point-point distance strategy, defaults to haversine\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename CalculationType = void,\r
+ typename Strategy = haversine<double, CalculationType>\r
+>\r
+class cross_track\r
+{\r
+public :\r
+ template <typename Point, typename PointOfSegment>\r
+ struct return_type\r
+ : promote_floating_point\r
+ <\r
+ typename select_calculation_type\r
+ <\r
+ Point,\r
+ PointOfSegment,\r
+ CalculationType\r
+ >::type\r
+ >\r
+ {};\r
+\r
+ typedef typename Strategy::radius_type radius_type;\r
+\r
+ inline cross_track()\r
+ {}\r
+\r
+ explicit inline cross_track(typename Strategy::radius_type const& r)\r
+ : m_strategy(r)\r
+ {}\r
+\r
+ inline cross_track(Strategy const& s)\r
+ : m_strategy(s)\r
+ {}\r
+\r
+\r
+ // It might be useful in the future\r
+ // to overload constructor with strategy info.\r
+ // crosstrack(...) {}\r
+\r
+\r
+ template <typename Point, typename PointOfSegment>\r
+ inline typename return_type<Point, PointOfSegment>::type\r
+ apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const\r
+ {\r
+\r
+#if !defined(BOOST_MSVC)\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::PointDistanceStrategy<Strategy, Point, PointOfSegment>)\r
+ );\r
+#endif\r
+ typedef typename return_type<Point, PointOfSegment>::type return_type;\r
+ typedef cross_track<CalculationType, Strategy> this_type;\r
+\r
+ typedef typename services::comparable_type\r
+ <\r
+ this_type\r
+ >::type comparable_type;\r
+\r
+ comparable_type cstrategy\r
+ = services::get_comparable<this_type>::apply(m_strategy);\r
+\r
+ return_type const a = cstrategy.apply(p, sp1, sp2);\r
+ return_type const c = return_type(2.0) * asin(math::sqrt(a));\r
+ return c * radius();\r
+ }\r
+\r
+ inline typename Strategy::radius_type radius() const\r
+ { return m_strategy.radius(); }\r
+\r
+private :\r
+\r
+ Strategy m_strategy;\r
+};\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct tag<cross_track<CalculationType, Strategy> >\r
+{\r
+ typedef strategy_tag_distance_point_segment type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename PS>\r
+struct return_type<cross_track<CalculationType, Strategy>, P, PS>\r
+ : cross_track<CalculationType, Strategy>::template return_type<P, PS>\r
+{};\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct comparable_type<cross_track<CalculationType, Strategy> >\r
+{\r
+ typedef comparable::cross_track\r
+ <\r
+ CalculationType, typename comparable_type<Strategy>::type\r
+ > type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename CalculationType,\r
+ typename Strategy\r
+>\r
+struct get_comparable<cross_track<CalculationType, Strategy> >\r
+{\r
+ typedef typename comparable_type\r
+ <\r
+ cross_track<CalculationType, Strategy>\r
+ >::type comparable_type;\r
+public :\r
+ static inline comparable_type\r
+ apply(cross_track<CalculationType, Strategy> const& strategy)\r
+ {\r
+ return comparable_type(strategy.radius());\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename CalculationType,\r
+ typename Strategy,\r
+ typename P,\r
+ typename PS\r
+>\r
+struct result_from_distance<cross_track<CalculationType, Strategy>, P, PS>\r
+{\r
+private :\r
+ typedef typename cross_track\r
+ <\r
+ CalculationType, Strategy\r
+ >::template return_type<P, PS>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type\r
+ apply(cross_track<CalculationType, Strategy> const& , T const& distance)\r
+ {\r
+ return distance;\r
+ }\r
+};\r
+\r
+\r
+// Specializations for comparable::cross_track\r
+template <typename RadiusType, typename CalculationType>\r
+struct tag<comparable::cross_track<RadiusType, CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_segment type;\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename RadiusType,\r
+ typename CalculationType,\r
+ typename P,\r
+ typename PS\r
+>\r
+struct return_type<comparable::cross_track<RadiusType, CalculationType>, P, PS>\r
+ : comparable::cross_track\r
+ <\r
+ RadiusType, CalculationType\r
+ >::template return_type<P, PS>\r
+{};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct comparable_type<comparable::cross_track<RadiusType, CalculationType> >\r
+{\r
+ typedef comparable::cross_track<RadiusType, CalculationType> type;\r
+};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct get_comparable<comparable::cross_track<RadiusType, CalculationType> >\r
+{\r
+private :\r
+ typedef comparable::cross_track<RadiusType, CalculationType> this_type;\r
+public :\r
+ static inline this_type apply(this_type const& input)\r
+ {\r
+ return input;\r
+ }\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename RadiusType,\r
+ typename CalculationType,\r
+ typename P,\r
+ typename PS\r
+>\r
+struct result_from_distance\r
+ <\r
+ comparable::cross_track<RadiusType, CalculationType>, P, PS\r
+ >\r
+{\r
+private :\r
+ typedef comparable::cross_track<RadiusType, CalculationType> strategy_type;\r
+ typedef typename return_type<strategy_type, P, PS>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(strategy_type const& strategy,\r
+ T const& distance)\r
+ {\r
+ return_type const s\r
+ = sin( (distance / strategy.radius()) / return_type(2.0) );\r
+ return s * s;\r
+ }\r
+};\r
+\r
+\r
+\r
+/*\r
+\r
+TODO: spherical polar coordinate system requires "get_as_radian_equatorial<>"\r
+\r
+template <typename Point, typename PointOfSegment, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ segment_tag, Point, PointOfSegment,\r
+ spherical_polar_tag, spherical_polar_tag,\r
+ Strategy\r
+ >\r
+{\r
+ typedef cross_track\r
+ <\r
+ void,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_void<Strategy>,\r
+ typename default_strategy\r
+ <\r
+ point_tag, Point, PointOfSegment,\r
+ spherical_polar_tag, spherical_polar_tag\r
+ >::type,\r
+ Strategy\r
+ >::type\r
+ > type;\r
+};\r
+*/\r
+\r
+template <typename Point, typename PointOfSegment, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ point_tag, segment_tag, Point, PointOfSegment,\r
+ spherical_equatorial_tag, spherical_equatorial_tag,\r
+ Strategy\r
+ >\r
+{\r
+ typedef cross_track\r
+ <\r
+ void,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_void<Strategy>,\r
+ typename default_strategy\r
+ <\r
+ point_tag, point_tag, Point, PointOfSegment,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ >::type,\r
+ Strategy\r
+ >::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename PointOfSegment, typename Point, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ segment_tag, point_tag, PointOfSegment, Point,\r
+ spherical_equatorial_tag, spherical_equatorial_tag,\r
+ Strategy\r
+ >\r
+{\r
+ typedef typename default_strategy\r
+ <\r
+ point_tag, segment_tag, Point, PointOfSegment,\r
+ spherical_equatorial_tag, spherical_equatorial_tag,\r
+ Strategy\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+}} // namespace strategy::distance\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/concept_check.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>\r
+#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+\r
+/*!\r
+\brief Strategy functor for distance point to box calculation\r
+\ingroup strategies\r
+\details Class which calculates the distance of a point to a box, for\r
+points and boxes on a sphere or globe\r
+\tparam CalculationType \tparam_calculation\r
+\tparam Strategy underlying point-segment distance strategy, defaults\r
+to cross track\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename CalculationType = void,\r
+ typename Strategy = cross_track<CalculationType>\r
+>\r
+class cross_track_point_box\r
+{\r
+public:\r
+ template <typename Point, typename Box>\r
+ struct return_type\r
+ : services::return_type<Strategy, Point, typename point_type<Box>::type>\r
+ {};\r
+\r
+ typedef typename Strategy::radius_type radius_type;\r
+\r
+ inline cross_track_point_box()\r
+ {}\r
+\r
+ explicit inline cross_track_point_box(typename Strategy::radius_type const& r)\r
+ : m_ps_strategy(r)\r
+ {}\r
+\r
+ inline cross_track_point_box(Strategy const& s)\r
+ : m_ps_strategy(s)\r
+ {}\r
+\r
+\r
+ // It might be useful in the future\r
+ // to overload constructor with strategy info.\r
+ // crosstrack(...) {}\r
+\r
+ template <typename Point, typename Box>\r
+ inline typename return_type<Point, Box>::type\r
+ apply(Point const& point, Box const& box) const\r
+ {\r
+#if !defined(BOOST_MSVC)\r
+ BOOST_CONCEPT_ASSERT\r
+ (\r
+ (concepts::PointSegmentDistanceStrategy\r
+ <\r
+ Strategy, Point, typename point_type<Box>::type\r
+ >)\r
+ );\r
+#endif\r
+\r
+ // this method assumes that the coordinates of the point and\r
+ // the box are normalized\r
+\r
+ typedef typename return_type<Point, Box>::type return_type;\r
+ typedef typename point_type<Box>::type box_point_type;\r
+\r
+ // TODO: This strategy as well as other cross-track strategies\r
+ // and therefore e.g. spherical within(Point, Box) may not work\r
+ // properly for a Box degenerated to a Segment or Point\r
+\r
+ box_point_type bottom_left, bottom_right, top_left, top_right;\r
+ geometry::detail::assign_box_corners(box,\r
+ bottom_left, bottom_right,\r
+ top_left, top_right);\r
+\r
+ return_type const plon = geometry::get_as_radian<0>(point);\r
+ return_type const plat = geometry::get_as_radian<1>(point);\r
+\r
+ return_type const lon_min = geometry::get_as_radian<0>(bottom_left);\r
+ return_type const lat_min = geometry::get_as_radian<1>(bottom_left);\r
+ return_type const lon_max = geometry::get_as_radian<0>(top_right);\r
+ return_type const lat_max = geometry::get_as_radian<1>(top_right);\r
+\r
+ return_type const pi = math::pi<return_type>();\r
+ return_type const two_pi = math::two_pi<return_type>();\r
+\r
+ // First check if the point is within the band defined by the\r
+ // minimum and maximum longitude of the box; if yes, determine\r
+ // if the point is above, below or inside the box and compute\r
+ // the distance (easy in this case)\r
+ //\r
+ // Notice that the point may not be inside the longitude range\r
+ // of the box, but the shifted point may be inside the\r
+ // longitude range of the box; in this case the point is still\r
+ // considered as inside the longitude range band of the box\r
+ if ((plon >= lon_min && plon <= lon_max) || plon + two_pi <= lon_max)\r
+ {\r
+ if (plat > lat_max)\r
+ {\r
+ return services::result_from_distance\r
+ <\r
+ Strategy, Point, box_point_type\r
+ >::apply(m_ps_strategy, radius() * (plat - lat_max));\r
+ }\r
+ else if (plat < lat_min)\r
+ {\r
+ return services::result_from_distance\r
+ <\r
+ Strategy, Point, box_point_type\r
+ >::apply(m_ps_strategy, radius() * (lat_min - plat));\r
+ }\r
+ else\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(plat >= lat_min && plat <= lat_max);\r
+ return return_type(0);\r
+ }\r
+ }\r
+\r
+ // Otherwise determine which among the two medirian segments of the\r
+ // box the point is closest to, and compute the distance of\r
+ // the point to this closest segment\r
+\r
+ // Below lon_midway is the longitude of the meridian that:\r
+ // (1) is midway between the meridians of the left and right\r
+ // meridians of the box, and\r
+ // (2) does not intersect the box\r
+ return_type const two = 2.0;\r
+ bool use_left_segment;\r
+ if (lon_max > pi)\r
+ {\r
+ // the box crosses the antimeridian\r
+\r
+ // midway longitude = lon_min - (lon_min + (lon_max - 2 * pi)) / 2;\r
+ return_type const lon_midway = (lon_min - lon_max) / two + pi;\r
+ BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);\r
+\r
+ use_left_segment = plon > lon_midway;\r
+ }\r
+ else\r
+ {\r
+ // the box does not cross the antimeridian\r
+\r
+ return_type const lon_sum = lon_min + lon_max;\r
+ if (math::equals(lon_sum, return_type(0)))\r
+ {\r
+ // special case: the box is symmetric with respect to\r
+ // the prime meridian; the midway meridian is the antimeridian\r
+\r
+ use_left_segment = plon < lon_min;\r
+ }\r
+ else\r
+ {\r
+ // midway long. = lon_min - (2 * pi - (lon_max - lon_min)) / 2;\r
+ return_type lon_midway = (lon_min + lon_max) / two - pi;\r
+\r
+ // normalize the midway longitude\r
+ if (lon_midway > pi)\r
+ {\r
+ lon_midway -= two_pi;\r
+ }\r
+ else if (lon_midway < -pi)\r
+ {\r
+ lon_midway += two_pi;\r
+ }\r
+ BOOST_GEOMETRY_ASSERT(lon_midway >= -pi && lon_midway <= pi);\r
+\r
+ // if lon_sum is positive the midway meridian is left\r
+ // of the box, or right of the box otherwise\r
+ use_left_segment = lon_sum > 0\r
+ ? (plon < lon_min && plon >= lon_midway)\r
+ : (plon <= lon_max || plon > lon_midway);\r
+ }\r
+ }\r
+\r
+ return use_left_segment\r
+ ? m_ps_strategy.apply(point, bottom_left, top_left)\r
+ : m_ps_strategy.apply(point, bottom_right, top_right);\r
+ }\r
+\r
+ inline typename Strategy::radius_type radius() const\r
+ {\r
+ return m_ps_strategy.radius();\r
+ }\r
+\r
+private:\r
+ Strategy m_ps_strategy;\r
+};\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct tag<cross_track_point_box<CalculationType, Strategy> >\r
+{\r
+ typedef strategy_tag_distance_point_box type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename Box>\r
+struct return_type<cross_track_point_box<CalculationType, Strategy>, P, Box>\r
+ : cross_track_point_box\r
+ <\r
+ CalculationType, Strategy\r
+ >::template return_type<P, Box>\r
+{};\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct comparable_type<cross_track_point_box<CalculationType, Strategy> >\r
+{\r
+ typedef cross_track_point_box\r
+ <\r
+ CalculationType, typename comparable_type<Strategy>::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy>\r
+struct get_comparable<cross_track_point_box<CalculationType, Strategy> >\r
+{\r
+ typedef cross_track_point_box<CalculationType, Strategy> this_strategy;\r
+ typedef typename comparable_type<this_strategy>::type comparable_type;\r
+\r
+public:\r
+ static inline comparable_type apply(this_strategy const& strategy)\r
+ {\r
+ return comparable_type(strategy.radius());\r
+ }\r
+};\r
+\r
+\r
+template <typename CalculationType, typename Strategy, typename P, typename Box>\r
+struct result_from_distance\r
+ <\r
+ cross_track_point_box<CalculationType, Strategy>, P, Box\r
+ >\r
+{\r
+private:\r
+ typedef cross_track_point_box<CalculationType, Strategy> this_strategy;\r
+\r
+ typedef typename this_strategy::template return_type\r
+ <\r
+ P, Box\r
+ >::type return_type;\r
+\r
+public:\r
+ template <typename T>\r
+ static inline return_type apply(this_strategy const& strategy,\r
+ T const& distance)\r
+ {\r
+ Strategy s(strategy.radius());\r
+\r
+ return result_from_distance\r
+ <\r
+ Strategy, P, typename point_type<Box>::type\r
+ >::apply(s, distance);\r
+ }\r
+};\r
+\r
+\r
+// define cross_track_point_box<default_point_segment_strategy> as\r
+// default point-box strategy for the spherical equatorial coordinate system\r
+template <typename Point, typename Box, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ point_tag, box_tag, Point, Box,\r
+ spherical_equatorial_tag, spherical_equatorial_tag,\r
+ Strategy\r
+ >\r
+{\r
+ typedef cross_track_point_box\r
+ <\r
+ void,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_void<Strategy>,\r
+ typename default_strategy\r
+ <\r
+ point_tag, segment_tag,\r
+ Point, typename point_type<Box>::type,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ >::type,\r
+ Strategy\r
+ >::type\r
+ > type;\r
+};\r
+\r
+\r
+template <typename Box, typename Point, typename Strategy>\r
+struct default_strategy\r
+ <\r
+ box_tag, point_tag, Box, Point,\r
+ spherical_equatorial_tag, spherical_equatorial_tag,\r
+ Strategy\r
+ >\r
+{\r
+ typedef typename default_strategy\r
+ <\r
+ point_tag, box_tag, Point, Box,\r
+ spherical_equatorial_tag, spherical_equatorial_tag,\r
+ Strategy\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_POINT_BOX_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP\r
+\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+\r
+#include <boost/geometry/strategies/distance.hpp>\r
+\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace distance\r
+{\r
+\r
+\r
+namespace comparable\r
+{\r
+\r
+// Comparable haversine.\r
+// To compare distances, we can avoid:\r
+// - multiplication with radius and 2.0\r
+// - applying sqrt\r
+// - applying asin (which is strictly (monotone) increasing)\r
+template\r
+<\r
+ typename RadiusType,\r
+ typename CalculationType = void\r
+>\r
+class haversine\r
+{\r
+public :\r
+ template <typename Point1, typename Point2>\r
+ struct calculation_type\r
+ : promote_floating_point\r
+ <\r
+ typename select_calculation_type\r
+ <\r
+ Point1,\r
+ Point2,\r
+ CalculationType\r
+ >::type\r
+ >\r
+ {};\r
+\r
+ typedef RadiusType radius_type;\r
+\r
+ explicit inline haversine(RadiusType const& r = 1.0)\r
+ : m_radius(r)\r
+ {}\r
+\r
+ template <typename Point1, typename Point2>\r
+ static inline typename calculation_type<Point1, Point2>::type\r
+ apply(Point1 const& p1, Point2 const& p2)\r
+ {\r
+ return calculate<typename calculation_type<Point1, Point2>::type>(\r
+ get_as_radian<0>(p1), get_as_radian<1>(p1),\r
+ get_as_radian<0>(p2), get_as_radian<1>(p2)\r
+ );\r
+ }\r
+\r
+ inline RadiusType radius() const\r
+ {\r
+ return m_radius;\r
+ }\r
+\r
+\r
+private :\r
+ template <typename R, typename T1, typename T2>\r
+ static inline R calculate(T1 const& lon1, T1 const& lat1,\r
+ T2 const& lon2, T2 const& lat2)\r
+ {\r
+ return math::hav(lat2 - lat1)\r
+ + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);\r
+ }\r
+\r
+ RadiusType m_radius;\r
+};\r
+\r
+\r
+\r
+} // namespace comparable\r
+\r
+/*!\r
+\brief Distance calculation for spherical coordinates\r
+on a perfect sphere using haversine\r
+\ingroup strategies\r
+\tparam RadiusType \tparam_radius\r
+\tparam CalculationType \tparam_calculation\r
+\author Adapted from: http://williams.best.vwh.net/avform.htm\r
+\see http://en.wikipedia.org/wiki/Great-circle_distance\r
+\note (from Wiki:) The great circle distance d between two\r
+points with coordinates {lat1,lon1} and {lat2,lon2} is given by:\r
+ d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))\r
+A mathematically equivalent formula, which is less subject\r
+ to rounding error for short distances is:\r
+ d=2*asin(sqrt((sin((lat1-lat2) / 2))^2\r
+ + cos(lat1)*cos(lat2)*(sin((lon1-lon2) / 2))^2))\r
+\r
+\r
+\qbk{\r
+[heading See also]\r
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]\r
+}\r
+\r
+*/\r
+template\r
+<\r
+ typename RadiusType,\r
+ typename CalculationType = void\r
+>\r
+class haversine\r
+{\r
+ typedef comparable::haversine<RadiusType, CalculationType> comparable_type;\r
+\r
+public :\r
+ template <typename Point1, typename Point2>\r
+ struct calculation_type\r
+ : services::return_type<comparable_type, Point1, Point2>\r
+ {};\r
+\r
+ typedef RadiusType radius_type;\r
+\r
+ /*!\r
+ \brief Constructor\r
+ \param radius radius of the sphere, defaults to 1.0 for the unit sphere\r
+ */\r
+ inline haversine(RadiusType const& radius = 1.0)\r
+ : m_radius(radius)\r
+ {}\r
+\r
+ /*!\r
+ \brief applies the distance calculation\r
+ \return the calculated distance (including multiplying with radius)\r
+ \param p1 first point\r
+ \param p2 second point\r
+ */\r
+ template <typename Point1, typename Point2>\r
+ inline typename calculation_type<Point1, Point2>::type\r
+ apply(Point1 const& p1, Point2 const& p2) const\r
+ {\r
+ typedef typename calculation_type<Point1, Point2>::type calculation_type;\r
+ calculation_type const a = comparable_type::apply(p1, p2);\r
+ calculation_type const c = calculation_type(2.0) * asin(math::sqrt(a));\r
+ return calculation_type(m_radius) * c;\r
+ }\r
+\r
+ /*!\r
+ \brief access to radius value\r
+ \return the radius\r
+ */\r
+ inline RadiusType radius() const\r
+ {\r
+ return m_radius;\r
+ }\r
+\r
+private :\r
+ RadiusType m_radius;\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct tag<haversine<RadiusType, CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType, typename P1, typename P2>\r
+struct return_type<haversine<RadiusType, CalculationType>, P1, P2>\r
+ : haversine<RadiusType, CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct comparable_type<haversine<RadiusType, CalculationType> >\r
+{\r
+ typedef comparable::haversine<RadiusType, CalculationType> type;\r
+};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct get_comparable<haversine<RadiusType, CalculationType> >\r
+{\r
+private :\r
+ typedef haversine<RadiusType, CalculationType> this_type;\r
+ typedef comparable::haversine<RadiusType, CalculationType> comparable_type;\r
+public :\r
+ static inline comparable_type apply(this_type const& input)\r
+ {\r
+ return comparable_type(input.radius());\r
+ }\r
+};\r
+\r
+template <typename RadiusType, typename CalculationType, typename P1, typename P2>\r
+struct result_from_distance<haversine<RadiusType, CalculationType>, P1, P2>\r
+{\r
+private :\r
+ typedef haversine<RadiusType, CalculationType> this_type;\r
+ typedef typename return_type<this_type, P1, P2>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(this_type const& , T const& value)\r
+ {\r
+ return return_type(value);\r
+ }\r
+};\r
+\r
+\r
+// Specializations for comparable::haversine\r
+template <typename RadiusType, typename CalculationType>\r
+struct tag<comparable::haversine<RadiusType, CalculationType> >\r
+{\r
+ typedef strategy_tag_distance_point_point type;\r
+};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType, typename P1, typename P2>\r
+struct return_type<comparable::haversine<RadiusType, CalculationType>, P1, P2>\r
+ : comparable::haversine<RadiusType, CalculationType>::template calculation_type<P1, P2>\r
+{};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct comparable_type<comparable::haversine<RadiusType, CalculationType> >\r
+{\r
+ typedef comparable::haversine<RadiusType, CalculationType> type;\r
+};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType>\r
+struct get_comparable<comparable::haversine<RadiusType, CalculationType> >\r
+{\r
+private :\r
+ typedef comparable::haversine<RadiusType, CalculationType> this_type;\r
+public :\r
+ static inline this_type apply(this_type const& input)\r
+ {\r
+ return input;\r
+ }\r
+};\r
+\r
+\r
+template <typename RadiusType, typename CalculationType, typename P1, typename P2>\r
+struct result_from_distance<comparable::haversine<RadiusType, CalculationType>, P1, P2>\r
+{\r
+private :\r
+ typedef comparable::haversine<RadiusType, CalculationType> strategy_type;\r
+ typedef typename return_type<strategy_type, P1, P2>::type return_type;\r
+public :\r
+ template <typename T>\r
+ static inline return_type apply(strategy_type const& strategy, T const& distance)\r
+ {\r
+ return_type const s = sin((distance / strategy.radius()) / return_type(2));\r
+ return s * s;\r
+ }\r
+};\r
+\r
+\r
+// Register it as the default for point-types\r
+// in a spherical equatorial coordinate system\r
+template <typename Point1, typename Point2>\r
+struct default_strategy\r
+ <\r
+ point_tag, point_tag, Point1, Point2,\r
+ spherical_equatorial_tag, spherical_equatorial_tag\r
+ >\r
+{\r
+ typedef strategy::distance::haversine<typename select_coordinate_type<Point1, Point2>::type> type;\r
+};\r
+\r
+// Note: spherical polar coordinate system requires "get_as_radian_equatorial"\r
+\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::distance\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2016, Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INTERSECTION_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INTERSECTION_HPP\r
+\r
+#include <algorithm>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/assign_values.hpp>\r
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>\r
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>\r
+#include <boost/geometry/algorithms/detail/recalculate.hpp>\r
+\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/arithmetic/cross_product.hpp>\r
+#include <boost/geometry/arithmetic/dot_product.hpp>\r
+#include <boost/geometry/formulas/spherical.hpp>\r
+\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>\r
+\r
+#include <boost/geometry/policies/robustness/segment_ratio.hpp>\r
+\r
+#include <boost/geometry/strategies/side_info.hpp>\r
+#include <boost/geometry/strategies/intersection.hpp>\r
+#include <boost/geometry/strategies/intersection_result.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace intersection\r
+{\r
+\r
+// NOTE:\r
+// The coordinates of crossing IP may be calculated with small precision in some cases.\r
+// For double, near the equator noticed error ~1e-9 so far greater than\r
+// machine epsilon which is ~1e-16. This error is ~0.04m.\r
+// E.g. consider two cases, one near the origin and the second one rotated by 90 deg around Z or SN axis.\r
+// After the conversion from spherical degrees to cartesian 3d the following coordinates\r
+// are calculated:\r
+// for sph (-1 -1, 1 1) deg cart3d ys are -0.017449748351250485 and 0.017449748351250485\r
+// for sph (89 -1, 91 1) deg cart3d xs are 0.017449748351250571 and -0.017449748351250450\r
+// During the conversion degrees must first be converted to radians and then radians\r
+// are passed into trigonometric functions. The error may have several causes:\r
+// 1. Radians cannot represent exactly the same angles as degrees.\r
+// 2. Different longitudes are passed into sin() for x, corresponding to cos() for y,\r
+// and for different angle the error of the result may be different.\r
+// 3. These non-corresponding cartesian coordinates are used in calculation,\r
+// e.g. multiplied several times in cross and dot products.\r
+// If it was a problem this strategy could e.g. "normalize" longitudes before the conversion using the source units\r
+// by rotating the globe around Z axis, so moving longitudes always the same way towards the origin,\r
+// assuming this could help which is not clear.\r
+// For now, intersection points near the endpoints are checked explicitly if needed (if the IP is near the endpoint)\r
+// to generate precise result for them. Only the crossing (i) case may suffer from lower precision.\r
+\r
+template <typename Policy, typename CalculationType = void>\r
+struct relate_spherical_segments\r
+{\r
+ typedef typename Policy::return_type return_type;\r
+\r
+ enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };\r
+\r
+ template <typename CoordinateType, typename SegmentRatio, typename Vector3d>\r
+ struct segment_intersection_info\r
+ {\r
+ typedef typename select_most_precise\r
+ <\r
+ CoordinateType, double\r
+ >::type promoted_type;\r
+\r
+ promoted_type comparable_length_a() const\r
+ {\r
+ return robust_ra.denominator();\r
+ }\r
+\r
+ promoted_type comparable_length_b() const\r
+ {\r
+ return robust_rb.denominator();\r
+ }\r
+\r
+ template <typename Point, typename Segment1, typename Segment2>\r
+ void assign_a(Point& point, Segment1 const& a, Segment2 const& b) const\r
+ {\r
+ assign(point, a, b);\r
+ }\r
+ template <typename Point, typename Segment1, typename Segment2>\r
+ void assign_b(Point& point, Segment1 const& a, Segment2 const& b) const\r
+ {\r
+ assign(point, a, b);\r
+ }\r
+\r
+ template <typename Point, typename Segment1, typename Segment2>\r
+ void assign(Point& point, Segment1 const& a, Segment2 const& b) const\r
+ {\r
+ if (ip_flag == ipi_inters)\r
+ {\r
+ // TODO: assign the rest of coordinates\r
+ point = formula::cart3d_to_sph<Point>(intersection_point);\r
+ }\r
+ else if (ip_flag == ipi_at_a1)\r
+ {\r
+ detail::assign_point_from_index<0>(a, point);\r
+ }\r
+ else if (ip_flag == ipi_at_a2)\r
+ {\r
+ detail::assign_point_from_index<1>(a, point);\r
+ }\r
+ else if (ip_flag == ipi_at_b1)\r
+ {\r
+ detail::assign_point_from_index<0>(b, point);\r
+ }\r
+ else // ip_flag == ipi_at_b2\r
+ {\r
+ detail::assign_point_from_index<1>(b, point);\r
+ }\r
+ }\r
+\r
+ Vector3d intersection_point;\r
+ SegmentRatio robust_ra;\r
+ SegmentRatio robust_rb;\r
+ intersection_point_flag ip_flag;\r
+ };\r
+\r
+ // Relate segments a and b\r
+ template <typename Segment1, typename Segment2, typename RobustPolicy>\r
+ static inline return_type apply(Segment1 const& a, Segment2 const& b,\r
+ RobustPolicy const& robust_policy)\r
+ {\r
+ typedef typename point_type<Segment1>::type point1_t;\r
+ typedef typename point_type<Segment2>::type point2_t;\r
+ point1_t a1, a2;\r
+ point2_t b1, b2;\r
+\r
+ // TODO: use indexed_point_view if possible?\r
+ detail::assign_point_from_index<0>(a, a1);\r
+ detail::assign_point_from_index<1>(a, a2);\r
+ detail::assign_point_from_index<0>(b, b1);\r
+ detail::assign_point_from_index<1>(b, b2);\r
+\r
+ return apply(a, b, robust_policy, a1, a2, b1, b2);\r
+ }\r
+\r
+ // Relate segments a and b\r
+ template <typename Segment1, typename Segment2, typename RobustPolicy, typename Point1, typename Point2>\r
+ static inline return_type apply(Segment1 const& a, Segment2 const& b,\r
+ RobustPolicy const&,\r
+ Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)\r
+ {\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );\r
+\r
+ // TODO: check only 2 first coordinates here?\r
+ using geometry::detail::equals::equals_point_point;\r
+ bool a_is_point = equals_point_point(a1, a2);\r
+ bool b_is_point = equals_point_point(b1, b2);\r
+\r
+ if(a_is_point && b_is_point)\r
+ {\r
+ return equals_point_point(a1, b2)\r
+ ? Policy::degenerate(a, true)\r
+ : Policy::disjoint()\r
+ ;\r
+ }\r
+\r
+ typedef typename select_calculation_type\r
+ <Segment1, Segment2, CalculationType>::type calc_t;\r
+\r
+ calc_t const c0 = 0;\r
+ calc_t const c1 = 1;\r
+\r
+ typedef model::point<calc_t, 3, cs::cartesian> vec3d_t;\r
+\r
+ using namespace formula;\r
+ vec3d_t const a1v = sph_to_cart3d<vec3d_t>(a1);\r
+ vec3d_t const a2v = sph_to_cart3d<vec3d_t>(a2);\r
+ vec3d_t const b1v = sph_to_cart3d<vec3d_t>(b1);\r
+ vec3d_t const b2v = sph_to_cart3d<vec3d_t>(b2);\r
+ \r
+ vec3d_t norm1 = cross_product(a1v, a2v);\r
+ vec3d_t norm2 = cross_product(b1v, b2v);\r
+\r
+ side_info sides;\r
+ // not normalized normals, the same as in SSF\r
+ sides.set<0>(sph_side_value(norm2, a1v), sph_side_value(norm2, a2v));\r
+ if (sides.same<0>())\r
+ {\r
+ // Both points are at same side of other segment, we can leave\r
+ return Policy::disjoint();\r
+ }\r
+ // not normalized normals, the same as in SSF\r
+ sides.set<1>(sph_side_value(norm1, b1v), sph_side_value(norm1, b2v));\r
+ if (sides.same<1>())\r
+ {\r
+ // Both points are at same side of other segment, we can leave\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ // NOTE: at this point the segments may still be disjoint\r
+\r
+ bool collinear = sides.collinear();\r
+\r
+ calc_t const len1 = math::sqrt(dot_product(norm1, norm1));\r
+ calc_t const len2 = math::sqrt(dot_product(norm2, norm2));\r
+\r
+ // point or opposite sides of a sphere, assume point\r
+ if (math::equals(len1, c0))\r
+ {\r
+ a_is_point = true;\r
+ if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)\r
+ {\r
+ sides.set<0>(0, 0);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // normalize\r
+ divide_value(norm1, len1);\r
+ }\r
+\r
+ if (math::equals(len2, c0))\r
+ {\r
+ b_is_point = true;\r
+ if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)\r
+ {\r
+ sides.set<1>(0, 0);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // normalize\r
+ divide_value(norm2, len2);\r
+ }\r
+\r
+ // check both degenerated once more\r
+ if (a_is_point && b_is_point)\r
+ {\r
+ return equals_point_point(a1, b2)\r
+ ? Policy::degenerate(a, true)\r
+ : Policy::disjoint()\r
+ ;\r
+ }\r
+\r
+ // NOTE: at this point one of the segments may be degenerated\r
+ // and the segments may still be disjoint\r
+\r
+ calc_t dot_n1n2 = dot_product(norm1, norm2);\r
+\r
+ // NOTE: this is technically not needed since theoretically above sides\r
+ // are calculated, but just in case check the normals.\r
+ // Have in mind that SSF side strategy doesn't check this.\r
+ // collinear if normals are equal or opposite: cos(a) in {-1, 1}\r
+ if (!collinear && math::equals(math::abs(dot_n1n2), c1))\r
+ {\r
+ collinear = true;\r
+ sides.set<0>(0, 0);\r
+ sides.set<1>(0, 0);\r
+ }\r
+ \r
+ if (collinear)\r
+ {\r
+ if (a_is_point)\r
+ {\r
+ return collinear_one_degenerted<calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, norm2, a1v);\r
+ }\r
+ else if (b_is_point)\r
+ {\r
+ // b2 used to be consistent with (degenerated) checks above (is it needed?)\r
+ return collinear_one_degenerted<calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, norm1, b1v);\r
+ }\r
+ else\r
+ {\r
+ calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;\r
+ calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;\r
+ // use shorter segment\r
+ if (len1 <= len2)\r
+ {\r
+ calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b1v, dist_a1_a2, dist_a1_b1);\r
+ calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, norm1, b2v, dist_a1_a2, dist_a1_b2);\r
+ dist_b1_b2 = dist_a1_b2 - dist_a1_b1;\r
+ dist_b1_a1 = -dist_a1_b1;\r
+ dist_b1_a2 = dist_a1_a2 - dist_a1_b1;\r
+ }\r
+ else\r
+ {\r
+ calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a1v, dist_b1_b2, dist_b1_a1);\r
+ calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, norm2, a2v, dist_b1_b2, dist_b1_a2);\r
+ dist_a1_a2 = dist_b1_a2 - dist_b1_a1;\r
+ dist_a1_b1 = -dist_b1_a1;\r
+ dist_a1_b2 = dist_b1_b2 - dist_b1_a1;\r
+ }\r
+\r
+ segment_ratio<calc_t> ra_from(dist_b1_a1, dist_b1_b2);\r
+ segment_ratio<calc_t> ra_to(dist_b1_a2, dist_b1_b2);\r
+ segment_ratio<calc_t> rb_from(dist_a1_b1, dist_a1_a2);\r
+ segment_ratio<calc_t> rb_to(dist_a1_b2, dist_a1_a2);\r
+ \r
+ // NOTE: this is probably not needed\r
+ int const a1_wrt_b = position_value(c0, dist_a1_b1, dist_a1_b2);\r
+ int const a2_wrt_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);\r
+ int const b1_wrt_a = position_value(c0, dist_b1_a1, dist_b1_a2);\r
+ int const b2_wrt_a = position_value(dist_b1_b2, dist_b1_a1, dist_b1_a2);\r
+\r
+ if (a1_wrt_b == 1)\r
+ {\r
+ ra_from.assign(0, dist_b1_b2);\r
+ rb_from.assign(0, dist_a1_a2);\r
+ }\r
+ else if (a1_wrt_b == 3)\r
+ {\r
+ ra_from.assign(dist_b1_b2, dist_b1_b2);\r
+ rb_to.assign(0, dist_a1_a2);\r
+ }\r
+\r
+ if (a2_wrt_b == 1)\r
+ {\r
+ ra_to.assign(0, dist_b1_b2);\r
+ rb_from.assign(dist_a1_a2, dist_a1_a2);\r
+ }\r
+ else if (a2_wrt_b == 3)\r
+ {\r
+ ra_to.assign(dist_b1_b2, dist_b1_b2);\r
+ rb_to.assign(dist_a1_a2, dist_a1_a2);\r
+ }\r
+\r
+ if ((a1_wrt_b < 1 && a2_wrt_b < 1) || (a1_wrt_b > 3 && a2_wrt_b > 3))\r
+ {\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ bool const opposite = dot_n1n2 < c0;\r
+\r
+ return Policy::segments_collinear(a, b, opposite,\r
+ a1_wrt_b, a2_wrt_b, b1_wrt_a, b2_wrt_a,\r
+ ra_from, ra_to, rb_from, rb_to);\r
+ }\r
+ }\r
+ else // crossing\r
+ {\r
+ if (a_is_point || b_is_point)\r
+ {\r
+ return Policy::disjoint();\r
+ }\r
+\r
+ vec3d_t i1;\r
+ intersection_point_flag ip_flag;\r
+ calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;\r
+ if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v, norm1, norm2, sides,\r
+ i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag))\r
+ {\r
+ // intersects\r
+ segment_intersection_info\r
+ <\r
+ calc_t,\r
+ segment_ratio<calc_t>,\r
+ vec3d_t\r
+ > sinfo;\r
+\r
+ sinfo.robust_ra.assign(dist_a1_i1, dist_a1_a2);\r
+ sinfo.robust_rb.assign(dist_b1_i1, dist_b1_b2);\r
+ sinfo.intersection_point = i1;\r
+ sinfo.ip_flag = ip_flag;\r
+\r
+ return Policy::segments_crosses(sides, sinfo, a, b);\r
+ }\r
+ else\r
+ {\r
+ return Policy::disjoint();\r
+ }\r
+ }\r
+ }\r
+\r
+private:\r
+ template <typename CalcT, typename Segment, typename Point1, typename Point2, typename Vec3d>\r
+ static inline return_type collinear_one_degenerted(Segment const& segment, bool degenerated_a,\r
+ Point1 const& a1, Point1 const& a2,\r
+ Point2 const& b1, Point2 const& b2,\r
+ Vec3d const& v1, Vec3d const& v2, Vec3d const& norm,\r
+ Vec3d const& vother)\r
+ {\r
+ CalcT dist_1_2, dist_1_o;\r
+ return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, norm, vother, dist_1_2, dist_1_o)\r
+ ? Policy::disjoint()\r
+ : Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);\r
+ }\r
+\r
+ template <typename Point1, typename Point2, typename Vec3d, typename CalcT>\r
+ static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2,\r
+ Point2 const& b1, Point2 const& b2,\r
+ Vec3d const& a1v, // in\r
+ Vec3d const& a2v, // in\r
+ Vec3d const& norm1, // in\r
+ Vec3d const& b1v_or_b2v, // in\r
+ CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out\r
+ {\r
+ // calculate dist_a1_a2 and dist_a1_i1\r
+ calculate_dists(a1v, a2v, norm1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);\r
+\r
+ // if i1 is close to a1 and b1 or b2 is equal to a1\r
+ if (is_endpoint_equal(dist_a1_i1, a1, b1, b2))\r
+ {\r
+ dist_a1_i1 = 0;\r
+ return true;\r
+ }\r
+ // or i1 is close to a2 and b1 or b2 is equal to a2\r
+ else if (is_endpoint_equal(dist_a1_a2 - dist_a1_i1, a2, b1, b2))\r
+ {\r
+ dist_a1_i1 = dist_a1_a2;\r
+ return true;\r
+ }\r
+\r
+ // or i1 is on b\r
+ return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();\r
+ }\r
+\r
+ template <typename Point1, typename Point2, typename Vec3d, typename CalcT>\r
+ static inline bool calculate_ip_data(Point1 const& a1, Point1 const& a2, // in\r
+ Point2 const& b1, Point2 const& b2, // in\r
+ Vec3d const& a1v, Vec3d const& a2v, // in\r
+ Vec3d const& b1v, Vec3d const& b2v, // in\r
+ Vec3d const& norm1, Vec3d const& norm2, // in\r
+ side_info const& sides, // in\r
+ Vec3d & i1, // in-out\r
+ CalcT& dist_a1_a2, CalcT& dist_a1_i1, // out\r
+ CalcT& dist_b1_b2, CalcT& dist_b1_i1, // out\r
+ intersection_point_flag& ip_flag) // out\r
+ {\r
+ // great circles intersections\r
+ i1 = cross_product(norm1, norm2);\r
+ // NOTE: the length should be greater than 0 at this point\r
+ // if the normals were not normalized and their dot product\r
+ // not checked before this function is called the length\r
+ // should be checked here (math::equals(len, c0))\r
+ CalcT const len = math::sqrt(dot_product(i1, i1));\r
+ divide_value(i1, len); // normalize i1\r
+\r
+ calculate_dists(a1v, a2v, norm1, i1, dist_a1_a2, dist_a1_i1);\r
+ \r
+ // choose the opposite side of the globe if the distance is shorter\r
+ {\r
+ CalcT const d = abs_distance(dist_a1_a2, dist_a1_i1);\r
+ if (d > CalcT(0))\r
+ {\r
+ CalcT const dist_a1_i2 = dist_of_i2(dist_a1_i1);\r
+ CalcT const d2 = abs_distance(dist_a1_a2, dist_a1_i2);\r
+ if (d2 < d)\r
+ {\r
+ dist_a1_i1 = dist_a1_i2;\r
+ multiply_value(i1, CalcT(-1)); // the opposite intersection\r
+ }\r
+ }\r
+ }\r
+\r
+ bool is_on_a = false, is_near_a1 = false, is_near_a2 = false;\r
+ if (! is_potentially_crossing(dist_a1_a2, dist_a1_i1, is_on_a, is_near_a1, is_near_a2))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ calculate_dists(b1v, b2v, norm2, i1, dist_b1_b2, dist_b1_i1);\r
+\r
+ bool is_on_b = false, is_near_b1 = false, is_near_b2 = false;\r
+ if (! is_potentially_crossing(dist_b1_b2, dist_b1_i1, is_on_b, is_near_b1, is_near_b2))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // reassign the IP if some endpoints overlap\r
+ using geometry::detail::equals::equals_point_point;\r
+ if (is_near_a1)\r
+ {\r
+ if (is_near_b1 && equals_point_point(a1, b1))\r
+ {\r
+ dist_a1_i1 = 0;\r
+ dist_b1_i1 = 0;\r
+ //i1 = a1v;\r
+ ip_flag = ipi_at_a1;\r
+ return true;\r
+ }\r
+ \r
+ if (is_near_b2 && equals_point_point(a1, b2))\r
+ {\r
+ dist_a1_i1 = 0;\r
+ dist_b1_i1 = dist_b1_b2;\r
+ //i1 = a1v;\r
+ ip_flag = ipi_at_a1;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ if (is_near_a2)\r
+ {\r
+ if (is_near_b1 && equals_point_point(a2, b1))\r
+ {\r
+ dist_a1_i1 = dist_a1_a2;\r
+ dist_b1_i1 = 0;\r
+ //i1 = a2v;\r
+ ip_flag = ipi_at_a2;\r
+ return true;\r
+ }\r
+\r
+ if (is_near_b2 && equals_point_point(a2, b2))\r
+ {\r
+ dist_a1_i1 = dist_a1_a2;\r
+ dist_b1_i1 = dist_b1_b2;\r
+ //i1 = a2v;\r
+ ip_flag = ipi_at_a2;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ // at this point we know that the endpoints doesn't overlap\r
+ // reassign IP and distance if the IP is on a segment and one of\r
+ // the endpoints of the other segment lies on the former segment\r
+ if (is_on_a)\r
+ {\r
+ if (is_near_b1 && sides.template get<1, 0>() == 0) // b1 wrt a\r
+ {\r
+ dist_b1_i1 = 0;\r
+ //i1 = b1v;\r
+ ip_flag = ipi_at_b1;\r
+ return true;\r
+ }\r
+\r
+ if (is_near_b2 && sides.template get<1, 1>() == 0) // b2 wrt a\r
+ {\r
+ dist_b1_i1 = dist_b1_b2;\r
+ //i1 = b2v;\r
+ ip_flag = ipi_at_b2;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ if (is_on_b)\r
+ {\r
+ if (is_near_a1 && sides.template get<0, 0>() == 0) // a1 wrt b\r
+ {\r
+ dist_a1_i1 = 0;\r
+ //i1 = a1v;\r
+ ip_flag = ipi_at_a1;\r
+ return true;\r
+ }\r
+\r
+ if (is_near_a2 && sides.template get<0, 1>() == 0) // a2 wrt b\r
+ {\r
+ dist_a1_i1 = dist_a1_a2;\r
+ //i1 = a2v;\r
+ ip_flag = ipi_at_a2;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ ip_flag = ipi_inters;\r
+\r
+ return is_on_a && is_on_b;\r
+ }\r
+\r
+ template <typename Vec3d, typename CalcT>\r
+ static inline void calculate_dists(Vec3d const& a1v, // in\r
+ Vec3d const& a2v, // in\r
+ Vec3d const& norm1, // in\r
+ Vec3d const& i1, // in\r
+ CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out\r
+ {\r
+ CalcT const c0 = 0;\r
+ CalcT const c1 = 1;\r
+ CalcT const c2 = 2;\r
+ CalcT const c4 = 4;\r
+ \r
+ CalcT cos_a1_a2 = dot_product(a1v, a2v);\r
+ dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]\r
+\r
+ CalcT cos_a1_i1 = dot_product(a1v, i1);\r
+ dist_a1_i1 = -cos_a1_i1 + c1; // [0, 2] representing [0, pi]\r
+ if (dot_product(norm1, cross_product(a1v, i1)) < c0) // left or right of a1 on a\r
+ {\r
+ dist_a1_i1 = -dist_a1_i1; // [0, 2] -> [0, -2] representing [0, -pi]\r
+ }\r
+ if (dist_a1_i1 <= -c2) // <= -pi\r
+ {\r
+ dist_a1_i1 += c4; // += 2pi\r
+ }\r
+ }\r
+\r
+ // the dist of the ip on the other side of the sphere\r
+ template <typename CalcT>\r
+ static inline CalcT dist_of_i2(CalcT const& dist_a1_i1)\r
+ {\r
+ CalcT const c2 = 2;\r
+ CalcT const c4 = 4;\r
+\r
+ CalcT dist_a1_i2 = dist_a1_i1 - c2; // dist_a1_i2 = dist_a1_i1 - pi;\r
+ if (dist_a1_i2 <= -c2) // <= -pi\r
+ {\r
+ dist_a1_i2 += c4; // += 2pi;\r
+ }\r
+ return dist_a1_i2;\r
+ }\r
+\r
+ template <typename CalcT>\r
+ static inline CalcT abs_distance(CalcT const& dist_a1_a2, CalcT const& dist_a1_i1)\r
+ {\r
+ if (dist_a1_i1 < CalcT(0))\r
+ return -dist_a1_i1;\r
+ else if (dist_a1_i1 > dist_a1_a2)\r
+ return dist_a1_i1 - dist_a1_a2;\r
+ else\r
+ return CalcT(0);\r
+ }\r
+\r
+ template <typename CalcT>\r
+ static inline bool is_potentially_crossing(CalcT const& dist_a1_a2, CalcT const& dist_a1_i1, // in\r
+ bool& is_on_a, bool& is_near_a1, bool& is_near_a2) // out\r
+ {\r
+ is_on_a = segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();\r
+ is_near_a1 = is_near(dist_a1_i1);\r
+ is_near_a2 = is_near(dist_a1_a2 - dist_a1_i1);\r
+ return is_on_a || is_near_a1 || is_near_a2;\r
+ }\r
+\r
+ template <typename CalcT, typename P1, typename P2>\r
+ static inline bool is_endpoint_equal(CalcT const& dist,\r
+ P1 const& ai, P2 const& b1, P2 const& b2)\r
+ {\r
+ using geometry::detail::equals::equals_point_point;\r
+ return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));\r
+ }\r
+\r
+ template <typename CalcT>\r
+ static inline bool is_near(CalcT const& dist)\r
+ {\r
+ CalcT const small_number = CalcT(boost::is_same<CalcT, float>::value ? 0.0001 : 0.00000001);\r
+ return math::abs(dist) <= small_number;\r
+ }\r
+\r
+ template <typename ProjCoord1, typename ProjCoord2>\r
+ static inline int position_value(ProjCoord1 const& ca1,\r
+ ProjCoord2 const& cb1,\r
+ ProjCoord2 const& cb2)\r
+ {\r
+ // S1x 0 1 2 3 4\r
+ // S2 |---------->\r
+ return math::equals(ca1, cb1) ? 1\r
+ : math::equals(ca1, cb2) ? 3\r
+ : cb1 < cb2 ?\r
+ ( ca1 < cb1 ? 0\r
+ : ca1 > cb2 ? 4\r
+ : 2 )\r
+ : ( ca1 > cb1 ? 0\r
+ : ca1 < cb2 ? 4\r
+ : 2 );\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+/*template <typename Policy, typename CalculationType>\r
+struct default_strategy<spherical_polar_tag, Policy, CalculationType>\r
+{\r
+ typedef relate_spherical_segments<Policy, CalculationType> type;\r
+};*/\r
+\r
+template <typename Policy, typename CalculationType>\r
+struct default_strategy<spherical_equatorial_tag, Policy, CalculationType>\r
+{\r
+ typedef relate_spherical_segments<Policy, CalculationType> type;\r
+};\r
+\r
+template <typename Policy, typename CalculationType>\r
+struct default_strategy<geographic_tag, Policy, CalculationType>\r
+{\r
+ typedef relate_spherical_segments<Policy, CalculationType> type;\r
+};\r
+\r
+} // namespace services\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::intersection\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_INTERSECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+\r
+#include <boost/geometry/algorithms/detail/course.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+/*!\r
+\brief Check at which side of a Great Circle segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename CalculationType = void>\r
+class side_by_cross_track\r
+{\r
+\r
+public :\r
+ template <typename P1, typename P2, typename P>\r
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename select_calculation_type_alt\r
+ <\r
+ CalculationType,\r
+ P1, P2, P\r
+ >::type\r
+ >::type calc_t;\r
+\r
+ calc_t d1 = 0.001; // m_strategy.apply(sp1, p);\r
+ calc_t crs_AD = geometry::detail::course<calc_t>(p1, p);\r
+ calc_t crs_AB = geometry::detail::course<calc_t>(p1, p2);\r
+ calc_t XTD = asin(sin(d1) * sin(crs_AD - crs_AB));\r
+\r
+ return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;\r
+ }\r
+};\r
+\r
+}} // namespace strategy::side\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2016.\r
+// Modifications copyright (c) 2016, Oracle and/or its affiliates.\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP\r
+\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_calculation_type.hpp>\r
+\r
+#include <boost/geometry/strategies/side.hpp>\r
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace strategy { namespace side\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename T>\r
+int spherical_side_formula(T const& lambda1, T const& delta1,\r
+ T const& lambda2, T const& delta2,\r
+ T const& lambda, T const& delta)\r
+{\r
+ // Create temporary points (vectors) on unit a sphere\r
+ T const cos_delta1 = cos(delta1);\r
+ T const c1x = cos_delta1 * cos(lambda1);\r
+ T const c1y = cos_delta1 * sin(lambda1);\r
+ T const c1z = sin(delta1);\r
+\r
+ T const cos_delta2 = cos(delta2);\r
+ T const c2x = cos_delta2 * cos(lambda2);\r
+ T const c2y = cos_delta2 * sin(lambda2);\r
+ T const c2z = sin(delta2);\r
+\r
+ // (Third point is converted directly)\r
+ T const cos_delta = cos(delta);\r
+\r
+ // Apply the "Spherical Side Formula" as presented on my blog\r
+ T const dist\r
+ = (c1y * c2z - c1z * c2y) * cos_delta * cos(lambda)\r
+ + (c1z * c2x - c1x * c2z) * cos_delta * sin(lambda)\r
+ + (c1x * c2y - c1y * c2x) * sin(delta);\r
+\r
+ T zero = T();\r
+ return math::equals(dist, zero) ? 0\r
+ : dist > zero ? 1\r
+ : -1; // dist < zero\r
+}\r
+\r
+}\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+/*!\r
+\brief Check at which side of a Great Circle segment a point lies\r
+ left of segment (> 0), right of segment (< 0), on segment (0)\r
+\ingroup strategies\r
+\tparam CalculationType \tparam_calculation\r
+ */\r
+template <typename CalculationType = void>\r
+class spherical_side_formula\r
+{\r
+\r
+public :\r
+ template <typename P1, typename P2, typename P>\r
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)\r
+ {\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename select_calculation_type_alt\r
+ <\r
+ CalculationType,\r
+ P1, P2, P\r
+ >::type\r
+ >::type calculation_type;\r
+\r
+ calculation_type const lambda1 = get_as_radian<0>(p1);\r
+ calculation_type const delta1 = get_as_radian<1>(p1);\r
+ calculation_type const lambda2 = get_as_radian<0>(p2);\r
+ calculation_type const delta2 = get_as_radian<1>(p2);\r
+ calculation_type const lambda = get_as_radian<0>(p);\r
+ calculation_type const delta = get_as_radian<1>(p);\r
+\r
+ return detail::spherical_side_formula(lambda1, delta1,\r
+ lambda2, delta2,\r
+ lambda, delta);\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+namespace services\r
+{\r
+\r
+/*template <typename CalculationType>\r
+struct default_strategy<spherical_polar_tag, CalculationType>\r
+{\r
+ typedef spherical_side_formula<CalculationType> type;\r
+};*/\r
+\r
+template <typename CalculationType>\r
+struct default_strategy<spherical_equatorial_tag, CalculationType>\r
+{\r
+ typedef spherical_side_formula<CalculationType> type;\r
+};\r
+\r
+template <typename CalculationType>\r
+struct default_strategy<geographic_tag, CalculationType>\r
+{\r
+ typedef spherical_side_formula<CalculationType> type;\r
+};\r
+\r
+}\r
+#endif\r
+\r
+}} // namespace strategy::side\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014-2016.\r
+// Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP\r
+\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+#include <boost/geometry/strategies/area.hpp>\r
+#include <boost/geometry/strategies/buffer.hpp>\r
+#include <boost/geometry/strategies/centroid.hpp>\r
+#include <boost/geometry/strategies/compare.hpp>\r
+#include <boost/geometry/strategies/convex_hull.hpp>\r
+#include <boost/geometry/strategies/distance.hpp>\r
+#include <boost/geometry/strategies/intersection.hpp>\r
+#include <boost/geometry/strategies/intersection_strategies.hpp> // for backward compatibility\r
+#include <boost/geometry/strategies/side.hpp>\r
+#include <boost/geometry/strategies/transform.hpp>\r
+#include <boost/geometry/strategies/within.hpp>\r
+\r
+#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>\r
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_end_flat.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_end_round.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_join_miter.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_join_round.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_point_circle.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_point_square.hpp>\r
+#include <boost/geometry/strategies/cartesian/buffer_side_straight.hpp>\r
+#include <boost/geometry/strategies/cartesian/centroid_average.hpp>\r
+#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>\r
+#include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>\r
+#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>\r
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>\r
+#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>\r
+#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>\r
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>\r
+\r
+#include <boost/geometry/strategies/spherical/area_huiller.hpp>\r
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>\r
+#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>\r
+#include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>\r
+#include <boost/geometry/strategies/spherical/compare_circular.hpp>\r
+#include <boost/geometry/strategies/spherical/intersection.hpp>\r
+#include <boost/geometry/strategies/spherical/ssf.hpp>\r
+\r
+#include <boost/geometry/strategies/geographic/distance_andoyer.hpp>\r
+#include <boost/geometry/strategies/geographic/distance_thomas.hpp>\r
+#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>\r
+//#include <boost/geometry/strategies/geographic/side_andoyer.hpp>\r
+//#include <boost/geometry/strategies/geographic/side_thomas.hpp>\r
+//#include <boost/geometry/strategies/geographic/side_vincenty.hpp>\r
+\r
+#include <boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp>\r
+#include <boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp>\r
+#include <boost/geometry/strategies/agnostic/hull_graham_andrew.hpp>\r
+#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>\r
+#include <boost/geometry/strategies/agnostic/point_in_point.hpp>\r
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>\r
+#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>\r
+\r
+#include <boost/geometry/strategies/agnostic/relate.hpp>\r
+\r
+#include <boost/geometry/strategies/strategy_transform.hpp>\r
+\r
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>\r
+#include <boost/geometry/strategies/transform/map_transformer.hpp>\r
+#include <boost/geometry/strategies/transform/inverse_transformer.hpp>\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP\r
+\r
+#include <cstddef>\r
+#include <cmath>\r
+#include <functional>\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#include <boost/geometry/algorithms/convert.hpp>\r
+#include <boost/geometry/arithmetic/arithmetic.hpp>\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/radian_access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/strategies/transform.hpp>\r
+\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace transform\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template\r
+<\r
+ typename Src, typename Dst,\r
+ std::size_t D, std::size_t N,\r
+ template <typename> class F\r
+>\r
+struct transform_coordinates\r
+{\r
+ template <typename T>\r
+ static inline void transform(Src const& source, Dst& dest, T value)\r
+ {\r
+ typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;\r
+\r
+ F<coordinate_type> function;\r
+ set<D>(dest, boost::numeric_cast<coordinate_type>(function(get<D>(source), value)));\r
+ transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Src, typename Dst,\r
+ std::size_t N,\r
+ template <typename> class F\r
+>\r
+struct transform_coordinates<Src, Dst, N, N, F>\r
+{\r
+ template <typename T>\r
+ static inline void transform(Src const& , Dst& , T )\r
+ {\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+ \brief Transformation strategy to copy one point to another using assignment operator\r
+ \ingroup transform\r
+ \tparam P point type\r
+ */\r
+template <typename P>\r
+struct copy_direct\r
+{\r
+ inline bool apply(P const& p1, P& p2) const\r
+ {\r
+ p2 = p1;\r
+ return true;\r
+ }\r
+};\r
+\r
+/*!\r
+ \brief Transformation strategy to do copy a point, copying per coordinate.\r
+ \ingroup transform\r
+ \tparam P1 first point type\r
+ \tparam P2 second point type\r
+ */\r
+template <typename P1, typename P2>\r
+struct copy_per_coordinate\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ // Defensive check, dimensions are equal, selected by specialization\r
+ assert_dimension_equal<P1, P2>();\r
+\r
+ geometry::convert(p1, p2);\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Transformation strategy to go from degree to radian and back\r
+ \ingroup transform\r
+ \tparam P1 first point type\r
+ \tparam P2 second point type\r
+ \tparam F additional functor to divide or multiply with d2r\r
+ */\r
+template <typename P1, typename P2, template <typename> class F>\r
+struct degree_radian_vv\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ // Spherical coordinates always have 2 coordinates measured in angles\r
+ // The optional third one is distance/height, provided in another strategy\r
+ // Polar coordinates having one angle, will be also in another strategy\r
+ assert_dimension<P1, 2>();\r
+ assert_dimension<P2, 2>();\r
+\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename select_coordinate_type<P1, P2>::type\r
+ >::type calculation_type;\r
+\r
+ detail::transform_coordinates\r
+ <\r
+ P1, P2, 0, 2, F\r
+ >::transform(p1, p2, math::d2r<calculation_type>());\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename P1, typename P2, template <typename> class F>\r
+struct degree_radian_vv_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ assert_dimension<P2, 3>();\r
+\r
+ typedef typename promote_floating_point\r
+ <\r
+ typename select_coordinate_type<P1, P2>::type\r
+ >::type calculation_type;\r
+\r
+ detail::transform_coordinates\r
+ <\r
+ P1, P2, 0, 2, F\r
+ >::transform(p1, p2, math::d2r<calculation_type>());\r
+\r
+ // Copy height or other third dimension\r
+ set<2>(p2, get<2>(p1));\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+ /// Helper function for conversion, phi/theta are in radians\r
+ template <typename P, typename T, typename R>\r
+ inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p)\r
+ {\r
+ assert_dimension<P, 3>();\r
+\r
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates\r
+ // http://www.vias.org/comp_geometry/math_coord_convert_3d.htm\r
+ // https://moodle.polymtl.ca/file.php/1183/Autres_Documents/Derivation_for_Spherical_Co-ordinates.pdf\r
+ // http://en.citizendium.org/wiki/Spherical_polar_coordinates\r
+\r
+ // Phi = first, theta is second, r is third, see documentation on cs::spherical\r
+\r
+ // (calculations are splitted to implement ttmath)\r
+\r
+ T r_sin_theta = r;\r
+ T r_cos_theta = r;\r
+ r_sin_theta *= sin(theta);\r
+ r_cos_theta *= cos(theta);\r
+\r
+ set<0>(p, r_sin_theta * cos(phi));\r
+ set<1>(p, r_sin_theta * sin(phi));\r
+ set<2>(p, r_cos_theta);\r
+ }\r
+\r
+ /// Helper function for conversion, lambda/delta (lon lat) are in radians\r
+ template <typename P, typename T, typename R>\r
+ inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p)\r
+ {\r
+ assert_dimension<P, 3>();\r
+\r
+ // http://mathworld.wolfram.com/GreatCircle.html\r
+ // http://www.spenvis.oma.be/help/background/coortran/coortran.html WRONG\r
+\r
+ T r_cos_delta = r;\r
+ T r_sin_delta = r;\r
+ r_cos_delta *= cos(delta);\r
+ r_sin_delta *= sin(delta);\r
+\r
+ set<0>(p, r_cos_delta * cos(lambda));\r
+ set<1>(p, r_cos_delta * sin(lambda));\r
+ set<2>(p, r_sin_delta);\r
+ }\r
+\r
+\r
+ /// Helper function for conversion\r
+ template <typename P, typename T>\r
+ inline bool cartesian_to_spherical2(T x, T y, T z, P& p)\r
+ {\r
+ assert_dimension<P, 2>();\r
+\r
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates\r
+\r
+#if defined(BOOST_GEOMETRY_TRANSFORM_CHECK_UNIT_SPHERE)\r
+ // TODO: MAYBE ONLY IF TO BE CHECKED?\r
+ T const r = /*sqrt not necessary, sqrt(1)=1*/ (x * x + y * y + z * z);\r
+\r
+ // Unit sphere, so r should be 1\r
+ if (geometry::math::abs(r - 1.0) > T(1e-6))\r
+ {\r
+ return false;\r
+ }\r
+ // end todo\r
+#endif\r
+\r
+ set_from_radian<0>(p, atan2(y, x));\r
+ set_from_radian<1>(p, acos(z));\r
+ return true;\r
+ }\r
+\r
+ template <typename P, typename T>\r
+ inline bool cartesian_to_spherical_equatorial2(T x, T y, T z, P& p)\r
+ {\r
+ assert_dimension<P, 2>();\r
+\r
+ set_from_radian<0>(p, atan2(y, x));\r
+ set_from_radian<1>(p, asin(z));\r
+ return true;\r
+ }\r
+\r
+\r
+ template <typename P, typename T>\r
+ inline bool cartesian_to_spherical3(T x, T y, T z, P& p)\r
+ {\r
+ assert_dimension<P, 3>();\r
+\r
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates\r
+ T const r = math::sqrt(x * x + y * y + z * z);\r
+ set<2>(p, r);\r
+ set_from_radian<0>(p, atan2(y, x));\r
+ if (r > 0.0)\r
+ {\r
+ set_from_radian<1>(p, acos(z / r));\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ template <typename P, typename T>\r
+ inline bool cartesian_to_spherical_equatorial3(T x, T y, T z, P& p)\r
+ {\r
+ assert_dimension<P, 3>();\r
+\r
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates\r
+ T const r = math::sqrt(x * x + y * y + z * z);\r
+ set<2>(p, r);\r
+ set_from_radian<0>(p, atan2(y, x));\r
+ if (r > 0.0)\r
+ {\r
+ set_from_radian<1>(p, asin(z / r));\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+ \brief Transformation strategy for 2D spherical (phi,theta) to 3D cartesian (x,y,z)\r
+ \details on Unit sphere\r
+ \ingroup transform\r
+ \tparam P1 first point type\r
+ \tparam P2 second point type\r
+ */\r
+template <typename P1, typename P2>\r
+struct from_spherical_polar_2_to_cartesian_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 2>();\r
+ detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename P1, typename P2>\r
+struct from_spherical_equatorial_2_to_cartesian_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 2>();\r
+ detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Transformation strategy for 3D spherical (phi,theta,r) to 3D cartesian (x,y,z)\r
+ \ingroup transform\r
+ \tparam P1 first point type\r
+ \tparam P2 second point type\r
+ */\r
+template <typename P1, typename P2>\r
+struct from_spherical_polar_3_to_cartesian_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ detail::spherical_polar_to_cartesian(\r
+ get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);\r
+ return true;\r
+ }\r
+};\r
+\r
+template <typename P1, typename P2>\r
+struct from_spherical_equatorial_3_to_cartesian_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ detail::spherical_equatorial_to_cartesian(\r
+ get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);\r
+ return true;\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Transformation strategy for 3D cartesian (x,y,z) to 2D spherical (phi,theta)\r
+ \details on Unit sphere\r
+ \ingroup transform\r
+ \tparam P1 first point type\r
+ \tparam P2 second point type\r
+ \note If x,y,z point is not lying on unit sphere, transformation will return false\r
+ */\r
+template <typename P1, typename P2>\r
+struct from_cartesian_3_to_spherical_polar_2\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);\r
+ }\r
+};\r
+\r
+template <typename P1, typename P2>\r
+struct from_cartesian_3_to_spherical_equatorial_2\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ return detail::cartesian_to_spherical_equatorial2(get<0>(p1), get<1>(p1), get<2>(p1), p2);\r
+ }\r
+};\r
+\r
+\r
+/*!\r
+ \brief Transformation strategy for 3D cartesian (x,y,z) to 3D spherical (phi,theta,r)\r
+ \ingroup transform\r
+ \tparam P1 first point type\r
+ \tparam P2 second point type\r
+ */\r
+template <typename P1, typename P2>\r
+struct from_cartesian_3_to_spherical_polar_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);\r
+ }\r
+};\r
+\r
+template <typename P1, typename P2>\r
+struct from_cartesian_3_to_spherical_equatorial_3\r
+{\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension<P1, 3>();\r
+ return detail::cartesian_to_spherical_equatorial3(get<0>(p1), get<1>(p1), get<2>(p1), p2);\r
+ }\r
+};\r
+\r
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+namespace services\r
+{\r
+\r
+/// Specialization for same coordinate system family, same system, same dimension, same point type, can be copied\r
+template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>\r
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>\r
+{\r
+ typedef copy_direct<P> type;\r
+};\r
+\r
+/// Specialization for same coordinate system family and system, same dimension, different point type, copy per coordinate\r
+template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>\r
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>\r
+{\r
+ typedef copy_per_coordinate<P1, P2> type;\r
+};\r
+\r
+/// Specialization to transform from degree to radian for any coordinate system / point type combination\r
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>\r
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>\r
+{\r
+ typedef degree_radian_vv<P1, P2, std::multiplies> type;\r
+};\r
+\r
+/// Specialization to transform from radian to degree for any coordinate system / point type combination\r
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>\r
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>\r
+{\r
+ typedef degree_radian_vv<P1, P2, std::divides> type;\r
+};\r
+\r
+\r
+/// Specialization degree->radian in 3D\r
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>\r
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>\r
+{\r
+ typedef degree_radian_vv_3<P1, P2, std::multiplies> type;\r
+};\r
+\r
+/// Specialization radian->degree in 3D\r
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>\r
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>\r
+{\r
+ typedef degree_radian_vv_3<P1, P2, std::divides> type;\r
+};\r
+\r
+/// Specialization to transform from unit sphere(phi,theta) to XYZ\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>\r
+{\r
+ typedef from_spherical_polar_2_to_cartesian_3<P1, P2> type;\r
+};\r
+\r
+/// Specialization to transform from sphere(phi,theta,r) to XYZ\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>\r
+{\r
+ typedef from_spherical_polar_3_to_cartesian_3<P1, P2> type;\r
+};\r
+\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>\r
+{\r
+ typedef from_spherical_equatorial_2_to_cartesian_3<P1, P2> type;\r
+};\r
+\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>\r
+{\r
+ typedef from_spherical_equatorial_3_to_cartesian_3<P1, P2> type;\r
+};\r
+\r
+/// Specialization to transform from XYZ to unit sphere(phi,theta)\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>\r
+{\r
+ typedef from_cartesian_3_to_spherical_polar_2<P1, P2> type;\r
+};\r
+\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>\r
+{\r
+ typedef from_cartesian_3_to_spherical_equatorial_2<P1, P2> type;\r
+};\r
+\r
+/// Specialization to transform from XYZ to sphere(phi,theta,r)\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>\r
+{\r
+ typedef from_cartesian_3_to_spherical_polar_3<P1, P2> type;\r
+};\r
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>\r
+struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>\r
+{\r
+ typedef from_cartesian_3_to_spherical_equatorial_3<P1, P2> type;\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace strategy::transform\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_TAGS_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_TAGS_HPP\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy\r
+{\r
+ /*!\r
+ \brief Indicate compiler/library user that strategy is not implemented.\r
+ \details Strategies are defined for point types or for point type\r
+ combinations. If there is no implementation for that specific point type, or point type\r
+ combination, the calculation cannot be done. To indicate this, this not_implemented\r
+ class is used as a typedef stub.\r
+\r
+ */\r
+ struct not_implemented {};\r
+}\r
+\r
+\r
+struct strategy_tag_distance_point_point {};\r
+struct strategy_tag_distance_point_segment {};\r
+struct strategy_tag_distance_point_box {};\r
+struct strategy_tag_distance_box_box {};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_TAGS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+#include <boost/geometry/strategies/tags.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace transform { namespace services\r
+{\r
+\r
+/*!\r
+ \brief Traits class binding a transformation strategy to a coordinate system\r
+ \ingroup transform\r
+ \details Can be specialized\r
+ - per coordinate system family (tag)\r
+ - per coordinate system (or groups of them)\r
+ - per dimension\r
+ - per point type\r
+ \tparam CoordinateSystemTag 1,2 coordinate system tags\r
+ \tparam CoordinateSystem 1,2 coordinate system\r
+ \tparam D 1, 2 dimension\r
+ \tparam Point 1, 2 point type\r
+ */\r
+template\r
+<\r
+ typename CoordinateSystemTag1, typename CoordinateSystemTag2,\r
+ typename CoordinateSystem1, typename CoordinateSystem2,\r
+ std::size_t Dimension1, std::size_t Dimension2,\r
+ typename Point1, typename Point2\r
+>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPES\r
+ , (types<Point1, Point2>)\r
+ );\r
+};\r
+\r
+}}} // namespace strategy::transform::services\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP\r
+\r
+// Remove the ublas checking, otherwise the inverse might fail\r
+// (while nothing seems to be wrong)\r
+#ifdef BOOST_UBLAS_TYPE_CHECK\r
+#undef BOOST_UBLAS_TYPE_CHECK\r
+#endif\r
+#define BOOST_UBLAS_TYPE_CHECK 0\r
+\r
+#include <boost/numeric/ublas/lu.hpp>\r
+#include <boost/numeric/ublas/io.hpp>\r
+\r
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace transform\r
+{\r
+\r
+/*!\r
+\brief Transformation strategy to do an inverse transformation in a Cartesian coordinate system\r
+\ingroup strategies\r
+ */\r
+template\r
+<\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2\r
+>\r
+class inverse_transformer\r
+ : public ublas_transformer<CalculationType, Dimension1, Dimension2>\r
+{\r
+public :\r
+ template <typename Transformer>\r
+ inline inverse_transformer(Transformer const& input)\r
+ {\r
+ typedef boost::numeric::ublas::matrix<CalculationType> matrix_type;\r
+\r
+ // create a working copy of the input\r
+ matrix_type copy(input.matrix());\r
+\r
+ // create a permutation matrix for the LU-factorization\r
+ typedef boost::numeric::ublas::permutation_matrix<> permutation_matrix;\r
+ permutation_matrix pm(copy.size1());\r
+\r
+ // perform LU-factorization\r
+ int res = boost::numeric::ublas::lu_factorize<matrix_type>(copy, pm);\r
+ if( res == 0 )\r
+ {\r
+ // create identity matrix\r
+ this->m_matrix.assign(boost::numeric::ublas::identity_matrix<CalculationType>(copy.size1()));\r
+\r
+ // backsubstitute to get the inverse\r
+ boost::numeric::ublas::lu_substitute(copy, pm, this->m_matrix);\r
+ }\r
+ }\r
+\r
+};\r
+\r
+\r
+}} // namespace strategy::transform\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4127: conditional expression is constant\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4127)\r
+#endif\r
+\r
+namespace strategy { namespace transform\r
+{\r
+\r
+/*!\r
+\brief Transformation strategy to map from one to another Cartesian coordinate system\r
+\ingroup strategies\r
+\tparam Mirror if true map is mirrored upside-down (in most cases pixels\r
+ are from top to bottom, while map is from bottom to top)\r
+ */\r
+template\r
+<\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2,\r
+ bool Mirror = false,\r
+ bool SameScale = true\r
+>\r
+class map_transformer\r
+ : public ublas_transformer<CalculationType, Dimension1, Dimension2>\r
+{\r
+ typedef boost::numeric::ublas::matrix<CalculationType> M;\r
+\r
+public :\r
+ template <typename B, typename D>\r
+ explicit inline map_transformer(B const& box, D const& width, D const& height)\r
+ {\r
+ set_transformation(\r
+ get<min_corner, 0>(box), get<min_corner, 1>(box),\r
+ get<max_corner, 0>(box), get<max_corner, 1>(box),\r
+ width, height);\r
+ }\r
+\r
+ template <typename W, typename D>\r
+ explicit inline map_transformer(W const& wx1, W const& wy1, W const& wx2, W const& wy2,\r
+ D const& width, D const& height)\r
+ {\r
+ set_transformation(wx1, wy1, wx2, wy2, width, height);\r
+ }\r
+\r
+\r
+private :\r
+ template <typename W, typename P, typename S>\r
+ inline void set_transformation_point(W const& wx, W const& wy,\r
+ P const& px, P const& py,\r
+ S const& scalex, S const& scaley)\r
+ {\r
+\r
+ // Translate to a coordinate system centered on world coordinates (-wx, -wy)\r
+ M t1(3,3);\r
+ t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx;\r
+ t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy;\r
+ t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1;\r
+\r
+ // Scale the map\r
+ M s(3,3);\r
+ s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0;\r
+ s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0;\r
+ s(2,0) = 0; s(2,1) = 0; s(2,2) = 1;\r
+\r
+ // Translate to a coordinate system centered on the specified pixels (+px, +py)\r
+ M t2(3, 3);\r
+ t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px;\r
+ t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py;\r
+ t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1;\r
+\r
+ // Calculate combination matrix in two steps\r
+ this->m_matrix = boost::numeric::ublas::prod(s, t1);\r
+ this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix);\r
+ }\r
+\r
+\r
+ template <typename W, typename D>\r
+ void set_transformation(W const& wx1, W const& wy1, W const& wx2, W const& wy2,\r
+ D const& width, D const& height)\r
+ {\r
+ D px1 = 0;\r
+ D py1 = 0;\r
+ D px2 = width;\r
+ D py2 = height;\r
+\r
+ // Get the same type, but at least a double\r
+ typedef typename select_most_precise<D, double>::type type;\r
+\r
+\r
+ // Calculate appropriate scale, take min because whole box must fit\r
+ // Scale is in PIXELS/MAPUNITS (meters)\r
+ W wdx = wx2 - wx1;\r
+ W wdy = wy2 - wy1;\r
+ type sx = (px2 - px1) / boost::numeric_cast<type>(wdx);\r
+ type sy = (py2 - py1) / boost::numeric_cast<type>(wdy);\r
+\r
+ if (SameScale)\r
+ {\r
+ type scale = (std::min)(sx, sy);\r
+ sx = scale;\r
+ sy = scale;\r
+ }\r
+\r
+ // Calculate centerpoints\r
+ W wtx = wx1 + wx2;\r
+ W wty = wy1 + wy2;\r
+ W two = 2;\r
+ W wmx = wtx / two;\r
+ W wmy = wty / two;\r
+ type pmx = (px1 + px2) / 2.0;\r
+ type pmy = (py1 + py2) / 2.0;\r
+\r
+ set_transformation_point(wmx, wmy, pmx, pmy, sx, sy);\r
+\r
+ if (Mirror)\r
+ {\r
+ // Mirror in y-direction\r
+ M m(3,3);\r
+ m(0,0) = 1; m(0,1) = 0; m(0,2) = 0;\r
+ m(1,0) = 0; m(1,1) = -1; m(1,2) = 0;\r
+ m(2,0) = 0; m(2,1) = 0; m(2,2) = 1;\r
+\r
+ // Translate in y-direction such that it fits again\r
+ M y(3, 3);\r
+ y(0,0) = 1; y(0,1) = 0; y(0,2) = 0;\r
+ y(1,0) = 0; y(1,1) = 1; y(1,2) = height;\r
+ y(2,0) = 0; y(2,1) = 0; y(2,2) = 1;\r
+\r
+ // Calculate combination matrix in two steps\r
+ this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix);\r
+ this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix);\r
+ }\r
+ }\r
+};\r
+\r
+\r
+}} // namespace strategy::transform\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP\r
+\r
+\r
+#include <cstddef>\r
+\r
+// Remove the ublas checking, otherwise the inverse might fail\r
+// (while nothing seems to be wrong)\r
+#ifdef BOOST_UBLAS_TYPE_CHECK\r
+#undef BOOST_UBLAS_TYPE_CHECK\r
+#endif\r
+#define BOOST_UBLAS_TYPE_CHECK 0\r
+\r
+#include <boost/numeric/conversion/cast.hpp>\r
+\r
+#if defined(__clang__)\r
+// Avoid warning about unused UBLAS function: boost_numeric_ublas_abs\r
+#pragma clang diagnostic push\r
+#pragma clang diagnostic ignored "-Wunused-function"\r
+#endif\r
+\r
+#include <boost/numeric/ublas/vector.hpp>\r
+#include <boost/numeric/ublas/matrix.hpp>\r
+\r
+#if defined(__clang__)\r
+#pragma clang diagnostic pop\r
+#endif\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/promote_floating_point.hpp>\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace transform\r
+{\r
+\r
+/*!\r
+\brief Affine transformation strategy in Cartesian system.\r
+\details The strategy serves as a generic definition of affine transformation matrix\r
+ and procedure of application it to given point.\r
+\see http://en.wikipedia.org/wiki/Affine_transformation\r
+ and http://www.devmaster.net/wiki/Transformation_matrices\r
+\ingroup strategies\r
+\tparam Dimension1 number of dimensions to transform from\r
+\tparam Dimension2 number of dimensions to transform to\r
+ */\r
+template\r
+<\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2\r
+>\r
+class ublas_transformer\r
+{\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+class ublas_transformer<CalculationType, 2, 2>\r
+{\r
+protected :\r
+ typedef CalculationType ct;\r
+ typedef boost::numeric::ublas::matrix<ct> matrix_type;\r
+ matrix_type m_matrix;\r
+\r
+public :\r
+\r
+ inline ublas_transformer(\r
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,\r
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,\r
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)\r
+ : m_matrix(3, 3)\r
+ {\r
+ m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;\r
+ m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;\r
+ m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;\r
+ }\r
+\r
+ inline ublas_transformer(matrix_type const& matrix)\r
+ : m_matrix(matrix)\r
+ {}\r
+\r
+\r
+ inline ublas_transformer() : m_matrix(3, 3) {}\r
+\r
+ template <typename P1, typename P2>\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ assert_dimension_greater_equal<P1, 2>();\r
+ assert_dimension_greater_equal<P2, 2>();\r
+\r
+ ct const& c1 = get<0>(p1);\r
+ ct const& c2 = get<1>(p1);\r
+\r
+ ct p2x = c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2);\r
+ ct p2y = c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2);\r
+\r
+ typedef typename geometry::coordinate_type<P2>::type ct2;\r
+ set<0>(p2, boost::numeric_cast<ct2>(p2x));\r
+ set<1>(p2, boost::numeric_cast<ct2>(p2y));\r
+\r
+ return true;\r
+ }\r
+\r
+ matrix_type const& matrix() const { return m_matrix; }\r
+};\r
+\r
+\r
+// It IS possible to go from 3 to 2 coordinates\r
+template <typename CalculationType>\r
+class ublas_transformer<CalculationType, 3, 2> : public ublas_transformer<CalculationType, 2, 2>\r
+{\r
+ typedef CalculationType ct;\r
+\r
+public :\r
+ inline ublas_transformer(\r
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,\r
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,\r
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)\r
+ : ublas_transformer<CalculationType, 2, 2>(\r
+ m_0_0, m_0_1, m_0_2,\r
+ m_1_0, m_1_1, m_1_2,\r
+ m_2_0, m_2_1, m_2_2)\r
+ {}\r
+\r
+ inline ublas_transformer()\r
+ : ublas_transformer<CalculationType, 2, 2>()\r
+ {}\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+class ublas_transformer<CalculationType, 3, 3>\r
+{\r
+protected :\r
+ typedef CalculationType ct;\r
+ typedef boost::numeric::ublas::matrix<ct> matrix_type;\r
+ matrix_type m_matrix;\r
+\r
+public :\r
+ inline ublas_transformer(\r
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,\r
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,\r
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,\r
+ ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3\r
+ )\r
+ : m_matrix(4, 4)\r
+ {\r
+ m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;\r
+ m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;\r
+ m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;\r
+ m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;\r
+ }\r
+\r
+ inline ublas_transformer() : m_matrix(4, 4) {}\r
+\r
+ template <typename P1, typename P2>\r
+ inline bool apply(P1 const& p1, P2& p2) const\r
+ {\r
+ ct const& c1 = get<0>(p1);\r
+ ct const& c2 = get<1>(p1);\r
+ ct const& c3 = get<2>(p1);\r
+\r
+ typedef typename geometry::coordinate_type<P2>::type ct2;\r
+\r
+ set<0>(p2, boost::numeric_cast<ct2>(\r
+ c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + c3 * m_matrix(0,2) + m_matrix(0,3)));\r
+ set<1>(p2, boost::numeric_cast<ct2>(\r
+ c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + c3 * m_matrix(1,2) + m_matrix(1,3)));\r
+ set<2>(p2, boost::numeric_cast<ct2>(\r
+ c1 * m_matrix(2,0) + c2 * m_matrix(2,1) + c3 * m_matrix(2,2) + m_matrix(2,3)));\r
+\r
+ return true;\r
+ }\r
+\r
+ matrix_type const& matrix() const { return m_matrix; }\r
+};\r
+\r
+\r
+/*!\r
+\brief Strategy of translate transformation in Cartesian system.\r
+\details Translate moves a geometry a fixed distance in 2 or 3 dimensions.\r
+\see http://en.wikipedia.org/wiki/Translation_%28geometry%29\r
+\ingroup strategies\r
+\tparam Dimension1 number of dimensions to transform from\r
+\tparam Dimension2 number of dimensions to transform to\r
+ */\r
+template\r
+<\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2\r
+>\r
+class translate_transformer\r
+{\r
+};\r
+\r
+\r
+template<typename CalculationType>\r
+class translate_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>\r
+{\r
+public :\r
+ // To have translate transformers compatible for 2/3 dimensions, the\r
+ // constructor takes an optional third argument doing nothing.\r
+ inline translate_transformer(CalculationType const& translate_x,\r
+ CalculationType const& translate_y,\r
+ CalculationType const& = 0)\r
+ : ublas_transformer<CalculationType, 2, 2>(\r
+ 1, 0, translate_x,\r
+ 0, 1, translate_y,\r
+ 0, 0, 1)\r
+ {}\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+class translate_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>\r
+{\r
+public :\r
+ inline translate_transformer(CalculationType const& translate_x,\r
+ CalculationType const& translate_y,\r
+ CalculationType const& translate_z)\r
+ : ublas_transformer<CalculationType, 3, 3>(\r
+ 1, 0, 0, translate_x,\r
+ 0, 1, 0, translate_y,\r
+ 0, 0, 1, translate_z,\r
+ 0, 0, 0, 1)\r
+ {}\r
+\r
+};\r
+\r
+\r
+/*!\r
+\brief Strategy of scale transformation in Cartesian system.\r
+\details Scale scales a geometry up or down in all its dimensions.\r
+\see http://en.wikipedia.org/wiki/Scaling_%28geometry%29\r
+\ingroup strategies\r
+\tparam Dimension1 number of dimensions to transform from\r
+\tparam Dimension2 number of dimensions to transform to\r
+*/\r
+template\r
+<\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2\r
+>\r
+class scale_transformer\r
+{\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+class scale_transformer<CalculationType, 2, 2> : public ublas_transformer<CalculationType, 2, 2>\r
+{\r
+\r
+public :\r
+ inline scale_transformer(CalculationType const& scale_x,\r
+ CalculationType const& scale_y,\r
+ CalculationType const& = 0)\r
+ : ublas_transformer<CalculationType, 2, 2>(\r
+ scale_x, 0, 0,\r
+ 0, scale_y, 0,\r
+ 0, 0, 1)\r
+ {}\r
+\r
+\r
+ inline scale_transformer(CalculationType const& scale)\r
+ : ublas_transformer<CalculationType, 2, 2>(\r
+ scale, 0, 0,\r
+ 0, scale, 0,\r
+ 0, 0, 1)\r
+ {}\r
+};\r
+\r
+\r
+template <typename CalculationType>\r
+class scale_transformer<CalculationType, 3, 3> : public ublas_transformer<CalculationType, 3, 3>\r
+{\r
+public :\r
+ inline scale_transformer(CalculationType const& scale_x,\r
+ CalculationType const& scale_y,\r
+ CalculationType const& scale_z)\r
+ : ublas_transformer<CalculationType, 3, 3>(\r
+ scale_x, 0, 0, 0,\r
+ 0, scale_y, 0, 0,\r
+ 0, 0, scale_z, 0,\r
+ 0, 0, 0, 1)\r
+ {}\r
+\r
+\r
+ inline scale_transformer(CalculationType const& scale)\r
+ : ublas_transformer<CalculationType, 3, 3>(\r
+ scale, 0, 0, 0,\r
+ 0, scale, 0, 0,\r
+ 0, 0, scale, 0,\r
+ 0, 0, 0, 1)\r
+ {}\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename DegreeOrRadian>\r
+struct as_radian\r
+{};\r
+\r
+\r
+template <>\r
+struct as_radian<radian>\r
+{\r
+ template <typename T>\r
+ static inline T get(T const& value)\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+template <>\r
+struct as_radian<degree>\r
+{\r
+ template <typename T>\r
+ static inline T get(T const& value)\r
+ {\r
+ typedef typename promote_floating_point<T>::type promoted_type;\r
+ return value * math::d2r<promoted_type>();\r
+ }\r
+\r
+};\r
+\r
+\r
+template\r
+<\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2\r
+>\r
+class rad_rotate_transformer\r
+ : public ublas_transformer<CalculationType, Dimension1, Dimension2>\r
+{\r
+public :\r
+ inline rad_rotate_transformer(CalculationType const& angle)\r
+ : ublas_transformer<CalculationType, Dimension1, Dimension2>(\r
+ cos(angle), sin(angle), 0,\r
+ -sin(angle), cos(angle), 0,\r
+ 0, 0, 1)\r
+ {}\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Strategy for rotate transformation in Cartesian coordinate system.\r
+\details Rotate rotates a geometry of specified angle about a fixed point (e.g. origin).\r
+\see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29\r
+\ingroup strategies\r
+\tparam DegreeOrRadian degree/or/radian, type of rotation angle specification\r
+\note A single angle is needed to specify a rotation in 2D.\r
+ Not yet in 3D, the 3D version requires special things to allow\r
+ for rotation around X, Y, Z or arbitrary axis.\r
+\todo The 3D version will not compile.\r
+ */\r
+template\r
+<\r
+ typename DegreeOrRadian,\r
+ typename CalculationType,\r
+ std::size_t Dimension1,\r
+ std::size_t Dimension2\r
+>\r
+class rotate_transformer : public detail::rad_rotate_transformer<CalculationType, Dimension1, Dimension2>\r
+{\r
+\r
+public :\r
+ inline rotate_transformer(CalculationType const& angle)\r
+ : detail::rad_rotate_transformer\r
+ <\r
+ CalculationType, Dimension1, Dimension2\r
+ >(detail::as_radian<DegreeOrRadian>::get(angle))\r
+ {}\r
+};\r
+\r
+\r
+}} // namespace strategy::transform\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP\r
+#define BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP\r
+\r
+#include <boost/mpl/assert.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace strategy { namespace within\r
+{\r
+\r
+\r
+namespace services\r
+{\r
+\r
+/*!\r
+\brief Traits class binding a within determination strategy to a coordinate system\r
+\ingroup within\r
+\tparam TagContained tag (possibly casted) of point-type\r
+\tparam TagContained tag (possibly casted) of (possibly) containing type\r
+\tparam CsTagContained tag of coordinate system of point-type\r
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type\r
+\tparam Geometry geometry-type of input (often point, or box)\r
+\tparam GeometryContaining geometry-type of input (possibly) containing type\r
+*/\r
+template\r
+<\r
+ typename TagContained,\r
+ typename TagContaining,\r
+ typename CastedTagContained,\r
+ typename CastedTagContaining,\r
+ typename CsTagContained,\r
+ typename CsTagContaining,\r
+ typename GeometryContained,\r
+ typename GeometryContaining\r
+>\r
+struct default_strategy\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES\r
+ , (types<GeometryContained, GeometryContaining>)\r
+ );\r
+};\r
+\r
+\r
+} // namespace services\r
+\r
+\r
+}} // namespace strategy::within\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP\r
+#define BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP\r
+\r
+\r
+#include <boost/mpl/if.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Meta-function to define a const or non const type\r
+ \ingroup utility\r
+ \details If the boolean template parameter is true, the type parameter\r
+ will be defined as const, otherwise it will be defined as it was.\r
+ This meta-function is used to have one implementation for both\r
+ const and non const references\r
+ \note This traits class is completely independant from Boost.Geometry\r
+ and might be a separate addition to Boost\r
+ \note Used in a.o. for_each, interior_rings, exterior_ring\r
+ \par Example\r
+ \code\r
+ void foo(typename add_const_if_c<IsConst, Point>::type& point)\r
+ \endcode\r
+*/\r
+template <bool IsConst, typename Type>\r
+struct add_const_if_c\r
+{\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ IsConst,\r
+ Type const,\r
+ Type\r
+ >::type type;\r
+};\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP\r
+#define BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP\r
+\r
+\r
+#include <boost/type_traits/remove_const.hpp>\r
+#include <boost/type_traits/remove_pointer.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace util\r
+{\r
+\r
+template <typename T>\r
+struct bare_type\r
+{\r
+ typedef typename boost::remove_const\r
+ <\r
+ typename boost::remove_pointer\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ T\r
+ >::type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace util\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2012 Mateusz Loskot, London, UK.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP\r
+#define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP\r
+\r
+#include <boost/config.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+#include <boost/type_traits/is_fundamental.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace util\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+struct default_integral\r
+{\r
+#ifdef BOOST_HAS_LONG_LONG\r
+ typedef boost::long_long_type type;\r
+#else\r
+ typedef int type;\r
+#endif\r
+};\r
+\r
+/*!\r
+\details Selects the most appropriate:\r
+ - if calculation type is specified (not void), that one is used\r
+ - else if type is non-fundamental (user defined e.g. ttmath), that one\r
+ - else if type is floating point, the specified default FP is used\r
+ - else it is integral and the specified default integral is used\r
+ */\r
+template\r
+<\r
+ typename Type,\r
+ typename CalculationType,\r
+ typename DefaultFloatingPointCalculationType,\r
+ typename DefaultIntegralCalculationType\r
+>\r
+struct calculation_type\r
+{\r
+ BOOST_STATIC_ASSERT((\r
+ boost::is_fundamental\r
+ <\r
+ DefaultFloatingPointCalculationType\r
+ >::type::value\r
+ ));\r
+ BOOST_STATIC_ASSERT((\r
+ boost::is_fundamental\r
+ <\r
+ DefaultIntegralCalculationType\r
+ >::type::value\r
+ ));\r
+\r
+\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_void<CalculationType>,\r
+ typename boost::mpl::if_\r
+ <\r
+ boost::is_floating_point<Type>,\r
+ typename select_most_precise\r
+ <\r
+ DefaultFloatingPointCalculationType,\r
+ Type\r
+ >::type,\r
+ typename select_most_precise\r
+ <\r
+ DefaultIntegralCalculationType,\r
+ Type\r
+ >::type\r
+ >::type,\r
+ CalculationType\r
+ >::type type;\r
+};\r
+\r
+} // namespace detail\r
+\r
+\r
+namespace calculation_type\r
+{\r
+\r
+namespace geometric\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ typename CalculationType,\r
+ typename DefaultFloatingPointCalculationType = double,\r
+ typename DefaultIntegralCalculationType = detail::default_integral::type\r
+>\r
+struct unary\r
+{\r
+ typedef typename detail::calculation_type\r
+ <\r
+ typename geometry::coordinate_type<Geometry>::type,\r
+ CalculationType,\r
+ DefaultFloatingPointCalculationType,\r
+ DefaultIntegralCalculationType\r
+ >::type type;\r
+};\r
+\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename CalculationType,\r
+ typename DefaultFloatingPointCalculationType = double,\r
+ typename DefaultIntegralCalculationType = detail::default_integral::type\r
+>\r
+struct binary\r
+{\r
+ typedef typename detail::calculation_type\r
+ <\r
+ typename select_coordinate_type<Geometry1, Geometry2>::type,\r
+ CalculationType,\r
+ DefaultFloatingPointCalculationType,\r
+ DefaultIntegralCalculationType\r
+ >::type type;\r
+};\r
+\r
+\r
+/*!\r
+\brief calculation type (ternary, for three geometry types)\r
+ */\r
+template\r
+<\r
+ typename Geometry1,\r
+ typename Geometry2,\r
+ typename Geometry3,\r
+ typename CalculationType,\r
+ typename DefaultFloatingPointCalculationType = double,\r
+ typename DefaultIntegralCalculationType = detail::default_integral::type\r
+>\r
+struct ternary\r
+{\r
+ typedef typename detail::calculation_type\r
+ <\r
+ typename select_most_precise\r
+ <\r
+ typename coordinate_type<Geometry1>::type,\r
+ typename select_coordinate_type\r
+ <\r
+ Geometry2,\r
+ Geometry3\r
+ >::type\r
+ >::type,\r
+ CalculationType,\r
+ DefaultFloatingPointCalculationType,\r
+ DefaultIntegralCalculationType\r
+ >::type type;\r
+};\r
+\r
+}} // namespace calculation_type::geometric\r
+\r
+} // namespace util\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP\r
+#define BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+template<closure_selector Closure>\r
+struct closure_as_bool\r
+{};\r
+\r
+\r
+template<>\r
+struct closure_as_bool<closed>\r
+{\r
+ static const bool value = true;\r
+};\r
+\r
+\r
+template<>\r
+struct closure_as_bool<open>\r
+{\r
+ static const bool value = false;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP\r
+#define BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP\r
+\r
+#include <boost/mpl/fold.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/bind.hpp>\r
+#include <boost/mpl/set.hpp>\r
+#include <boost/mpl/insert.hpp>\r
+#include <boost/mpl/placeholders.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace util\r
+{\r
+\r
+\r
+/*!\r
+ \brief Meta-function to generate all the combination of pairs of types\r
+ from a given sequence Sequence except those that does not satisfy the\r
+ predicate Pred\r
+ \ingroup utility\r
+ \par Example\r
+ \code\r
+ typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<1> > types;\r
+ typedef combine_if<types, types, always<true_> >::type combinations;\r
+ typedef boost::mpl::vector<\r
+ pair<boost::mpl::int_<1>, boost::mpl::int_<1> >,\r
+ pair<boost::mpl::int_<1>, boost::mpl::int_<0> >,\r
+ pair<boost::mpl::int_<0>, boost::mpl::int_<1> >,\r
+ pair<boost::mpl::int_<0>, boost::mpl::int_<0> > \r
+ > result_types;\r
+ \r
+ BOOST_MPL_ASSERT(( boost::mpl::equal<combinations, result_types> ));\r
+ \endcode\r
+*/\r
+template <typename Sequence1, typename Sequence2, typename Pred>\r
+struct combine_if\r
+{\r
+ struct combine\r
+ {\r
+ template <typename Result, typename T>\r
+ struct apply\r
+ {\r
+ typedef typename boost::mpl::fold<Sequence2, Result,\r
+ boost::mpl::if_\r
+ <\r
+ boost::mpl::bind\r
+ <\r
+ typename boost::mpl::lambda<Pred>::type,\r
+ T,\r
+ boost::mpl::_2\r
+ >,\r
+ boost::mpl::insert\r
+ <\r
+ boost::mpl::_1, boost::mpl::pair<T, boost::mpl::_2>\r
+ >,\r
+ boost::mpl::_1\r
+ >\r
+ >::type type;\r
+ };\r
+ };\r
+\r
+ typedef typename boost::mpl::fold\r
+ <\r
+ Sequence1, boost::mpl::set0<>, combine\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace util\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP\r
+#define BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP\r
+\r
+\r
+#include <boost/mpl/equal_to.hpp>\r
+#include <boost/mpl/fold.hpp>\r
+#include <boost/mpl/front.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/insert.hpp>\r
+#include <boost/mpl/int.hpp>\r
+#include <boost/mpl/set.hpp>\r
+#include <boost/mpl/size.hpp>\r
+#include <boost/mpl/vector.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+namespace detail\r
+{\r
+\r
+template <typename Variant>\r
+struct unique_types:\r
+ boost::mpl::fold<\r
+ typename boost::mpl::reverse_fold<\r
+ typename Variant::types,\r
+ boost::mpl::set<>,\r
+ boost::mpl::insert<\r
+ boost::mpl::placeholders::_1,\r
+ boost::mpl::placeholders::_2\r
+ >\r
+ >::type,\r
+ boost::mpl::vector<>,\r
+ boost::mpl::push_back\r
+ <\r
+ boost::mpl::placeholders::_1, boost::mpl::placeholders::_2\r
+ >\r
+ >\r
+{};\r
+\r
+template <typename Types>\r
+struct variant_or_single:\r
+ boost::mpl::if_<\r
+ boost::mpl::equal_to<\r
+ boost::mpl::size<Types>,\r
+ boost::mpl::int_<1>\r
+ >,\r
+ typename boost::mpl::front<Types>::type,\r
+ typename make_variant_over<Types>::type\r
+ >\r
+{};\r
+\r
+} // namespace detail\r
+\r
+\r
+/*!\r
+ \brief Meta-function that takes a boost::variant type and tries to minimize\r
+ it by doing the following:\r
+ - if there's any duplicate types, remove them\r
+ - if the result is a variant of one type, turn it into just that type\r
+ \ingroup utility\r
+ \par Example\r
+ \code\r
+ typedef variant<int, float, int, long> variant_type;\r
+ typedef compress_variant<variant_type>::type compressed;\r
+ typedef boost::mpl::vector<int, float, long> result_types;\r
+ BOOST_MPL_ASSERT(( boost::mpl::equal<compressed::types, result_types> ));\r
+\r
+ typedef variant<int, int, int> one_type_variant_type;\r
+ typedef compress_variant<one_type_variant_type>::type single_type;\r
+ BOOST_MPL_ASSERT(( boost::equals<single_type, int> ));\r
+ \endcode\r
+*/\r
+\r
+template <typename Variant>\r
+struct compress_variant:\r
+ detail::variant_or_single<\r
+ typename detail::unique_types<Variant>::type\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_CONDITION_HPP\r
+#define BOOST_GEOMETRY_UTIL_CONDITION_HPP\r
+\r
+\r
+#include <boost/config.hpp>\r
+\r
+\r
+// The macro defined in this file allows to suppress the MSVC\r
+// compiler warning C4127: conditional expression is constant\r
+\r
+#ifdef BOOST_MSVC\r
+\r
+// NOTE: The code commented out below contains an alternative implementation\r
+// of a macro using a free function. It was left here in case if in the future\r
+// version of MSVC for the code currently used in the macro implementation\r
+// the warning was generated.\r
+\r
+//#ifndef DOXYGEN_NO_DETAIL\r
+//namespace boost { namespace geometry { namespace detail {\r
+//BOOST_FORCEINLINE bool condition(bool const b) { return b; }\r
+//}}} // boost::geometry::detail\r
+//#endif // DOXYGEN_NO_DETAIL\r
+//#define BOOST_GEOMETRY_CONDITION(CONDITION) boost::geometry::detail::condition(CONDITION)\r
+\r
+#define BOOST_GEOMETRY_CONDITION(CONDITION) ((void)0, (CONDITION))\r
+\r
+#else\r
+\r
+#define BOOST_GEOMETRY_CONDITION(CONDITION) (CONDITION)\r
+\r
+#endif\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_CONDITION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP\r
+#define BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP\r
+\r
+#include <cstdlib>\r
+#include <string>\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+/*!\r
+\brief cast coordinates from a string to a coordinate type\r
+\detail By default it uses lexical_cast. However, lexical_cast seems not to support\r
+ ttmath / partial specializations. Therefore this small utility is added.\r
+ See also "define_pi" where the same issue is solved\r
+*/\r
+template <typename CoordinateType>\r
+struct coordinate_cast\r
+{\r
+ static inline CoordinateType apply(std::string const& source)\r
+ {\r
+#if defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)\r
+ return atof(source.c_str());\r
+#else\r
+ return boost::lexical_cast<CoordinateType>(source);\r
+#endif\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP\r
+#define BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP\r
+\r
+#include <boost/concept/requires.hpp>\r
+#include <boost/geometry/geometries/concepts/point_concept.hpp>\r
+#include <boost/geometry/util/add_const_if_c.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Point, int Dimension, int DimensionCount, bool IsConst>\r
+struct coordinates_scanner\r
+{\r
+ template <typename Op>\r
+ static inline Op apply(typename add_const_if_c\r
+ <\r
+ IsConst,\r
+ Point\r
+ >::type& point, Op operation)\r
+ {\r
+ operation.template apply<Point, Dimension>(point);\r
+ return coordinates_scanner\r
+ <\r
+ Point,\r
+ Dimension+1,\r
+ DimensionCount,\r
+ IsConst\r
+ >::apply(point, operation);\r
+ }\r
+};\r
+\r
+template <typename Point, int DimensionCount, bool IsConst>\r
+struct coordinates_scanner<Point, DimensionCount, DimensionCount, IsConst>\r
+{\r
+ template <typename Op>\r
+ static inline Op apply(typename add_const_if_c\r
+ <\r
+ IsConst,\r
+ Point\r
+ >::type& , Op operation)\r
+ {\r
+ return operation;\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+template <typename Point, typename Op>\r
+inline void for_each_coordinate(Point& point, Op operation)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );\r
+\r
+ typedef typename detail::coordinates_scanner\r
+ <\r
+ Point, 0, dimension<Point>::type::value, false\r
+ > scanner;\r
+\r
+ scanner::apply(point, operation);\r
+}\r
+\r
+template <typename Point, typename Op>\r
+inline Op for_each_coordinate(Point const& point, Op operation)\r
+{\r
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point>) );\r
+\r
+ typedef typename detail::coordinates_scanner\r
+ <\r
+ Point, 0, dimension<Point>::type::value, true\r
+ > scanner;\r
+\r
+ return scanner::apply(point, operation);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP\r
+#define BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP\r
+\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/util/has_nan_coordinate.hpp>\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ \r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+struct isinf\r
+{\r
+ template <typename T>\r
+ static inline bool apply(T const& t)\r
+ {\r
+ return boost::math::isinf(t);\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+template <typename Point>\r
+bool has_infinite_coordinate(Point const& point)\r
+{\r
+ return detail::has_coordinate_with_property\r
+ <\r
+ Point,\r
+ detail::isinf,\r
+ boost::is_floating_point\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >::value\r
+ >::apply(point);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP\r
+#define BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ \r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+struct isnan\r
+{\r
+ template <typename T>\r
+ static inline bool apply(T const& t)\r
+ {\r
+ return boost::math::isnan(t);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Point,\r
+ typename Predicate,\r
+ bool Enable,\r
+ std::size_t I = 0,\r
+ std::size_t N = geometry::dimension<Point>::value\r
+>\r
+struct has_coordinate_with_property\r
+{\r
+ static bool apply(Point const& point)\r
+ {\r
+ return Predicate::apply(geometry::get<I>(point))\r
+ || has_coordinate_with_property\r
+ <\r
+ Point, Predicate, Enable, I+1, N\r
+ >::apply(point);\r
+ }\r
+};\r
+\r
+template <typename Point, typename Predicate, std::size_t I, std::size_t N>\r
+struct has_coordinate_with_property<Point, Predicate, false, I, N>\r
+{\r
+ static inline bool apply(Point const&)\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+template <typename Point, typename Predicate, std::size_t N>\r
+struct has_coordinate_with_property<Point, Predicate, true, N, N>\r
+{\r
+ static bool apply(Point const& )\r
+ {\r
+ return false;\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+template <typename Point>\r
+bool has_nan_coordinate(Point const& point)\r
+{\r
+ return detail::has_coordinate_with_property\r
+ <\r
+ Point,\r
+ detail::isnan,\r
+ boost::is_floating_point\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >::value\r
+ >::apply(point);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP\r
--- /dev/null
+// Boost.Geometry\r
+\r
+// Copyright (c) 2015 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP\r
+#define BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP\r
+\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/util/has_nan_coordinate.hpp>\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+ \r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+struct is_not_finite\r
+{\r
+ template <typename T>\r
+ static inline bool apply(T const& t)\r
+ {\r
+ return ! boost::math::isfinite(t);\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+template <typename Point>\r
+bool has_non_finite_coordinate(Point const& point)\r
+{\r
+ return detail::has_coordinate_with_property\r
+ <\r
+ Point,\r
+ detail::is_not_finite,\r
+ boost::is_floating_point\r
+ <\r
+ typename coordinate_type<Point>::type\r
+ >::value\r
+ >::apply(point);\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014, 2015.\r
+// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP\r
+#define BOOST_GEOMETRY_UTIL_MATH_HPP\r
+\r
+#include <cmath>\r
+#include <limits>\r
+\r
+#include <boost/core/ignore_unused.hpp>\r
+\r
+#include <boost/math/constants/constants.hpp>\r
+#include <boost/math/special_functions/fpclassify.hpp>\r
+//#include <boost/math/special_functions/round.hpp>\r
+#include <boost/numeric/conversion/cast.hpp>\r
+#include <boost/type_traits/is_fundamental.hpp>\r
+#include <boost/type_traits/is_integral.hpp>\r
+\r
+#include <boost/geometry/core/cs.hpp>\r
+\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace math\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename T>\r
+inline T const& greatest(T const& v1, T const& v2)\r
+{\r
+ return (std::max)(v1, v2);\r
+}\r
+\r
+template <typename T>\r
+inline T const& greatest(T const& v1, T const& v2, T const& v3)\r
+{\r
+ return (std::max)(greatest(v1, v2), v3);\r
+}\r
+\r
+template <typename T>\r
+inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)\r
+{\r
+ return (std::max)(greatest(v1, v2, v3), v4);\r
+}\r
+\r
+template <typename T>\r
+inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)\r
+{\r
+ return (std::max)(greatest(v1, v2, v3, v4), v5);\r
+}\r
+\r
+\r
+template <typename T,\r
+ bool IsFloatingPoint = boost::is_floating_point<T>::value>\r
+struct abs\r
+{\r
+ static inline T apply(T const& value)\r
+ {\r
+ T const zero = T();\r
+ return value < zero ? -value : value;\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct abs<T, true>\r
+{\r
+ static inline T apply(T const& value)\r
+ {\r
+ using ::fabs;\r
+ using std::fabs; // for long double\r
+\r
+ return fabs(value);\r
+ }\r
+};\r
+\r
+\r
+struct equals_default_policy\r
+{\r
+ template <typename T>\r
+ static inline T apply(T const& a, T const& b)\r
+ {\r
+ // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17\r
+ return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));\r
+ }\r
+};\r
+\r
+template <typename T,\r
+ bool IsFloatingPoint = boost::is_floating_point<T>::value>\r
+struct equals_factor_policy\r
+{\r
+ equals_factor_policy()\r
+ : factor(1) {}\r
+ explicit equals_factor_policy(T const& v)\r
+ : factor(greatest(abs<T>::apply(v), T(1)))\r
+ {}\r
+ equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)\r
+ : factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),\r
+ abs<T>::apply(v2), abs<T>::apply(v3),\r
+ T(1)))\r
+ {}\r
+\r
+ T const& apply(T const&, T const&) const\r
+ {\r
+ return factor;\r
+ }\r
+\r
+ T factor;\r
+};\r
+\r
+template <typename T>\r
+struct equals_factor_policy<T, false>\r
+{\r
+ equals_factor_policy() {}\r
+ explicit equals_factor_policy(T const&) {}\r
+ equals_factor_policy(T const& , T const& , T const& , T const& ) {}\r
+\r
+ static inline T apply(T const&, T const&)\r
+ {\r
+ return T(1);\r
+ }\r
+};\r
+\r
+template <typename Type,\r
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>\r
+struct equals\r
+{\r
+ template <typename Policy>\r
+ static inline bool apply(Type const& a, Type const& b, Policy const&)\r
+ {\r
+ return a == b;\r
+ }\r
+};\r
+\r
+template <typename Type>\r
+struct equals<Type, true>\r
+{\r
+ template <typename Policy>\r
+ static inline bool apply(Type const& a, Type const& b, Policy const& policy)\r
+ {\r
+ boost::ignore_unused(policy);\r
+\r
+ if (a == b)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if (boost::math::isfinite(a) && boost::math::isfinite(b))\r
+ {\r
+ // If a is INF and b is e.g. 0, the expression below returns true\r
+ // but the values are obviously not equal, hence the condition\r
+ return abs<Type>::apply(a - b)\r
+ <= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);\r
+ }\r
+ else\r
+ {\r
+ return a == b;\r
+ }\r
+ }\r
+};\r
+\r
+template <typename T1, typename T2, typename Policy>\r
+inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)\r
+{\r
+ return detail::equals\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(a, b, policy);\r
+}\r
+\r
+template <typename Type,\r
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>\r
+struct smaller\r
+{\r
+ static inline bool apply(Type const& a, Type const& b)\r
+ {\r
+ return a < b;\r
+ }\r
+};\r
+\r
+template <typename Type>\r
+struct smaller<Type, true>\r
+{\r
+ static inline bool apply(Type const& a, Type const& b)\r
+ {\r
+ if (!(a < b)) // a >= b\r
+ {\r
+ return false;\r
+ }\r
+ \r
+ return ! equals<Type, true>::apply(b, a, equals_default_policy());\r
+ }\r
+};\r
+\r
+template <typename Type,\r
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>\r
+struct smaller_or_equals\r
+{\r
+ static inline bool apply(Type const& a, Type const& b)\r
+ {\r
+ return a <= b;\r
+ }\r
+};\r
+\r
+template <typename Type>\r
+struct smaller_or_equals<Type, true>\r
+{\r
+ static inline bool apply(Type const& a, Type const& b)\r
+ {\r
+ if (a <= b)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ return equals<Type, true>::apply(a, b, equals_default_policy());\r
+ }\r
+};\r
+\r
+\r
+template <typename Type,\r
+ bool IsFloatingPoint = boost::is_floating_point<Type>::value>\r
+struct equals_with_epsilon\r
+ : public equals<Type, IsFloatingPoint>\r
+{};\r
+\r
+template\r
+<\r
+ typename T,\r
+ bool IsFundemantal = boost::is_fundamental<T>::value /* false */\r
+>\r
+struct square_root\r
+{\r
+ typedef T return_type;\r
+\r
+ static inline T apply(T const& value)\r
+ {\r
+ // for non-fundamental number types assume that sqrt is\r
+ // defined either:\r
+ // 1) at T's scope, or\r
+ // 2) at global scope, or\r
+ // 3) in namespace std\r
+ using ::sqrt;\r
+ using std::sqrt;\r
+\r
+ return sqrt(value);\r
+ }\r
+};\r
+\r
+template <typename FundamentalFP>\r
+struct square_root_for_fundamental_fp\r
+{\r
+ typedef FundamentalFP return_type;\r
+\r
+ static inline FundamentalFP apply(FundamentalFP const& value)\r
+ {\r
+#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS\r
+ // This is a workaround for some 32-bit platforms.\r
+ // For some of those platforms it has been reported that\r
+ // std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.\r
+ // For those platforms we need to define the macro\r
+ // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument\r
+ // to std::sqrt is checked appropriately before passed to std::sqrt\r
+ if (boost::math::isfinite(value))\r
+ {\r
+ return std::sqrt(value);\r
+ }\r
+ else if (boost::math::isinf(value) && value < 0)\r
+ {\r
+ return -std::numeric_limits<FundamentalFP>::quiet_NaN();\r
+ }\r
+ return value;\r
+#else\r
+ // for fundamental floating point numbers use std::sqrt\r
+ return std::sqrt(value);\r
+#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS\r
+ }\r
+};\r
+\r
+template <>\r
+struct square_root<float, true>\r
+ : square_root_for_fundamental_fp<float>\r
+{\r
+};\r
+\r
+template <>\r
+struct square_root<double, true>\r
+ : square_root_for_fundamental_fp<double>\r
+{\r
+};\r
+\r
+template <>\r
+struct square_root<long double, true>\r
+ : square_root_for_fundamental_fp<long double>\r
+{\r
+};\r
+\r
+template <typename T>\r
+struct square_root<T, true>\r
+{\r
+ typedef double return_type;\r
+\r
+ static inline double apply(T const& value)\r
+ {\r
+ // for all other fundamental number types use also std::sqrt\r
+ //\r
+ // Note: in C++98 the only other possibility is double;\r
+ // in C++11 there are also overloads for integral types;\r
+ // this specialization works for those as well.\r
+ return square_root_for_fundamental_fp\r
+ <\r
+ double\r
+ >::apply(boost::numeric_cast<double>(value));\r
+ }\r
+};\r
+\r
+\r
+\r
+template\r
+<\r
+ typename T,\r
+ bool IsFundemantal = boost::is_fundamental<T>::value /* false */\r
+>\r
+struct modulo\r
+{\r
+ typedef T return_type;\r
+\r
+ static inline T apply(T const& value1, T const& value2)\r
+ {\r
+ // for non-fundamental number types assume that a free\r
+ // function mod() is defined either:\r
+ // 1) at T's scope, or\r
+ // 2) at global scope\r
+ return mod(value1, value2);\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename Fundamental,\r
+ bool IsIntegral = boost::is_integral<Fundamental>::value\r
+>\r
+struct modulo_for_fundamental\r
+{\r
+ typedef Fundamental return_type;\r
+\r
+ static inline Fundamental apply(Fundamental const& value1,\r
+ Fundamental const& value2)\r
+ {\r
+ return value1 % value2;\r
+ }\r
+};\r
+\r
+// specialization for floating-point numbers\r
+template <typename Fundamental>\r
+struct modulo_for_fundamental<Fundamental, false>\r
+{\r
+ typedef Fundamental return_type;\r
+\r
+ static inline Fundamental apply(Fundamental const& value1,\r
+ Fundamental const& value2)\r
+ {\r
+ return std::fmod(value1, value2);\r
+ }\r
+};\r
+\r
+// specialization for fundamental number type\r
+template <typename Fundamental>\r
+struct modulo<Fundamental, true>\r
+ : modulo_for_fundamental<Fundamental>\r
+{};\r
+\r
+\r
+\r
+/*!\r
+\brief Short constructs to enable partial specialization for PI, 2*PI\r
+ and PI/2, currently not possible in Math.\r
+*/\r
+template <typename T>\r
+struct define_pi\r
+{\r
+ static inline T apply()\r
+ {\r
+ // Default calls Boost.Math\r
+ return boost::math::constants::pi<T>();\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct define_two_pi\r
+{\r
+ static inline T apply()\r
+ {\r
+ // Default calls Boost.Math\r
+ return boost::math::constants::two_pi<T>();\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct define_half_pi\r
+{\r
+ static inline T apply()\r
+ {\r
+ // Default calls Boost.Math\r
+ return boost::math::constants::half_pi<T>();\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct relaxed_epsilon\r
+{\r
+ static inline T apply(const T& factor)\r
+ {\r
+ return factor * std::numeric_limits<T>::epsilon();\r
+ }\r
+};\r
+\r
+// This must be consistent with math::equals.\r
+// By default math::equals() scales the error by epsilon using the greater of\r
+// compared values but here is only one value, though it should work the same way.\r
+// (a-a) <= max(a, a) * EPS -> 0 <= a*EPS\r
+// (a+da-a) <= max(a+da, a) * EPS -> da <= (a+da)*EPS\r
+template <typename T, bool IsFloat = boost::is_floating_point<T>::value>\r
+struct scaled_epsilon\r
+{\r
+ static inline T apply(T const& val)\r
+ {\r
+ return (std::max)(abs<T>::apply(val), T(1))\r
+ * std::numeric_limits<T>::epsilon();\r
+ }\r
+};\r
+\r
+template <typename T>\r
+struct scaled_epsilon<T, false>\r
+{\r
+ static inline T apply(T const&)\r
+ {\r
+ return T(0);\r
+ }\r
+};\r
+\r
+// ItoF ItoI FtoF\r
+template <typename Result, typename Source,\r
+ bool ResultIsInteger = std::numeric_limits<Result>::is_integer,\r
+ bool SourceIsInteger = std::numeric_limits<Source>::is_integer>\r
+struct rounding_cast\r
+{\r
+ static inline Result apply(Source const& v)\r
+ {\r
+ return boost::numeric_cast<Result>(v);\r
+ }\r
+};\r
+\r
+// TtoT\r
+template <typename Source, bool ResultIsInteger, bool SourceIsInteger>\r
+struct rounding_cast<Source, Source, ResultIsInteger, SourceIsInteger>\r
+{\r
+ static inline Source apply(Source const& v)\r
+ {\r
+ return v;\r
+ }\r
+};\r
+\r
+// FtoI\r
+template <typename Result, typename Source>\r
+struct rounding_cast<Result, Source, true, false>\r
+{\r
+ static inline Result apply(Source const& v)\r
+ {\r
+ return boost::numeric_cast<Result>(v < Source(0) ?\r
+ v - Source(0.5) :\r
+ v + Source(0.5));\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+\r
+template <typename T>\r
+inline T pi() { return detail::define_pi<T>::apply(); }\r
+\r
+template <typename T>\r
+inline T two_pi() { return detail::define_two_pi<T>::apply(); }\r
+\r
+template <typename T>\r
+inline T half_pi() { return detail::define_half_pi<T>::apply(); }\r
+\r
+template <typename T>\r
+inline T relaxed_epsilon(T const& factor)\r
+{\r
+ return detail::relaxed_epsilon<T>::apply(factor);\r
+}\r
+\r
+template <typename T>\r
+inline T scaled_epsilon(T const& value)\r
+{\r
+ return detail::scaled_epsilon<T>::apply(value);\r
+}\r
+\r
+\r
+// Maybe replace this by boost equals or boost ublas numeric equals or so\r
+\r
+/*!\r
+ \brief returns true if both arguments are equal.\r
+ \ingroup utility\r
+ \param a first argument\r
+ \param b second argument\r
+ \return true if a == b\r
+ \note If both a and b are of an integral type, comparison is done by ==.\r
+ If one of the types is floating point, comparison is done by abs and\r
+ comparing with epsilon. If one of the types is non-fundamental, it might\r
+ be a high-precision number and comparison is done using the == operator\r
+ of that class.\r
+*/\r
+\r
+template <typename T1, typename T2>\r
+inline bool equals(T1 const& a, T2 const& b)\r
+{\r
+ return detail::equals\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(a, b, detail::equals_default_policy());\r
+}\r
+\r
+template <typename T1, typename T2>\r
+inline bool equals_with_epsilon(T1 const& a, T2 const& b)\r
+{\r
+ return detail::equals_with_epsilon\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(a, b, detail::equals_default_policy());\r
+}\r
+\r
+template <typename T1, typename T2>\r
+inline bool smaller(T1 const& a, T2 const& b)\r
+{\r
+ return detail::smaller\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(a, b);\r
+}\r
+\r
+template <typename T1, typename T2>\r
+inline bool larger(T1 const& a, T2 const& b)\r
+{\r
+ return detail::smaller\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(b, a);\r
+}\r
+\r
+template <typename T1, typename T2>\r
+inline bool smaller_or_equals(T1 const& a, T2 const& b)\r
+{\r
+ return detail::smaller_or_equals\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(a, b);\r
+}\r
+\r
+template <typename T1, typename T2>\r
+inline bool larger_or_equals(T1 const& a, T2 const& b)\r
+{\r
+ return detail::smaller_or_equals\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ >::apply(b, a);\r
+}\r
+\r
+\r
+template <typename T>\r
+inline T d2r()\r
+{\r
+ static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);\r
+ return conversion_coefficient;\r
+}\r
+\r
+template <typename T>\r
+inline T r2d()\r
+{\r
+ static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();\r
+ return conversion_coefficient;\r
+}\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail {\r
+\r
+template <typename DegreeOrRadian>\r
+struct as_radian\r
+{\r
+ template <typename T>\r
+ static inline T apply(T const& value)\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+template <>\r
+struct as_radian<degree>\r
+{\r
+ template <typename T>\r
+ static inline T apply(T const& value)\r
+ {\r
+ return value * d2r<T>();\r
+ }\r
+};\r
+\r
+template <typename DegreeOrRadian>\r
+struct from_radian\r
+{\r
+ template <typename T>\r
+ static inline T apply(T const& value)\r
+ {\r
+ return value;\r
+ }\r
+};\r
+\r
+template <>\r
+struct from_radian<degree>\r
+{\r
+ template <typename T>\r
+ static inline T apply(T const& value)\r
+ {\r
+ return value * r2d<T>();\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+#endif\r
+\r
+template <typename DegreeOrRadian, typename T>\r
+inline T as_radian(T const& value)\r
+{\r
+ return detail::as_radian<DegreeOrRadian>::apply(value);\r
+}\r
+\r
+template <typename DegreeOrRadian, typename T>\r
+inline T from_radian(T const& value)\r
+{\r
+ return detail::from_radian<DegreeOrRadian>::apply(value);\r
+}\r
+\r
+\r
+/*!\r
+ \brief Calculates the haversine of an angle\r
+ \ingroup utility\r
+ \note See http://en.wikipedia.org/wiki/Haversine_formula\r
+ haversin(alpha) = sin2(alpha/2)\r
+*/\r
+template <typename T>\r
+inline T hav(T const& theta)\r
+{\r
+ T const half = T(0.5);\r
+ T const sn = sin(half * theta);\r
+ return sn * sn;\r
+}\r
+\r
+/*!\r
+\brief Short utility to return the square\r
+\ingroup utility\r
+\param value Value to calculate the square from\r
+\return The squared value\r
+*/\r
+template <typename T>\r
+inline T sqr(T const& value)\r
+{\r
+ return value * value;\r
+}\r
+\r
+/*!\r
+\brief Short utility to return the square root\r
+\ingroup utility\r
+\param value Value to calculate the square root from\r
+\return The square root value\r
+*/\r
+template <typename T>\r
+inline typename detail::square_root<T>::return_type\r
+sqrt(T const& value)\r
+{\r
+ return detail::square_root\r
+ <\r
+ T, boost::is_fundamental<T>::value\r
+ >::apply(value);\r
+}\r
+\r
+/*!\r
+\brief Short utility to return the modulo of two values\r
+\ingroup utility\r
+\param value1 First value\r
+\param value2 Second value\r
+\return The result of the modulo operation on the (ordered) pair\r
+(value1, value2)\r
+*/\r
+template <typename T>\r
+inline typename detail::modulo<T>::return_type\r
+mod(T const& value1, T const& value2)\r
+{\r
+ return detail::modulo\r
+ <\r
+ T, boost::is_fundamental<T>::value\r
+ >::apply(value1, value2);\r
+}\r
+\r
+/*!\r
+\brief Short utility to workaround gcc/clang problem that abs is converting to integer\r
+ and that older versions of MSVC does not support abs of long long...\r
+\ingroup utility\r
+*/\r
+template<typename T>\r
+inline T abs(T const& value)\r
+{\r
+ return detail::abs<T>::apply(value);\r
+}\r
+\r
+/*!\r
+\brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)\r
+\ingroup utility\r
+*/\r
+template <typename T>\r
+inline int sign(T const& value)\r
+{\r
+ T const zero = T();\r
+ return value > zero ? 1 : value < zero ? -1 : 0;\r
+}\r
+\r
+/*!\r
+\brief Short utility to cast a value possibly rounding it to the nearest\r
+ integral value.\r
+\ingroup utility\r
+\note If the source T is NOT an integral type and Result is an integral type\r
+ the value is rounded towards the closest integral value. Otherwise it's\r
+ casted without rounding.\r
+*/\r
+template <typename Result, typename T>\r
+inline Result rounding_cast(T const& v)\r
+{\r
+ return detail::rounding_cast<Result, T>::apply(v);\r
+}\r
+\r
+} // namespace math\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_MATH_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP\r
+#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace math \r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename Units, typename CoordinateType>\r
+class normalize_spheroidal_box_coordinates\r
+{\r
+private:\r
+ typedef normalize_spheroidal_coordinates<Units, CoordinateType> normalize;\r
+ typedef constants_on_spheroid<CoordinateType, Units> constants;\r
+\r
+ static inline bool is_band(CoordinateType const& longitude1,\r
+ CoordinateType const& longitude2)\r
+ {\r
+ return ! math::smaller(math::abs(longitude1 - longitude2),\r
+ constants::period());\r
+ }\r
+\r
+public:\r
+ static inline void apply(CoordinateType& longitude1,\r
+ CoordinateType& latitude1,\r
+ CoordinateType& longitude2,\r
+ CoordinateType& latitude2,\r
+ bool band)\r
+ {\r
+ normalize::apply(longitude1, latitude1, false);\r
+ normalize::apply(longitude2, latitude2, false);\r
+\r
+ if (math::equals(latitude1, constants::min_latitude())\r
+ && math::equals(latitude2, constants::min_latitude()))\r
+ {\r
+ // box degenerates to the south pole\r
+ longitude1 = longitude2 = CoordinateType(0);\r
+ }\r
+ else if (math::equals(latitude1, constants::max_latitude())\r
+ && math::equals(latitude2, constants::max_latitude()))\r
+ {\r
+ // box degenerates to the north pole\r
+ longitude1 = longitude2 = CoordinateType(0);\r
+ }\r
+ else if (band)\r
+ {\r
+ // the box is a band between two small circles (parallel\r
+ // to the equator) on the spheroid\r
+ longitude1 = constants::min_longitude();\r
+ longitude2 = constants::max_longitude();\r
+ }\r
+ else if (longitude1 > longitude2)\r
+ {\r
+ // the box crosses the antimeridian, so we need to adjust\r
+ // the longitudes\r
+ longitude2 += constants::period();\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2));\r
+ BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude()));\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude()));\r
+#endif\r
+\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));\r
+ BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));\r
+ BOOST_GEOMETRY_ASSERT\r
+ (! math::larger(longitude2 - longitude1, constants::period()));\r
+ }\r
+\r
+ static inline void apply(CoordinateType& longitude1,\r
+ CoordinateType& latitude1,\r
+ CoordinateType& longitude2,\r
+ CoordinateType& latitude2)\r
+ {\r
+ bool const band = is_band(longitude1, longitude2);\r
+\r
+ apply(longitude1, latitude1, longitude2, latitude2, band);\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Short utility to normalize the coordinates of a box on a spheroid\r
+\tparam Units The units of the coordindate system in the spheroid\r
+\tparam CoordinateType The type of the coordinates\r
+\param longitude1 Minimum longitude of the box\r
+\param latitude1 Minimum latitude of the box\r
+\param longitude2 Maximum longitude of the box\r
+\param latitude2 Maximum latitude of the box\r
+\ingroup utility\r
+*/\r
+template <typename Units, typename CoordinateType>\r
+inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,\r
+ CoordinateType& latitude1,\r
+ CoordinateType& longitude2,\r
+ CoordinateType& latitude2)\r
+{\r
+ detail::normalize_spheroidal_box_coordinates\r
+ <\r
+ Units, CoordinateType\r
+ >::apply(longitude1, latitude1, longitude2, latitude2);\r
+}\r
+\r
+/*!\r
+\brief Short utility to normalize the coordinates of a box on a spheroid\r
+\tparam Units The units of the coordindate system in the spheroid\r
+\tparam CoordinateType The type of the coordinates\r
+\param longitude1 Minimum longitude of the box\r
+\param latitude1 Minimum latitude of the box\r
+\param longitude2 Maximum longitude of the box\r
+\param latitude2 Maximum latitude of the box\r
+\param band Indicates whether the box should be treated as a band or\r
+ not and avoid the computation done in the other version of the function\r
+\ingroup utility\r
+*/\r
+template <typename Units, typename CoordinateType>\r
+inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,\r
+ CoordinateType& latitude1,\r
+ CoordinateType& longitude2,\r
+ CoordinateType& latitude2,\r
+ bool band)\r
+{\r
+ detail::normalize_spheroidal_box_coordinates\r
+ <\r
+ Units, CoordinateType\r
+ >::apply(longitude1, latitude1, longitude2, latitude2, band);\r
+}\r
+\r
+\r
+} // namespace math\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015-2016, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP\r
+#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/cs.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace math \r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+\r
+template <typename CoordinateType, typename Units>\r
+struct constants_on_spheroid\r
+{\r
+ static inline CoordinateType period()\r
+ {\r
+ return math::two_pi<CoordinateType>();\r
+ }\r
+\r
+ static inline CoordinateType half_period()\r
+ {\r
+ return math::pi<CoordinateType>();\r
+ }\r
+\r
+ static inline CoordinateType min_longitude()\r
+ {\r
+ static CoordinateType const minus_pi = -math::pi<CoordinateType>();\r
+ return minus_pi;\r
+ }\r
+\r
+ static inline CoordinateType max_longitude()\r
+ {\r
+ return math::pi<CoordinateType>();\r
+ }\r
+\r
+ static inline CoordinateType min_latitude()\r
+ {\r
+ static CoordinateType const minus_half_pi\r
+ = -math::half_pi<CoordinateType>();\r
+ return minus_half_pi;\r
+ }\r
+\r
+ static inline CoordinateType max_latitude()\r
+ {\r
+ return math::half_pi<CoordinateType>();\r
+ }\r
+};\r
+\r
+template <typename CoordinateType>\r
+struct constants_on_spheroid<CoordinateType, degree>\r
+{\r
+ static inline CoordinateType period()\r
+ {\r
+ return CoordinateType(360.0);\r
+ }\r
+\r
+ static inline CoordinateType half_period()\r
+ {\r
+ return CoordinateType(180.0);\r
+ }\r
+\r
+ static inline CoordinateType min_longitude()\r
+ {\r
+ return CoordinateType(-180.0);\r
+ }\r
+\r
+ static inline CoordinateType max_longitude()\r
+ {\r
+ return CoordinateType(180.0);\r
+ }\r
+\r
+ static inline CoordinateType min_latitude()\r
+ {\r
+ return CoordinateType(-90.0);\r
+ }\r
+\r
+ static inline CoordinateType max_latitude()\r
+ {\r
+ return CoordinateType(90.0);\r
+ }\r
+};\r
+\r
+\r
+template <typename Units, typename CoordinateType>\r
+class normalize_spheroidal_coordinates\r
+{\r
+ typedef constants_on_spheroid<CoordinateType, Units> constants;\r
+\r
+protected:\r
+ static inline CoordinateType normalize_up(CoordinateType const& value)\r
+ {\r
+ return\r
+ math::mod(value + constants::half_period(), constants::period())\r
+ - constants::half_period(); \r
+ }\r
+\r
+ static inline CoordinateType normalize_down(CoordinateType const& value)\r
+ {\r
+ return\r
+ math::mod(value - constants::half_period(), constants::period())\r
+ + constants::half_period(); \r
+ }\r
+\r
+public:\r
+ static inline void apply(CoordinateType& longitude)\r
+ {\r
+ // normalize longitude\r
+ if (math::equals(math::abs(longitude), constants::half_period()))\r
+ {\r
+ longitude = constants::half_period();\r
+ }\r
+ else if (longitude > constants::half_period())\r
+ {\r
+ longitude = normalize_up(longitude);\r
+ if (math::equals(longitude, -constants::half_period()))\r
+ {\r
+ longitude = constants::half_period();\r
+ }\r
+ }\r
+ else if (longitude < -constants::half_period())\r
+ {\r
+ longitude = normalize_down(longitude);\r
+ }\r
+ }\r
+\r
+ static inline void apply(CoordinateType& longitude,\r
+ CoordinateType& latitude,\r
+ bool normalize_poles = true)\r
+ {\r
+#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE\r
+ // normalize latitude\r
+ if (math::larger(latitude, constants::half_period()))\r
+ {\r
+ latitude = normalize_up(latitude);\r
+ }\r
+ else if (math::smaller(latitude, -constants::half_period()))\r
+ {\r
+ latitude = normalize_down(latitude);\r
+ }\r
+\r
+ // fix latitude range\r
+ if (latitude < constants::min_latitude())\r
+ {\r
+ latitude = -constants::half_period() - latitude;\r
+ longitude -= constants::half_period();\r
+ }\r
+ else if (latitude > constants::max_latitude())\r
+ {\r
+ latitude = constants::half_period() - latitude;\r
+ longitude -= constants::half_period();\r
+ }\r
+#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE\r
+\r
+ // normalize longitude\r
+ apply(longitude);\r
+\r
+ // finally normalize poles\r
+ if (normalize_poles)\r
+ {\r
+ if (math::equals(math::abs(latitude), constants::max_latitude()))\r
+ {\r
+ // for the north and south pole we set the longitude to 0\r
+ // (works for both radians and degrees)\r
+ longitude = CoordinateType(0);\r
+ }\r
+ }\r
+\r
+#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(constants::min_latitude(), latitude));\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude()));\r
+#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE\r
+\r
+ BOOST_GEOMETRY_ASSERT(math::smaller(constants::min_longitude(), longitude));\r
+ BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude()));\r
+ }\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief Short utility to normalize the coordinates on a spheroid\r
+\tparam Units The units of the coordindate system in the spheroid\r
+\tparam CoordinateType The type of the coordinates\r
+\param longitude Longitude\r
+\param latitude Latitude\r
+\ingroup utility\r
+*/\r
+template <typename Units, typename CoordinateType>\r
+inline void normalize_spheroidal_coordinates(CoordinateType& longitude,\r
+ CoordinateType& latitude)\r
+{\r
+ detail::normalize_spheroidal_coordinates\r
+ <\r
+ Units, CoordinateType\r
+ >::apply(longitude, latitude);\r
+}\r
+\r
+\r
+/*!\r
+\brief Short utility to normalize the longitude on a spheroid.\r
+ Note that in general both coordinates should be normalized at once.\r
+ This utility is suitable e.g. for normalization of the difference of longitudes.\r
+\tparam Units The units of the coordindate system in the spheroid\r
+\tparam CoordinateType The type of the coordinates\r
+\param longitude Longitude\r
+\ingroup utility\r
+*/\r
+template <typename Units, typename CoordinateType>\r
+inline void normalize_longitude(CoordinateType& longitude)\r
+{\r
+ detail::normalize_spheroidal_coordinates\r
+ <\r
+ Units, CoordinateType\r
+ >::apply(longitude);\r
+}\r
+\r
+\r
+/*!\r
+\brief Short utility to calculate difference between two longitudes\r
+ normalized in range (-180, 180].\r
+\tparam Units The units of the coordindate system in the spheroid\r
+\tparam CoordinateType The type of the coordinates\r
+\param longitude1 Longitude 1\r
+\param longitude2 Longitude 2\r
+\ingroup utility\r
+*/\r
+template <typename Units, typename CoordinateType>\r
+inline CoordinateType longitude_distance_signed(CoordinateType const& longitude1,\r
+ CoordinateType const& longitude2)\r
+{\r
+ CoordinateType diff = longitude2 - longitude1;\r
+ math::normalize_longitude<Units, CoordinateType>(diff);\r
+ return diff;\r
+}\r
+\r
+\r
+/*!\r
+\brief Short utility to calculate difference between two longitudes\r
+ normalized in range [0, 360).\r
+\tparam Units The units of the coordindate system in the spheroid\r
+\tparam CoordinateType The type of the coordinates\r
+\param longitude1 Longitude 1\r
+\param longitude2 Longitude 2\r
+\ingroup utility\r
+*/\r
+template <typename Units, typename CoordinateType>\r
+inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitude1,\r
+ CoordinateType const& longitude2)\r
+{\r
+ typedef math::detail::constants_on_spheroid\r
+ <\r
+ CoordinateType, Units\r
+ > constants;\r
+\r
+ CoordinateType const c0 = 0;\r
+ CoordinateType diff = longitude_distance_signed<Units>(longitude1, longitude2);\r
+ if (diff < c0) // (-180, 180] -> [0, 360)\r
+ {\r
+ diff += constants::period();\r
+ }\r
+ return diff;\r
+}\r
+\r
+} // namespace math\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP\r
+#define BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP\r
+\r
+#include <boost/geometry/core/point_order.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+template<order_selector Order>\r
+struct order_as_direction\r
+{};\r
+\r
+\r
+template<>\r
+struct order_as_direction<clockwise>\r
+{\r
+ static const iterate_direction value = iterate_forward;\r
+};\r
+\r
+\r
+template<>\r
+struct order_as_direction<counterclockwise>\r
+{\r
+ static const iterate_direction value = iterate_reverse;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP\r
+#define BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP\r
+\r
+\r
+#include <boost/function_types/function_arity.hpp>\r
+#include <boost/function_types/is_member_function_pointer.hpp>\r
+#include <boost/function_types/parameter_types.hpp>\r
+#include <boost/mpl/at.hpp>\r
+#include <boost/mpl/int.hpp>\r
+#include <boost/mpl/plus.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+\brief Meta-function selecting a parameter type of a (member) function, by index\r
+\ingroup utility\r
+ */\r
+template <typename Method, std::size_t Index>\r
+struct parameter_type_of\r
+{\r
+ typedef typename boost::function_types::parameter_types\r
+ <\r
+ Method\r
+ >::type parameter_types;\r
+\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::function_types::is_member_function_pointer<Method>,\r
+ boost::mpl::int_<1>,\r
+ boost::mpl::int_<0>\r
+ >::type base_index_type;\r
+\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ Index == 0,\r
+ base_index_type,\r
+ typename boost::mpl::plus\r
+ <\r
+ base_index_type,\r
+ boost::mpl::int_<Index>\r
+ >::type\r
+ >::type indexed_type;\r
+\r
+ typedef typename boost::remove_reference\r
+ <\r
+ typename boost::mpl::at\r
+ <\r
+ parameter_types,\r
+ indexed_type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP\r
+#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP\r
+\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_integral.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Meta-function converting, if necessary, to "a floating point" type\r
+ \details\r
+ - if input type is integer, type is double\r
+ - else type is input type\r
+ \ingroup utility\r
+ */\r
+\r
+template <typename T, typename PromoteIntegerTo = double>\r
+struct promote_floating_point\r
+{\r
+ typedef typename\r
+ boost::mpl::if_\r
+ <\r
+ boost::is_integral<T>,\r
+ PromoteIntegerTo,\r
+ T\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP\r
+#define BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP\r
+\r
+// For now deactivate the use of multiprecision integers\r
+// TODO: activate it later\r
+#define BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER\r
+\r
+#include <climits>\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/begin.hpp>\r
+#include <boost/mpl/deref.hpp>\r
+#include <boost/mpl/end.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/mpl/list.hpp>\r
+#include <boost/mpl/next.hpp>\r
+#include <boost/mpl/size_t.hpp>\r
+\r
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)\r
+#include <boost/multiprecision/cpp_int.hpp>\r
+#endif\r
+\r
+#include <boost/type_traits/integral_constant.hpp>\r
+#include <boost/type_traits/is_fundamental.hpp>\r
+#include <boost/type_traits/is_integral.hpp>\r
+#include <boost/type_traits/is_unsigned.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace promote_integral\r
+{\r
+\r
+// meta-function that returns the bit size of a type\r
+template\r
+<\r
+ typename T,\r
+ bool IsFundamental = boost::is_fundamental<T>::type::value\r
+>\r
+struct bit_size\r
+{};\r
+\r
+\r
+// for fundamental types, just return CHAR_BIT * sizeof(T)\r
+template <typename T>\r
+struct bit_size<T, true>\r
+ : boost::mpl::size_t<(CHAR_BIT * sizeof(T))>\r
+{};\r
+\r
+\r
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)\r
+// partial specialization for cpp_int\r
+template\r
+<\r
+ unsigned MinSize,\r
+ unsigned MaxSize,\r
+ boost::multiprecision::cpp_integer_type SignType,\r
+ boost::multiprecision::cpp_int_check_type Checked,\r
+ typename Allocator,\r
+ boost::multiprecision::expression_template_option ExpressionTemplates\r
+>\r
+struct bit_size\r
+ <\r
+ boost::multiprecision::number\r
+ <\r
+ boost::multiprecision::cpp_int_backend\r
+ <\r
+ MinSize, MaxSize, SignType, Checked, Allocator\r
+ >,\r
+ ExpressionTemplates\r
+ >,\r
+ false\r
+ > : boost::mpl::size_t<MaxSize>\r
+{};\r
+#endif // BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER\r
+\r
+\r
+template\r
+<\r
+ typename T,\r
+ typename Iterator,\r
+ typename EndIterator,\r
+ std::size_t MinSize\r
+>\r
+struct promote_to_larger\r
+{\r
+ typedef typename boost::mpl::deref<Iterator>::type current_type;\r
+\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ (bit_size<current_type>::type::value >= MinSize),\r
+ current_type,\r
+ typename promote_to_larger\r
+ <\r
+ T,\r
+ typename boost::mpl::next<Iterator>::type,\r
+ EndIterator,\r
+ MinSize\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+// The following specialization is required to finish the loop over\r
+// all list elements\r
+template <typename T, typename EndIterator, std::size_t MinSize>\r
+struct promote_to_larger<T, EndIterator, EndIterator, MinSize>\r
+{\r
+ // if promotion fails, keep the number T\r
+ // (and cross fingers that overflow will not occur)\r
+ typedef T type;\r
+};\r
+\r
+}} // namespace detail::promote_integral\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+\r
+/*!\r
+ \brief Meta-function to define an integral type with size\r
+ than is (roughly) twice the bit size of T\r
+ \ingroup utility\r
+ \details\r
+ This meta-function tries to promote the fundamental integral type T\r
+ to a another integral type with size (roughly) twice the bit size of T.\r
+\r
+ To do this, two times the bit size of T is tested against the bit sizes of:\r
+ short, int, long, boost::long_long_type, boost::int128_t\r
+ and the one that first matches is chosen.\r
+\r
+ For unsigned types the bit size of T is tested against the bit\r
+ sizes of the types above, if T is promoted to a signed type, or\r
+ the bit sizes of\r
+ unsigned short, unsigned int, unsigned long, std::size_t,\r
+ boost::ulong_long_type, boost::uint128_t\r
+ if T is promoted to an unsigned type.\r
+\r
+ By default an unsigned type is promoted to a signed type.\r
+ This behavior is controlled by the PromoteUnsignedToUnsigned\r
+ boolean template parameter, whose default value is "false".\r
+ To promote an unsigned type to an unsigned type set the value of\r
+ this template parameter to "true".\r
+\r
+ If the macro BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is not\r
+ defined, boost's multiprecision integer cpp_int<> is used as a\r
+ last resort.\r
+\r
+ If BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is defined and an\r
+ appropriate type cannot be detected, the input type is returned as is.\r
+\r
+ Finally, if the passed type is either a floating-point type or a\r
+ user-defined type it is returned as is.\r
+\r
+ \note boost::long_long_type and boost::ulong_long_type are\r
+ considered only if the macro BOOST_HAS_LONG_LONG is defined\r
+\r
+ \note boost::int128_type and boost::uint128_type are considered\r
+ only if the macros BOOST_HAS_INT128 and BOOST_GEOMETRY_ENABLE_INT128\r
+ are defined\r
+*/\r
+template\r
+<\r
+ typename T,\r
+ bool PromoteUnsignedToUnsigned = false,\r
+ bool UseCheckedInteger = false,\r
+ bool IsIntegral = boost::is_integral<T>::type::value\r
+>\r
+class promote_integral\r
+{\r
+private:\r
+ static bool const is_unsigned = boost::is_unsigned<T>::type::value;\r
+\r
+ typedef detail::promote_integral::bit_size<T> bit_size_type;\r
+\r
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)\r
+ // Define the proper check policy for the multiprecision integer\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ UseCheckedInteger,\r
+ boost::integral_constant\r
+ <\r
+ boost::multiprecision::cpp_int_check_type,\r
+ boost::multiprecision::checked\r
+ >,\r
+ boost::integral_constant\r
+ <\r
+ boost::multiprecision::cpp_int_check_type,\r
+ boost::multiprecision::unchecked\r
+ >\r
+ >::type check_policy_type;\r
+\r
+ // Meta-function to get the multiprecision integer type for the\r
+ // given size and sign type (signed/unsigned)\r
+ template\r
+ <\r
+ unsigned int Size,\r
+ boost::multiprecision::cpp_integer_type SignType\r
+ >\r
+ struct multiprecision_integer_type\r
+ {\r
+ typedef boost::multiprecision::number\r
+ <\r
+ boost::multiprecision::cpp_int_backend\r
+ <\r
+ Size,\r
+ Size,\r
+ SignType,\r
+ check_policy_type::value,\r
+ void\r
+ >\r
+ > type;\r
+ };\r
+#endif\r
+\r
+ // Define the minimum size (in bits) needed for the promoted type\r
+ // If T is the input type and P the promoted type, then the\r
+ // minimum number of bits for P are (below b stands for the number\r
+ // of bits of T):\r
+ // * if T is unsigned and P is unsigned: 2 * b\r
+ // * if T is signed and P is signed: 2 * b - 1\r
+ // * if T is unsigned and P is signed: 2 * b + 1\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ (PromoteUnsignedToUnsigned && is_unsigned),\r
+ boost::mpl::size_t<(2 * bit_size_type::value)>,\r
+ typename boost::mpl::if_c\r
+ <\r
+ is_unsigned,\r
+ boost::mpl::size_t<(2 * bit_size_type::value + 1)>,\r
+ boost::mpl::size_t<(2 * bit_size_type::value - 1)>\r
+ >::type\r
+ >::type min_bit_size_type;\r
+\r
+ // Define the list of signed integral types we are going to use\r
+ // for promotion\r
+ typedef boost::mpl::list\r
+ <\r
+ short, int, long\r
+#if defined(BOOST_HAS_LONG_LONG)\r
+ , boost::long_long_type\r
+#endif\r
+#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)\r
+ , boost::int128_type\r
+#endif\r
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)\r
+ , typename multiprecision_integer_type\r
+ <\r
+ min_bit_size_type::value,\r
+ boost::multiprecision::signed_magnitude\r
+ >::type\r
+#endif\r
+ > signed_integral_types;\r
+\r
+ // Define the list of unsigned integral types we are going to use\r
+ // for promotion\r
+ typedef boost::mpl::list\r
+ <\r
+ unsigned short, unsigned int, unsigned long, std::size_t\r
+#if defined(BOOST_HAS_LONG_LONG)\r
+ , boost::ulong_long_type\r
+#endif\r
+#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)\r
+ , boost::uint128_type\r
+#endif\r
+#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)\r
+ , typename multiprecision_integer_type\r
+ <\r
+ min_bit_size_type::value,\r
+ boost::multiprecision::unsigned_magnitude\r
+ >::type\r
+#endif\r
+ > unsigned_integral_types;\r
+\r
+ // Define the list of integral types that will be used for\r
+ // promotion (depending in whether we was to promote unsigned to\r
+ // unsigned or not)\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ (is_unsigned && PromoteUnsignedToUnsigned),\r
+ unsigned_integral_types,\r
+ signed_integral_types\r
+ >::type integral_types;\r
+\r
+public:\r
+ typedef typename detail::promote_integral::promote_to_larger\r
+ <\r
+ T,\r
+ typename boost::mpl::begin<integral_types>::type,\r
+ typename boost::mpl::end<integral_types>::type,\r
+ min_bit_size_type::value\r
+ >::type type;\r
+};\r
+\r
+\r
+template <typename T, bool PromoteUnsignedToUnsigned, bool UseCheckedInteger>\r
+class promote_integral\r
+ <\r
+ T, PromoteUnsignedToUnsigned, UseCheckedInteger, false\r
+ >\r
+{\r
+public:\r
+ typedef T type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+\r
+// This file was modified by Oracle on 2013, 2014, 2015, 2016.\r
+// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP\r
+#define BOOST_GEOMETRY_UTIL_RANGE_HPP\r
+\r
+#include <algorithm>\r
+#include <iterator>\r
+\r
+#include <boost/concept_check.hpp>\r
+#include <boost/config.hpp>\r
+#include <boost/core/addressof.hpp>\r
+#include <boost/range/concepts.hpp>\r
+#include <boost/range/begin.hpp>\r
+#include <boost/range/end.hpp>\r
+#include <boost/range/empty.hpp>\r
+#include <boost/range/difference_type.hpp>\r
+#include <boost/range/iterator.hpp>\r
+#include <boost/range/rbegin.hpp>\r
+#include <boost/range/reference.hpp>\r
+#include <boost/range/size.hpp>\r
+#include <boost/range/value_type.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/mutable_range.hpp>\r
+\r
+namespace boost { namespace geometry { namespace range {\r
+\r
+namespace detail {\r
+\r
+// NOTE: For SinglePassRanges pos could iterate over all elements until the i-th element was met.\r
+\r
+template <typename RandomAccessRange>\r
+struct pos\r
+{\r
+ typedef typename boost::range_iterator<RandomAccessRange>::type iterator;\r
+ typedef typename boost::range_size<RandomAccessRange>::type size_type;\r
+ typedef typename boost::range_difference<RandomAccessRange>::type difference_type;\r
+\r
+ static inline iterator apply(RandomAccessRange & rng, size_type i)\r
+ {\r
+ BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));\r
+ return boost::begin(rng) + static_cast<difference_type>(i);\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+\r
+/*!\r
+\brief Short utility to conveniently return an iterator of a RandomAccessRange.\r
+\ingroup utility\r
+*/\r
+template <typename RandomAccessRange>\r
+inline typename boost::range_iterator<RandomAccessRange const>::type\r
+pos(RandomAccessRange const& rng,\r
+ typename boost::range_size<RandomAccessRange const>::type i)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));\r
+ return detail::pos<RandomAccessRange const>::apply(rng, i);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently return an iterator of a RandomAccessRange.\r
+\ingroup utility\r
+*/\r
+template <typename RandomAccessRange>\r
+inline typename boost::range_iterator<RandomAccessRange>::type\r
+pos(RandomAccessRange & rng,\r
+ typename boost::range_size<RandomAccessRange>::type i)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));\r
+ return detail::pos<RandomAccessRange>::apply(rng, i);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently return an element of a RandomAccessRange.\r
+\ingroup utility\r
+*/\r
+template <typename RandomAccessRange>\r
+inline typename boost::range_reference<RandomAccessRange const>::type\r
+at(RandomAccessRange const& rng,\r
+ typename boost::range_size<RandomAccessRange const>::type i)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(i < boost::size(rng));\r
+ return * detail::pos<RandomAccessRange const>::apply(rng, i);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently return an element of a RandomAccessRange.\r
+\ingroup utility\r
+*/\r
+template <typename RandomAccessRange>\r
+inline typename boost::range_reference<RandomAccessRange>::type\r
+at(RandomAccessRange & rng,\r
+ typename boost::range_size<RandomAccessRange>::type i)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(i < boost::size(rng));\r
+ return * detail::pos<RandomAccessRange>::apply(rng, i);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently return the front element of a Range.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline typename boost::range_reference<Range const>::type\r
+front(Range const& rng)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));\r
+ return *boost::begin(rng);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently return the front element of a Range.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline typename boost::range_reference<Range>::type\r
+front(Range & rng)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));\r
+ return *boost::begin(rng);\r
+}\r
+\r
+// NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met.\r
+\r
+/*!\r
+\brief Short utility to conveniently return the back element of a BidirectionalRange.\r
+\ingroup utility\r
+*/\r
+template <typename BidirectionalRange>\r
+inline typename boost::range_reference<BidirectionalRange const>::type\r
+back(BidirectionalRange const& rng)\r
+{\r
+ BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));\r
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));\r
+ return *(boost::rbegin(rng));\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently return the back element of a BidirectionalRange.\r
+\ingroup utility\r
+*/\r
+template <typename BidirectionalRange>\r
+inline typename boost::range_reference<BidirectionalRange>::type\r
+back(BidirectionalRange & rng)\r
+{\r
+ BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));\r
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));\r
+ return *(boost::rbegin(rng));\r
+}\r
+\r
+\r
+/*!\r
+\brief Short utility to conveniently clear a mutable range.\r
+ It uses traits::clear<>.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline void clear(Range & rng)\r
+{\r
+ // NOTE: this trait is probably not needed since it could be implemented using resize()\r
+ geometry::traits::clear<Range>::apply(rng);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently insert a new element at the end of a mutable range.\r
+ It uses boost::geometry::traits::push_back<>.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline void push_back(Range & rng,\r
+ typename boost::range_value<Range>::type const& value)\r
+{\r
+ geometry::traits::push_back<Range>::apply(rng, value);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently resize a mutable range.\r
+ It uses boost::geometry::traits::resize<>.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline void resize(Range & rng,\r
+ typename boost::range_size<Range>::type new_size)\r
+{\r
+ geometry::traits::resize<Range>::apply(rng, new_size);\r
+}\r
+\r
+\r
+/*!\r
+\brief Short utility to conveniently remove an element from the back of a mutable range.\r
+ It uses resize().\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline void pop_back(Range & rng)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));\r
+ range::resize(rng, boost::size(rng) - 1);\r
+}\r
+\r
+namespace detail {\r
+\r
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES\r
+\r
+template <typename It,\r
+ typename OutIt,\r
+ bool UseMove = boost::is_convertible\r
+ <\r
+ typename std::iterator_traits<It>::value_type &&,\r
+ typename std::iterator_traits<OutIt>::value_type\r
+ >::value>\r
+struct copy_or_move_impl\r
+{\r
+ static inline OutIt apply(It first, It last, OutIt out)\r
+ {\r
+ return std::move(first, last, out);\r
+ }\r
+};\r
+\r
+template <typename It, typename OutIt>\r
+struct copy_or_move_impl<It, OutIt, false>\r
+{\r
+ static inline OutIt apply(It first, It last, OutIt out)\r
+ {\r
+ return std::copy(first, last, out);\r
+ }\r
+};\r
+\r
+template <typename It, typename OutIt>\r
+inline OutIt copy_or_move(It first, It last, OutIt out)\r
+{\r
+ return copy_or_move_impl<It, OutIt>::apply(first, last, out);\r
+}\r
+\r
+#else\r
+\r
+template <typename It, typename OutIt>\r
+inline OutIt copy_or_move(It first, It last, OutIt out)\r
+{\r
+ return std::copy(first, last, out);\r
+}\r
+\r
+#endif\r
+\r
+} // namespace detail\r
+\r
+/*!\r
+\brief Short utility to conveniently remove an element from a mutable range.\r
+ It uses std::copy() and resize(). Version taking mutable iterators.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline typename boost::range_iterator<Range>::type\r
+erase(Range & rng,\r
+ typename boost::range_iterator<Range>::type it)\r
+{\r
+ BOOST_GEOMETRY_ASSERT(!boost::empty(rng));\r
+ BOOST_GEOMETRY_ASSERT(it != boost::end(rng));\r
+\r
+ typename boost::range_difference<Range>::type const\r
+ d = std::distance(boost::begin(rng), it);\r
+\r
+ typename boost::range_iterator<Range>::type\r
+ next = it;\r
+ ++next;\r
+\r
+ detail::copy_or_move(next, boost::end(rng), it);\r
+ range::resize(rng, boost::size(rng) - 1);\r
+\r
+ // NOTE: In general this should be sufficient:\r
+ // return it;\r
+ // But in MSVC using the returned iterator causes\r
+ // assertion failures when iterator debugging is enabled\r
+ // Furthermore the code below should work in the case if resize()\r
+ // invalidates iterators when the container is resized down.\r
+ return boost::begin(rng) + d;\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently remove an element from a mutable range.\r
+ It uses std::copy() and resize(). Version taking non-mutable iterators.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline typename boost::range_iterator<Range>::type\r
+erase(Range & rng,\r
+ typename boost::range_iterator<Range const>::type cit)\r
+{\r
+ BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));\r
+\r
+ typename boost::range_iterator<Range>::type\r
+ it = boost::begin(rng)\r
+ + std::distance(boost::const_begin(rng), cit);\r
+\r
+ return erase(rng, it);\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently remove a range of elements from a mutable range.\r
+ It uses std::copy() and resize(). Version taking mutable iterators.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline typename boost::range_iterator<Range>::type\r
+erase(Range & rng,\r
+ typename boost::range_iterator<Range>::type first,\r
+ typename boost::range_iterator<Range>::type last)\r
+{\r
+ typename boost::range_difference<Range>::type const\r
+ diff = std::distance(first, last);\r
+ BOOST_GEOMETRY_ASSERT(diff >= 0);\r
+\r
+ std::size_t const count = static_cast<std::size_t>(diff);\r
+ BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));\r
+ \r
+ if ( count > 0 )\r
+ {\r
+ typename boost::range_difference<Range>::type const\r
+ d = std::distance(boost::begin(rng), first);\r
+\r
+ detail::copy_or_move(last, boost::end(rng), first);\r
+ range::resize(rng, boost::size(rng) - count);\r
+\r
+ // NOTE: In general this should be sufficient:\r
+ // return first;\r
+ // But in MSVC using the returned iterator causes\r
+ // assertion failures when iterator debugging is enabled\r
+ // Furthermore the code below should work in the case if resize()\r
+ // invalidates iterators when the container is resized down.\r
+ return boost::begin(rng) + d;\r
+ }\r
+\r
+ return first;\r
+}\r
+\r
+/*!\r
+\brief Short utility to conveniently remove a range of elements from a mutable range.\r
+ It uses std::copy() and resize(). Version taking non-mutable iterators.\r
+\ingroup utility\r
+*/\r
+template <typename Range>\r
+inline typename boost::range_iterator<Range>::type\r
+erase(Range & rng,\r
+ typename boost::range_iterator<Range const>::type cfirst,\r
+ typename boost::range_iterator<Range const>::type clast)\r
+{\r
+ BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));\r
+\r
+ typename boost::range_iterator<Range>::type\r
+ first = boost::begin(rng)\r
+ + std::distance(boost::const_begin(rng), cfirst);\r
+ typename boost::range_iterator<Range>::type\r
+ last = boost::begin(rng)\r
+ + std::distance(boost::const_begin(rng), clast);\r
+\r
+ return erase(rng, first, last);\r
+}\r
+\r
+// back_inserter\r
+\r
+template <class Container>\r
+class back_insert_iterator\r
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>\r
+{\r
+public:\r
+ typedef Container container_type;\r
+\r
+ explicit back_insert_iterator(Container & c)\r
+ : container(boost::addressof(c))\r
+ {}\r
+\r
+ back_insert_iterator & operator=(typename Container::value_type const& value)\r
+ {\r
+ range::push_back(*container, value);\r
+ return *this;\r
+ }\r
+\r
+ back_insert_iterator & operator* ()\r
+ {\r
+ return *this;\r
+ }\r
+\r
+ back_insert_iterator & operator++ ()\r
+ {\r
+ return *this;\r
+ }\r
+\r
+ back_insert_iterator operator++(int)\r
+ {\r
+ return *this;\r
+ }\r
+\r
+private:\r
+ Container * container;\r
+};\r
+\r
+template <typename Range>\r
+inline back_insert_iterator<Range> back_inserter(Range & rng)\r
+{\r
+ return back_insert_iterator<Range>(rng);\r
+}\r
+\r
+}}} // namespace boost::geometry::range\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2011-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2011-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP\r
+#define BOOST_GEOMETRY_UTIL_RATIONAL_HPP\r
+\r
+#include <boost/rational.hpp>\r
+#include <boost/numeric/conversion/bounds.hpp>\r
+\r
+#include <boost/geometry/util/coordinate_cast.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost{ namespace geometry\r
+{\r
+\r
+\r
+// Specialize for Boost.Geometry's coordinate cast\r
+// (from string to coordinate type)\r
+namespace detail\r
+{\r
+\r
+template <typename T>\r
+struct coordinate_cast<rational<T> >\r
+{\r
+ static inline void split_parts(std::string const& source, std::string::size_type p,\r
+ T& before, T& after, bool& negate, std::string::size_type& len)\r
+ {\r
+ std::string before_part = source.substr(0, p);\r
+ std::string const after_part = source.substr(p + 1);\r
+\r
+ negate = false;\r
+\r
+ if (before_part.size() > 0 && before_part[0] == '-')\r
+ {\r
+ negate = true;\r
+ before_part.erase(0, 1);\r
+ }\r
+ before = atol(before_part.c_str());\r
+ after = atol(after_part.c_str());\r
+ len = after_part.length();\r
+ }\r
+\r
+\r
+ static inline rational<T> apply(std::string const& source)\r
+ {\r
+ T before, after;\r
+ bool negate;\r
+ std::string::size_type len;\r
+\r
+ // Note: decimal comma is not (yet) supported, it does (and should) not\r
+ // occur in a WKT, where points are comma separated.\r
+ std::string::size_type p = source.find(".");\r
+ if (p == std::string::npos)\r
+ {\r
+ p = source.find("/");\r
+ if (p == std::string::npos)\r
+ {\r
+ return rational<T>(atol(source.c_str()));\r
+ }\r
+ split_parts(source, p, before, after, negate, len);\r
+\r
+ return negate\r
+ ? -rational<T>(before, after)\r
+ : rational<T>(before, after)\r
+ ;\r
+\r
+ }\r
+\r
+ split_parts(source, p, before, after, negate, len);\r
+\r
+ T den = 1;\r
+ for (std::string::size_type i = 0; i < len; i++)\r
+ {\r
+ den *= 10;\r
+ }\r
+\r
+ return negate\r
+ ? -rational<T>(before) - rational<T>(after, den)\r
+ : rational<T>(before) + rational<T>(after, den)\r
+ ;\r
+ }\r
+};\r
+\r
+} // namespace detail\r
+\r
+// Specialize for Boost.Geometry's select_most_precise\r
+template <typename T1, typename T2>\r
+struct select_most_precise<boost::rational<T1>, boost::rational<T2> >\r
+{\r
+ typedef typename boost::rational\r
+ <\r
+ typename select_most_precise<T1, T2>::type\r
+ > type;\r
+};\r
+\r
+template <typename T>\r
+struct select_most_precise<boost::rational<T>, double>\r
+{\r
+ typedef typename boost::rational<T> type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+// Specializes boost::rational to boost::numeric::bounds\r
+namespace boost { namespace numeric\r
+{\r
+\r
+template<class T>\r
+struct bounds<rational<T> >\r
+{\r
+ static inline rational<T> lowest()\r
+ {\r
+ return rational<T>(bounds<T>::lowest(), 1);\r
+ }\r
+ static inline rational<T> highest()\r
+ {\r
+ return rational<T>(bounds<T>::highest(), 1);\r
+ }\r
+};\r
+\r
+}} // namespace boost::numeric\r
+\r
+\r
+// Support for boost::numeric_cast to int and to double (necessary for SVG-mapper)\r
+namespace boost { namespace numeric\r
+{\r
+\r
+template\r
+<\r
+ typename T,\r
+ typename Traits,\r
+ typename OverflowHandler,\r
+ typename Float2IntRounder,\r
+ typename RawConverter,\r
+ typename UserRangeChecker\r
+>\r
+struct converter<int, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>\r
+{\r
+ static inline int convert(rational<T> const& arg)\r
+ {\r
+ return int(rational_cast<double>(arg));\r
+ }\r
+};\r
+\r
+template\r
+<\r
+ typename T,\r
+ typename Traits,\r
+ typename OverflowHandler,\r
+ typename Float2IntRounder,\r
+ typename RawConverter,\r
+ typename UserRangeChecker\r
+>\r
+struct converter<double, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>\r
+{\r
+ static inline double convert(rational<T> const& arg)\r
+ {\r
+ return rational_cast<double>(arg);\r
+ }\r
+};\r
+\r
+\r
+}}\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+This folder contains several headerfiles not fitting in one of the other folders,\r
+or meta-functions which would fit into boost as a separate trait or utility,\r
+such as add_const_if_c\r
+\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP\r
+#define BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP\r
+\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_void.hpp>\r
+\r
+#include <boost/geometry/util/select_coordinate_type.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Meta-function selecting the "calculation" type\r
+ \details Based on two input geometry types, and an input calculation type,\r
+ (which defaults to void in the calling function), this meta-function\r
+ selects the most appropriate:\r
+ - if calculation type is specified, that one is used,\r
+ - if it is void, the most precise of the two points is used\r
+ \ingroup utility\r
+ */\r
+template <typename Geometry1, typename Geometry2, typename CalculationType>\r
+struct select_calculation_type\r
+{\r
+ typedef typename\r
+ boost::mpl::if_\r
+ <\r
+ boost::is_void<CalculationType>,\r
+ typename select_coordinate_type\r
+ <\r
+ Geometry1,\r
+ Geometry2\r
+ >::type,\r
+ CalculationType\r
+ >::type type;\r
+};\r
+\r
+// alternative version supporting more than 2 Geometries\r
+\r
+template <typename CalculationType,\r
+ typename Geometry1,\r
+ typename Geometry2 = void,\r
+ typename Geometry3 = void>\r
+struct select_calculation_type_alt\r
+{\r
+ typedef typename\r
+ boost::mpl::if_\r
+ <\r
+ boost::is_void<CalculationType>,\r
+ typename select_coordinate_type\r
+ <\r
+ Geometry1,\r
+ Geometry2,\r
+ Geometry3\r
+ >::type,\r
+ CalculationType\r
+ >::type type;\r
+};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP\r
+#define BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP\r
+\r
+\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/util/select_most_precise.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Meta-function selecting the most precise coordinate type\r
+ of two geometries\r
+ \ingroup utility\r
+ */\r
+template <typename T1, typename T2 = void, typename T3 = void>\r
+struct select_coordinate_type\r
+{\r
+ typedef typename select_most_precise\r
+ <\r
+ typename coordinate_type<T1>::type,\r
+ typename coordinate_type<T2>::type,\r
+ typename coordinate_type<T3>::type\r
+ >::type type;\r
+};\r
+\r
+template <typename T1, typename T2>\r
+struct select_coordinate_type<T1, T2, void>\r
+{\r
+ typedef typename select_most_precise\r
+ <\r
+ typename coordinate_type<T1>::type,\r
+ typename coordinate_type<T2>::type\r
+ >::type type;\r
+};\r
+\r
+template <typename T1>\r
+struct select_coordinate_type<T1, void, void>\r
+{\r
+ typedef typename select_most_precise\r
+ <\r
+ typename coordinate_type<T1>::type\r
+ >::type type;\r
+};\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP\r
+#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP\r
+\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_floating_point.hpp>\r
+#include <boost/type_traits/is_fundamental.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+\r
+namespace detail { namespace select_most_precise\r
+{\r
+\r
+\r
+// At least one of the types is non-fundamental. Take that one.\r
+// if both are non-fundamental, the type-to-be-selected\r
+// is unknown, it should be defined by explicit specialization.\r
+template <bool Fundamental1, bool Fundamental2, typename T1, typename T2>\r
+struct select_non_fundamental\r
+{\r
+ typedef T1 type;\r
+};\r
+\r
+template <typename T1, typename T2>\r
+struct select_non_fundamental<true, false, T1, T2>\r
+{\r
+ typedef T2 type;\r
+};\r
+\r
+template <typename T1, typename T2>\r
+struct select_non_fundamental<false, true, T1, T2>\r
+{\r
+ typedef T1 type;\r
+};\r
+\r
+\r
+// Selection of largest type (e.g. int of <short int,int>\r
+// It defaults takes the first one, if second is larger, take the second one\r
+template <bool SecondLarger, typename T1, typename T2>\r
+struct select_largest\r
+{\r
+ typedef T1 type;\r
+};\r
+\r
+template <typename T1, typename T2>\r
+struct select_largest<true, T1, T2>\r
+{\r
+ typedef T2 type;\r
+};\r
+\r
+\r
+\r
+// Selection of floating point and specializations:\r
+// both FP or both !FP does never occur...\r
+template <bool FP1, bool FP2, typename T1, typename T2>\r
+struct select_floating_point\r
+{\r
+ typedef char type;\r
+};\r
+\r
+\r
+// ... so if ONE but not both of these types is floating point, take that one\r
+template <typename T1, typename T2>\r
+struct select_floating_point<true, false, T1, T2>\r
+{\r
+ typedef T1 type;\r
+};\r
+\r
+\r
+template <typename T1, typename T2>\r
+struct select_floating_point<false, true, T1, T2>\r
+{\r
+ typedef T2 type;\r
+};\r
+\r
+\r
+}} // namespace detail::select_most_precise\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+ \brief Meta-function to select, of two types, the most accurate type for\r
+ calculations\r
+ \ingroup utility\r
+ \details select_most_precise classes, compares two types on compile time.\r
+ For example, if an addition must be done with a double and an integer, the\r
+ result must be a double.\r
+ If both types are integer, the result can be an integer.\r
+ \note It is different from the "promote" class, already in boost. That\r
+ class promotes e.g. a (one) float to a double. This class selects a\r
+ type from two types. It takes the most accurate, but does not promote\r
+ afterwards.\r
+ \note This traits class is completely independant from GGL and might be a\r
+ separate addition to Boost\r
+ \note If the input is a non-fundamental type, it might be a calculation\r
+ type such as a GMP-value or another high precision value. Therefore,\r
+ if one is non-fundamental, that one is chosen.\r
+ \note If both types are non-fundamental, the result is indeterminate and\r
+ currently the first one is chosen.\r
+*/\r
+template <typename T1, typename T2 = void, typename T3 = void>\r
+struct select_most_precise\r
+{\r
+ typedef typename select_most_precise\r
+ <\r
+ typename select_most_precise<T1, T2>::type,\r
+ T3\r
+ >::type type;\r
+};\r
+\r
+template <typename T1, typename T2>\r
+struct select_most_precise<T1, T2, void>\r
+{\r
+ static const bool second_larger = sizeof(T2) > sizeof(T1);\r
+ static const bool one_not_fundamental = !\r
+ (boost::is_fundamental<T1>::type::value\r
+ && boost::is_fundamental<T2>::type::value);\r
+\r
+ static const bool both_same =\r
+ boost::is_floating_point<T1>::type::value\r
+ == boost::is_floating_point<T2>::type::value;\r
+\r
+ typedef typename boost::mpl::if_c\r
+ <\r
+ one_not_fundamental,\r
+ typename detail::select_most_precise::select_non_fundamental\r
+ <\r
+ boost::is_fundamental<T1>::type::value,\r
+ boost::is_fundamental<T2>::type::value,\r
+ T1,\r
+ T2\r
+ >::type,\r
+ typename boost::mpl::if_c\r
+ <\r
+ both_same,\r
+ typename detail::select_most_precise::select_largest\r
+ <\r
+ second_larger,\r
+ T1,\r
+ T2\r
+ >::type,\r
+ typename detail::select_most_precise::select_floating_point\r
+ <\r
+ boost::is_floating_point<T1>::type::value,\r
+ boost::is_floating_point<T2>::type::value,\r
+ T1,\r
+ T2\r
+ >::type\r
+ >::type\r
+ >::type type;\r
+};\r
+\r
+template <typename T1>\r
+struct select_most_precise<T1, void, void>\r
+{\r
+ typedef T1 type;\r
+};\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP\r
+#define BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP\r
+\r
+\r
+#include <boost/mpl/transform.hpp>\r
+#include <boost/variant/variant_fwd.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+ \brief Meta-function that takes a Sequence type, an MPL lambda\r
+ expression and an optional Inserter and returns a variant type over\r
+ the same types as the initial variant type, each transformed using\r
+ the lambda expression.\r
+ \ingroup utility\r
+ \par Example\r
+ \code\r
+ typedef boost::mpl::vector<int, float, long> types;\r
+ typedef transform_variant<types, add_pointer<_> > transformed;\r
+ typedef variant<int*, float*, long*> result;\r
+ BOOST_MPL_ASSERT(( equal<result, transformed> ));\r
+ \endcode\r
+*/\r
+template <typename Sequence, typename Op, typename In = boost::mpl::na>\r
+struct transform_variant:\r
+ make_variant_over<\r
+ typename boost::mpl::transform<\r
+ Sequence,\r
+ Op,\r
+ In\r
+ >::type\r
+ >\r
+{};\r
+\r
+\r
+/*!\r
+ \brief Meta-function that takes a boost::variant type and an MPL lambda\r
+ expression and returns a variant type over the same types as the\r
+ initial variant type, each transformed using the lambda expression.\r
+ \ingroup utility\r
+ \par Example\r
+ \code\r
+ typedef variant<int, float, long> variant_type;\r
+ typedef transform_variant<variant_type, add_pointer<_> > transformed;\r
+ typedef variant<int*, float*, long*> result;\r
+ BOOST_MPL_ASSERT(( equal<result, transformed> ));\r
+ \endcode\r
+*/\r
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Op>\r
+struct transform_variant<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Op, boost::mpl::na> :\r
+ make_variant_over<\r
+ typename boost::mpl::transform<\r
+ typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,\r
+ Op\r
+ >::type\r
+ >\r
+{};\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_BOX_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_BOX_VIEW_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/views/detail/points_view.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+\brief Makes a box behave like a ring or a range\r
+\details Adapts a box to the Boost.Range concept, enabling the user to iterating\r
+ box corners. The box_view is registered as a Ring Concept\r
+\tparam Box \tparam_geometry{Box}\r
+\tparam Clockwise If true, walks in clockwise direction, otherwise\r
+ it walks in counterclockwise direction\r
+\ingroup views\r
+\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_ring Ring Concept]\r
+}\r
+\r
+\qbk{[include reference/views/box_view.qbk]}\r
+*/\r
+template <typename Box, bool Clockwise = true>\r
+struct box_view\r
+ : public detail::points_view\r
+ <\r
+ typename geometry::point_type<Box>::type,\r
+ 5\r
+ >\r
+{\r
+ typedef typename geometry::point_type<Box>::type point_type;\r
+\r
+ /// Constructor accepting the box to adapt\r
+ explicit box_view(Box const& box)\r
+ : detail::points_view<point_type, 5>(copy_policy(box))\r
+ {}\r
+\r
+private :\r
+\r
+ class copy_policy\r
+ {\r
+ public :\r
+ inline copy_policy(Box const& box)\r
+ : m_box(box)\r
+ {}\r
+\r
+ inline void apply(point_type* points) const\r
+ {\r
+ // assign_box_corners_oriented requires a range\r
+ // an alternative for this workaround would be to pass a range here,\r
+ // e.g. use boost::array in points_view instead of c-array\r
+ std::pair<point_type*, point_type*> rng = std::make_pair(points, points + 5);\r
+ detail::assign_box_corners_oriented<!Clockwise>(m_box, rng);\r
+ points[4] = points[0];\r
+ }\r
+ private :\r
+ Box const& m_box;\r
+ };\r
+\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+// All views on boxes are handled as rings\r
+namespace traits\r
+{\r
+\r
+template<typename Box, bool Clockwise>\r
+struct tag<box_view<Box, Clockwise> >\r
+{\r
+ typedef ring_tag type;\r
+};\r
+\r
+template<typename Box>\r
+struct point_order<box_view<Box, false> >\r
+{\r
+ static order_selector const value = counterclockwise;\r
+};\r
+\r
+\r
+template<typename Box>\r
+struct point_order<box_view<Box, true> >\r
+{\r
+ static order_selector const value = clockwise;\r
+};\r
+\r
+}\r
+\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_BOX_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+#include <boost/geometry/iterators/closing_iterator.hpp>\r
+\r
+#include <boost/geometry/views/identity_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4512: assignment operator could not be generated\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4512)\r
+#endif\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+\r
+namespace detail\r
+{\r
+\r
+template <typename Range>\r
+struct closing_view\r
+{\r
+ // Keep this explicit, important for nested views/ranges\r
+ explicit inline closing_view(Range& r)\r
+ : m_range(r)\r
+ {}\r
+\r
+ typedef closing_iterator<Range> iterator;\r
+ typedef closing_iterator<Range const> const_iterator;\r
+\r
+ inline const_iterator begin() const { return const_iterator(m_range); }\r
+ inline const_iterator end() const { return const_iterator(m_range, true); }\r
+\r
+ inline iterator begin() { return iterator(m_range); }\r
+ inline iterator end() { return iterator(m_range, true); }\r
+private :\r
+ Range& m_range;\r
+};\r
+\r
+}\r
+\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+/*!\r
+\brief View on a range, either closing it or leaving it as it is\r
+\details The closeable_view is used internally by the library to handle all rings,\r
+ either closed or open, the same way. The default method is closed, all\r
+ algorithms process rings as if they are closed. Therefore, if they are opened,\r
+ a view is created which closes them.\r
+ The closeable_view might be used by library users, but its main purpose is\r
+ internally.\r
+\tparam Range Original range\r
+\tparam Close Specifies if it the range is closed, if so, nothing will happen.\r
+ If it is open, it will iterate the first point after the last point.\r
+\ingroup views\r
+*/\r
+template <typename Range, closure_selector Close>\r
+struct closeable_view {};\r
+\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+template <typename Range>\r
+struct closeable_view<Range, closed>\r
+{\r
+ typedef identity_view<Range> type;\r
+};\r
+\r
+\r
+template <typename Range>\r
+struct closeable_view<Range, open>\r
+{\r
+ typedef detail::closing_view<Range> type;\r
+};\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP\r
+\r
+#include <boost/geometry/views/detail/boundary_view/interface.hpp>\r
+#include <boost/geometry/views/detail/boundary_view/implementation.hpp>\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP\r
+\r
+#include <cstddef>\r
+#include <algorithm>\r
+#include <iterator>\r
+#include <memory>\r
+#include <new>\r
+#include <utility>\r
+#include <vector>\r
+\r
+#include <boost/core/addressof.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/type_traits/is_convertible.hpp>\r
+#include <boost/type_traits/remove_reference.hpp>\r
+\r
+#include <boost/geometry/core/assert.hpp>\r
+#include <boost/geometry/core/closure.hpp>\r
+#include <boost/geometry/core/exterior_ring.hpp>\r
+#include <boost/geometry/core/interior_rings.hpp>\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/iterators/flatten_iterator.hpp>\r
+\r
+#include <boost/geometry/util/range.hpp>\r
+\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+\r
+#include <boost/geometry/algorithms/num_interior_rings.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail { namespace boundary_views\r
+{\r
+\r
+\r
+template\r
+<\r
+ typename Polygon,\r
+ typename Value = typename ring_type<Polygon>::type,\r
+ typename Reference = typename ring_return_type<Polygon>::type,\r
+ typename Difference = typename boost::range_difference\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename interior_return_type<Polygon>::type\r
+ >::type\r
+ >::type\r
+>\r
+class polygon_rings_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ polygon_rings_iterator<Polygon, Value, Reference, Difference>,\r
+ Value,\r
+ boost::random_access_traversal_tag,\r
+ Reference,\r
+ Difference\r
+ >\r
+{\r
+ typedef typename boost::range_size\r
+ <\r
+ typename boost::remove_reference\r
+ <\r
+ typename interior_return_type<Polygon>::type\r
+ >::type\r
+ >::type size_type;\r
+\r
+public:\r
+ // default constructor\r
+ polygon_rings_iterator()\r
+ : m_polygon(NULL)\r
+ , m_index(0)\r
+ {}\r
+\r
+ // for begin\r
+ polygon_rings_iterator(Polygon& polygon)\r
+ : m_polygon(boost::addressof(polygon))\r
+ , m_index(0)\r
+ {}\r
+\r
+ // for end\r
+ polygon_rings_iterator(Polygon& polygon, bool)\r
+ : m_polygon(boost::addressof(polygon))\r
+ , m_index(static_cast<size_type>(num_rings(polygon)))\r
+ {}\r
+\r
+ template\r
+ <\r
+ typename OtherPolygon,\r
+ typename OtherValue,\r
+ typename OtherReference,\r
+ typename OtherDifference\r
+ >\r
+ polygon_rings_iterator(polygon_rings_iterator\r
+ <\r
+ OtherPolygon,\r
+ OtherValue,\r
+ OtherReference,\r
+ OtherDifference\r
+ > const& other)\r
+ : m_polygon(other.m_polygon)\r
+ , m_index(other.m_index)\r
+ {\r
+ static const bool is_convertible\r
+ = boost::is_convertible<OtherPolygon, Polygon>::value;\r
+\r
+ BOOST_MPL_ASSERT_MSG((is_convertible),\r
+ NOT_CONVERTIBLE,\r
+ (types<OtherPolygon>));\r
+ }\r
+\r
+private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ template\r
+ <\r
+ typename OtherPolygon,\r
+ typename OtherValue,\r
+ typename OtherReference,\r
+ typename OtherDifference\r
+ >\r
+ friend class polygon_rings_iterator;\r
+\r
+\r
+ static inline std::size_t num_rings(Polygon const& polygon)\r
+ {\r
+ return geometry::num_interior_rings(polygon) + 1;\r
+ }\r
+\r
+ inline Reference dereference() const\r
+ {\r
+ if (m_index == 0)\r
+ {\r
+ return exterior_ring(*m_polygon);\r
+ }\r
+ return range::at(interior_rings(*m_polygon), m_index - 1);\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OtherPolygon,\r
+ typename OtherValue,\r
+ typename OtherReference,\r
+ typename OtherDifference\r
+ >\r
+ inline bool equal(polygon_rings_iterator\r
+ <\r
+ OtherPolygon,\r
+ OtherValue,\r
+ OtherReference,\r
+ OtherDifference\r
+ > const& other) const\r
+ {\r
+ BOOST_GEOMETRY_ASSERT(m_polygon == other.m_polygon);\r
+ return m_index == other.m_index;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ ++m_index;\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ --m_index;\r
+ }\r
+\r
+ template\r
+ <\r
+ typename OtherPolygon,\r
+ typename OtherValue,\r
+ typename OtherReference,\r
+ typename OtherDifference\r
+ >\r
+ inline Difference distance_to(polygon_rings_iterator\r
+ <\r
+ OtherPolygon,\r
+ OtherValue,\r
+ OtherReference,\r
+ OtherDifference\r
+ > const& other) const\r
+ {\r
+ return static_cast<Difference>(other.m_index)\r
+ - static_cast<Difference>(m_index);\r
+ }\r
+\r
+ inline void advance(Difference n)\r
+ {\r
+ m_index += n;\r
+ }\r
+\r
+private:\r
+ Polygon* m_polygon;\r
+ size_type m_index;\r
+};\r
+\r
+\r
+template <typename Ring>\r
+class ring_boundary : closeable_view<Ring, closure<Ring>::value>::type\r
+{\r
+private:\r
+ typedef typename closeable_view<Ring, closure<Ring>::value>::type base_type;\r
+\r
+public:\r
+ typedef typename base_type::iterator iterator;\r
+ typedef typename base_type::const_iterator const_iterator;\r
+ \r
+ typedef linestring_tag tag_type;\r
+\r
+ explicit ring_boundary(Ring& ring)\r
+ : base_type(ring) {}\r
+\r
+ iterator begin() { return base_type::begin(); }\r
+ iterator end() { return base_type::end(); }\r
+ const_iterator begin() const { return base_type::begin(); }\r
+ const_iterator end() const { return base_type::end(); }\r
+};\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct num_rings\r
+{};\r
+\r
+template <typename Polygon>\r
+struct num_rings<Polygon, polygon_tag>\r
+{\r
+ static inline std::size_t apply(Polygon const& polygon)\r
+ {\r
+ return geometry::num_interior_rings(polygon) + 1;\r
+ }\r
+};\r
+\r
+template <typename MultiPolygon>\r
+struct num_rings<MultiPolygon, multi_polygon_tag>\r
+{\r
+ static inline std::size_t apply(MultiPolygon const& multipolygon)\r
+ {\r
+ return geometry::num_interior_rings(multipolygon)\r
+ + static_cast<std::size_t>(boost::size(multipolygon));\r
+ }\r
+};\r
+\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct views_container_initializer\r
+{};\r
+\r
+template <typename Polygon>\r
+struct views_container_initializer<Polygon, polygon_tag>\r
+{\r
+ template <typename BoundaryView>\r
+ static inline void apply(Polygon const& polygon, BoundaryView* views)\r
+ {\r
+ typedef polygon_rings_iterator<Polygon> rings_iterator_type;\r
+\r
+ std::uninitialized_copy(rings_iterator_type(polygon),\r
+ rings_iterator_type(polygon, true),\r
+ views);\r
+ }\r
+};\r
+\r
+template <typename MultiPolygon>\r
+class views_container_initializer<MultiPolygon, multi_polygon_tag>\r
+{\r
+ typedef typename boost::mpl::if_\r
+ <\r
+ boost::is_const<MultiPolygon>,\r
+ typename boost::range_value<MultiPolygon>::type const,\r
+ typename boost::range_value<MultiPolygon>::type\r
+ >::type polygon_type;\r
+\r
+ typedef polygon_rings_iterator<polygon_type> inner_iterator_type;\r
+\r
+ struct polygon_rings_begin\r
+ {\r
+ static inline inner_iterator_type apply(polygon_type& polygon)\r
+ {\r
+ return inner_iterator_type(polygon);\r
+ }\r
+ };\r
+\r
+ struct polygon_rings_end\r
+ {\r
+ static inline inner_iterator_type apply(polygon_type& polygon)\r
+ {\r
+ return inner_iterator_type(polygon, true);\r
+ }\r
+ };\r
+\r
+ typedef flatten_iterator\r
+ <\r
+ typename boost::range_iterator<MultiPolygon>::type,\r
+ inner_iterator_type,\r
+ typename std::iterator_traits<inner_iterator_type>::value_type,\r
+ polygon_rings_begin,\r
+ polygon_rings_end,\r
+ typename std::iterator_traits<inner_iterator_type>::reference\r
+ > rings_iterator_type;\r
+\r
+public:\r
+ template <typename BoundaryView>\r
+ static inline void apply(MultiPolygon const& multipolygon,\r
+ BoundaryView* views)\r
+ {\r
+ rings_iterator_type first(boost::begin(multipolygon),\r
+ boost::end(multipolygon));\r
+ rings_iterator_type last(boost::end(multipolygon));\r
+\r
+ std::uninitialized_copy(first, last, views);\r
+ }\r
+};\r
+\r
+\r
+template <typename Areal>\r
+class areal_boundary\r
+{\r
+ typedef boundary_view<typename ring_type<Areal>::type> boundary_view_type;\r
+ typedef views_container_initializer<Areal> exception_safe_initializer;\r
+\r
+ template <typename T>\r
+ struct automatic_deallocator\r
+ {\r
+ automatic_deallocator(T* ptr) : m_ptr(ptr) {}\r
+\r
+ ~automatic_deallocator()\r
+ {\r
+ operator delete(m_ptr);\r
+ }\r
+\r
+ inline void release() { m_ptr = NULL; }\r
+\r
+ T* m_ptr;\r
+ };\r
+\r
+ inline void initialize_views(Areal const& areal)\r
+ {\r
+ // initialize number of rings\r
+ std::size_t n_rings = num_rings<Areal>::apply(areal);\r
+\r
+ if (n_rings == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ // allocate dynamic memory\r
+ boundary_view_type* views_ptr = static_cast\r
+ <\r
+ boundary_view_type*\r
+ >(operator new(sizeof(boundary_view_type) * n_rings));\r
+\r
+ // initialize; if exceptions are thrown by constructors\r
+ // they are handled automatically by automatic_deallocator\r
+ automatic_deallocator<boundary_view_type> deallocator(views_ptr);\r
+ exception_safe_initializer::apply(areal, views_ptr);\r
+ deallocator.release();\r
+\r
+ // now initialize member variables safely\r
+ m_views = views_ptr;\r
+ m_num_rings = n_rings;\r
+ }\r
+\r
+ // disallow copies and/or assignments\r
+ areal_boundary(areal_boundary const&);\r
+ areal_boundary& operator=(areal_boundary const&);\r
+\r
+public:\r
+ typedef boundary_view_type* iterator;\r
+ typedef boundary_view_type const* const_iterator;\r
+\r
+ typedef multi_linestring_tag tag_type;\r
+\r
+ explicit areal_boundary(Areal& areal)\r
+ : m_views(NULL)\r
+ , m_num_rings(0)\r
+ {\r
+ initialize_views(areal);\r
+ }\r
+\r
+ ~areal_boundary()\r
+ {\r
+ boundary_view_type* last = m_views + m_num_rings;\r
+ for (boundary_view_type* it = m_views; it != last; ++it)\r
+ {\r
+ it->~boundary_view_type();\r
+ }\r
+ operator delete(m_views);\r
+ }\r
+\r
+ inline iterator begin() { return m_views; }\r
+ inline iterator end() { return m_views + m_num_rings; }\r
+ inline const_iterator begin() const { return m_views; }\r
+ inline const_iterator end() const { return m_views + m_num_rings; }\r
+\r
+private:\r
+ boundary_view_type* m_views;\r
+ std::size_t m_num_rings;\r
+};\r
+\r
+\r
+}} // namespace detail::boundary_view\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch\r
+{\r
+\r
+\r
+template <typename Ring>\r
+struct boundary_view<Ring, ring_tag>\r
+ : detail::boundary_views::ring_boundary<Ring>\r
+{\r
+ explicit boundary_view(Ring& ring)\r
+ : detail::boundary_views::ring_boundary<Ring>(ring)\r
+ {}\r
+};\r
+\r
+template <typename Polygon>\r
+struct boundary_view<Polygon, polygon_tag>\r
+ : detail::boundary_views::areal_boundary<Polygon>\r
+{\r
+ explicit boundary_view(Polygon& polygon)\r
+ : detail::boundary_views::areal_boundary<Polygon>(polygon)\r
+ {}\r
+};\r
+\r
+template <typename MultiPolygon>\r
+struct boundary_view<MultiPolygon, multi_polygon_tag>\r
+ : detail::boundary_views::areal_boundary<MultiPolygon>\r
+{\r
+ explicit boundary_view(MultiPolygon& multipolygon)\r
+ : detail::boundary_views::areal_boundary\r
+ <\r
+ MultiPolygon\r
+ >(multipolygon)\r
+ {}\r
+};\r
+\r
+\r
+} // namespace detail_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_IMPLEMENTATION_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP\r
+\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace detail_dispatch\r
+{\r
+\r
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>\r
+struct boundary_view\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+} // namespace detail_dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template <typename Geometry>\r
+struct boundary_view\r
+ : detail_dispatch::boundary_view<Geometry>\r
+{\r
+ explicit boundary_view(Geometry& geometry)\r
+ : detail_dispatch::boundary_view<Geometry>(geometry)\r
+ {}\r
+};\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename Geometry>\r
+struct tag< geometry::detail::boundary_view<Geometry> >\r
+{\r
+ typedef typename detail_dispatch::boundary_view\r
+ <\r
+ Geometry\r
+ >::tag_type type;\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_BOUNDARY_VIEW_INTERFACE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.\r
+// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland\r
+\r
+// This file was modified by Oracle on 2015.\r
+// Modifications copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_INDEXED_POINT_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_INDEXED_POINT_VIEW_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/util/math.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+template <typename Geometry, std::size_t Index>\r
+class indexed_point_view\r
+{\r
+ indexed_point_view & operator=(indexed_point_view const&);\r
+\r
+public:\r
+ typedef typename geometry::point_type<Geometry>::type point_type;\r
+ typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ indexed_point_view(Geometry & geometry)\r
+ : m_geometry(geometry)\r
+ {}\r
+\r
+ template <std::size_t Dimension>\r
+ inline coordinate_type get() const\r
+ {\r
+ return geometry::get<Index, Dimension>(m_geometry);\r
+ }\r
+\r
+ template <std::size_t Dimension>\r
+ inline void set(coordinate_type const& value)\r
+ {\r
+ geometry::set<Index, Dimension>(m_geometry, value);\r
+ }\r
+\r
+private:\r
+ Geometry & m_geometry;\r
+};\r
+\r
+}\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+template <typename Geometry, std::size_t Index>\r
+struct tag< geometry::detail::indexed_point_view<Geometry, Index> >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+template <typename Geometry, std::size_t Index>\r
+struct coordinate_type< geometry::detail::indexed_point_view<Geometry, Index> >\r
+{\r
+ typedef typename geometry::coordinate_type<Geometry>::type type;\r
+};\r
+\r
+template <typename Geometry, std::size_t Index>\r
+struct coordinate_system\r
+ <\r
+ geometry::detail::indexed_point_view<Geometry, Index>\r
+ >\r
+{\r
+ typedef typename geometry::coordinate_system<Geometry>::type type;\r
+};\r
+\r
+template <typename Geometry, std::size_t Index>\r
+struct dimension< geometry::detail::indexed_point_view<Geometry, Index> >\r
+ : geometry::dimension<Geometry>\r
+{};\r
+\r
+template<typename Geometry, std::size_t Index, std::size_t Dimension>\r
+struct access\r
+ <\r
+ geometry::detail::indexed_point_view<Geometry, Index>, Dimension\r
+ >\r
+{\r
+ typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;\r
+\r
+ static inline coordinate_type get(\r
+ geometry::detail::indexed_point_view<Geometry, Index> const& p)\r
+ {\r
+ return p.template get<Dimension>();\r
+ }\r
+\r
+ static inline void set(\r
+ geometry::detail::indexed_point_view<Geometry, Index> & p,\r
+ coordinate_type const& value)\r
+ {\r
+ p.template set<Dimension>(value);\r
+ }\r
+};\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_INDEXED_POINT_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// This file was modified by Oracle on 2014.\r
+// Modifications copyright (c) 2014 Oracle and/or its affiliates.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_NORMALIZED_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_NORMALIZED_VIEW_HPP\r
+\r
+\r
+#include <boost/range/begin.hpp>\r
+#include <boost/range/end.hpp>\r
+#include <boost/range/iterator.hpp>\r
+#include <boost/mpl/if.hpp>\r
+#include <boost/type_traits/is_const.hpp>\r
+#include <boost/geometry/views/detail/range_type.hpp>\r
+#include <boost/geometry/views/reversible_view.hpp>\r
+#include <boost/geometry/views/closeable_view.hpp>\r
+#include <boost/geometry/util/order_as_direction.hpp>\r
+\r
+namespace boost { namespace geometry {\r
+\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+\r
+namespace detail {\r
+\r
+template <typename Geometry>\r
+struct normalized_view\r
+{\r
+ static const bool is_const = boost::is_const<Geometry>::value;\r
+\r
+ //typedef typename ring_type<Geometry>::type ring_type;\r
+\r
+ typedef typename detail::range_type<Geometry>::type range_type;\r
+\r
+ typedef typename\r
+ boost::mpl::if_c\r
+ <\r
+ is_const,\r
+ range_type const,\r
+ range_type\r
+ >::type range;\r
+\r
+ typedef typename\r
+ reversible_view\r
+ <\r
+ range,\r
+ order_as_direction\r
+ <\r
+ geometry::point_order<Geometry>::value\r
+ >::value\r
+ >::type reversible_type;\r
+\r
+ typedef typename\r
+ boost::mpl::if_c\r
+ <\r
+ is_const,\r
+ reversible_type const,\r
+ reversible_type\r
+ >::type reversible;\r
+\r
+ typedef typename\r
+ closeable_view\r
+ <\r
+ reversible,\r
+ geometry::closure<Geometry>::value\r
+ >::type closeable_type;\r
+\r
+ typedef typename\r
+ boost::mpl::if_c\r
+ <\r
+ is_const,\r
+ closeable_type const,\r
+ closeable_type\r
+ >::type closeable;\r
+ \r
+ explicit inline normalized_view(range & r)\r
+ : m_reversible(r)\r
+ , m_closeable(m_reversible)\r
+ {}\r
+\r
+ typedef typename boost::range_iterator<closeable>::type iterator;\r
+ typedef typename boost::range_const_iterator<closeable>::type const_iterator;\r
+\r
+ inline const_iterator begin() const { return boost::begin(m_closeable); }\r
+ inline const_iterator end() const { return boost::end(m_closeable); }\r
+\r
+ inline iterator begin() { return boost::begin(m_closeable); }\r
+ inline iterator end() { return boost::end(m_closeable); }\r
+\r
+private:\r
+ reversible_type m_reversible;\r
+ closeable_type m_closeable;\r
+};\r
+\r
+} // namespace detail\r
+\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_NORMALIZED_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_POINTS_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_POINTS_VIEW_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+#include <boost/iterator.hpp>\r
+#include <boost/iterator/iterator_facade.hpp>\r
+#include <boost/iterator/iterator_categories.hpp>\r
+\r
+#include <boost/geometry/core/exception.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+namespace detail\r
+{\r
+\r
+// Adapts pointer, on points, to a Boost.Range\r
+template <typename Point, int MaxSize>\r
+class points_view\r
+{\r
+ // Iterates over a series of points (indicated by pointer\r
+ // to have it lightweight). Probably there is already an\r
+ // equivalent of this within Boost. If so, TODO: use that one.\r
+ // This used to be "box_iterator" and "segment_iterator".\r
+ // ALTERNATIVE: use boost:array and its iterators\r
+ struct points_iterator\r
+ : public boost::iterator_facade\r
+ <\r
+ points_iterator,\r
+ Point const,\r
+ boost::random_access_traversal_tag\r
+ >\r
+ {\r
+ // Constructor: Begin iterator\r
+ inline points_iterator(Point const* p)\r
+ : m_points(p)\r
+ , m_index(0)\r
+ {}\r
+\r
+ // Constructor: End iterator\r
+ inline points_iterator(Point const* p, bool)\r
+ : m_points(p)\r
+ , m_index(MaxSize)\r
+ {}\r
+\r
+ // Constructor: default (for Range Concept checking).\r
+ inline points_iterator()\r
+ : m_points(NULL)\r
+ , m_index(MaxSize)\r
+ {}\r
+\r
+ typedef std::ptrdiff_t difference_type;\r
+\r
+ private:\r
+ friend class boost::iterator_core_access;\r
+\r
+ inline Point const& dereference() const\r
+ {\r
+ if (m_index >= 0 && m_index < MaxSize)\r
+ {\r
+ return m_points[m_index];\r
+ }\r
+\r
+ // If it index larger (or smaller) return first point\r
+ // (assuming initialized)\r
+ return m_points[0];\r
+ }\r
+\r
+ inline bool equal(points_iterator const& other) const\r
+ {\r
+ return other.m_index == this->m_index;\r
+ }\r
+\r
+ inline void increment()\r
+ {\r
+ m_index++;\r
+ }\r
+\r
+ inline void decrement()\r
+ {\r
+ m_index--;\r
+ }\r
+\r
+ inline difference_type distance_to(points_iterator const& other) const\r
+ {\r
+ return other.m_index - this->m_index;\r
+ }\r
+\r
+ inline void advance(difference_type n)\r
+ {\r
+ m_index += n;\r
+ }\r
+\r
+ Point const* m_points;\r
+ difference_type m_index;\r
+ };\r
+\r
+public :\r
+\r
+ typedef points_iterator const_iterator;\r
+ typedef points_iterator iterator; // must be defined\r
+\r
+ const_iterator begin() const { return const_iterator(m_points); }\r
+ const_iterator end() const { return const_iterator(m_points, true); }\r
+\r
+ // It may NOT be used non-const, so commented:\r
+ //iterator begin() { return m_begin; }\r
+ //iterator end() { return m_end; }\r
+\r
+protected :\r
+\r
+ template <typename CopyPolicy>\r
+ explicit points_view(CopyPolicy const& copy)\r
+ {\r
+ copy.apply(m_points);\r
+ }\r
+\r
+private :\r
+ // Copy points here - box might define them otherwise\r
+ Point m_points[MaxSize];\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_POINTS_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_RANGE_TYPE_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_RANGE_TYPE_HPP\r
+\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/range/value_type.hpp>\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/views/box_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+#ifndef DOXYGEN_NO_DISPATCH\r
+namespace dispatch\r
+{\r
+\r
+\r
+template <typename Geometry,\r
+ typename Tag = typename tag<Geometry>::type>\r
+struct range_type\r
+{\r
+ BOOST_MPL_ASSERT_MSG\r
+ (\r
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE\r
+ , (types<Geometry>)\r
+ );\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct range_type<Geometry, ring_tag>\r
+{\r
+ typedef Geometry type;\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct range_type<Geometry, linestring_tag>\r
+{\r
+ typedef Geometry type;\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct range_type<Geometry, polygon_tag>\r
+{\r
+ typedef typename ring_type<Geometry>::type type;\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct range_type<Geometry, box_tag>\r
+{\r
+ typedef box_view<Geometry> type;\r
+};\r
+\r
+\r
+// multi-point acts itself as a range\r
+template <typename Geometry>\r
+struct range_type<Geometry, multi_point_tag>\r
+{\r
+ typedef Geometry type;\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct range_type<Geometry, multi_linestring_tag>\r
+{\r
+ typedef typename boost::range_value<Geometry>::type type;\r
+};\r
+\r
+\r
+template <typename Geometry>\r
+struct range_type<Geometry, multi_polygon_tag>\r
+{\r
+ // Call its single-version\r
+ typedef typename dispatch::range_type\r
+ <\r
+ typename boost::range_value<Geometry>::type\r
+ >::type type;\r
+};\r
+\r
+\r
+} // namespace dispatch\r
+#endif // DOXYGEN_NO_DISPATCH\r
+\r
+// Will probably be replaced by the more generic "view_as", therefore in detail\r
+namespace detail\r
+{\r
+\r
+\r
+/*!\r
+\brief Meta-function defining a type which is a boost-range.\r
+\details\r
+- For linestrings and rings, it defines the type itself.\r
+- For polygons it defines the ring type.\r
+- For multi-points, it defines the type itself\r
+- For multi-polygons and multi-linestrings, it defines the single-version\r
+ (so in the end the linestring and ring-type-of-multi-polygon)\r
+\ingroup iterators\r
+*/\r
+template <typename Geometry>\r
+struct range_type\r
+{\r
+ typedef typename dispatch::range_type\r
+ <\r
+ Geometry\r
+ >::type type;\r
+};\r
+\r
+}\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_RANGE_TYPE_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2015, Oracle and/or its affiliates.\r
+\r
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle\r
+\r
+// Licensed under the Boost Software License version 1.0.\r
+// http://www.boost.org/users/license.html\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP\r
+\r
+#include <cstddef>\r
+\r
+#include <boost/mpl/assert.hpp>\r
+#include <boost/mpl/int.hpp>\r
+\r
+#include <boost/geometry/core/access.hpp>\r
+#include <boost/geometry/core/coordinate_type.hpp>\r
+#include <boost/geometry/core/coordinate_system.hpp>\r
+#include <boost/geometry/core/coordinate_dimension.hpp>\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/algorithms/not_implemented.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+#ifndef DOXYGEN_NO_DETAIL\r
+namespace detail\r
+{\r
+\r
+template\r
+<\r
+ typename Geometry,\r
+ std::size_t Dimension1 = 0,\r
+ std::size_t Dimension2 = 1,\r
+ typename Tag = typename tag<Geometry>::type\r
+>\r
+struct two_dimensional_view\r
+ : not_implemented<Tag>\r
+{};\r
+\r
+\r
+// View that enables to choose two dimensions of a point and see it as\r
+// a two-dimensional point\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct two_dimensional_view<Point, Dimension1, Dimension2, point_tag>\r
+{\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (Dimension1 < static_cast<std::size_t>(dimension<Point>::value)),\r
+ COORDINATE_DIMENSION1_IS_LARGER_THAN_POINT_DIMENSION,\r
+ (boost::mpl::int_<Dimension1>));\r
+\r
+ BOOST_MPL_ASSERT_MSG(\r
+ (Dimension2 < static_cast<std::size_t>(dimension<Point>::value)),\r
+ COORDINATE_DIMENSION2_IS_LARGER_THAN_POINT_DIMENSION,\r
+ (boost::mpl::int_<Dimension2>));\r
+\r
+ two_dimensional_view(Point& point)\r
+ : m_point(point)\r
+ {}\r
+\r
+ Point& m_point;\r
+};\r
+\r
+\r
+} // namespace detail\r
+#endif // DOXYGEN_NO_DETAIL\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+namespace traits\r
+{\r
+\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct tag\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >\r
+ >\r
+{\r
+ typedef point_tag type;\r
+};\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct coordinate_system\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >\r
+ > : coordinate_system<typename geometry::point_type<Point>::type>\r
+{};\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct coordinate_type\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >\r
+ > : coordinate_type<typename geometry::point_type<Point>::type>\r
+{};\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct dimension\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >\r
+ > : boost::mpl::int_<2>\r
+{};\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct point_type\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >\r
+ >\r
+{\r
+ typedef typename geometry::point_type<Point>::type type;\r
+};\r
+\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct access\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >,\r
+ 0\r
+ >\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+ typedef geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ > view_type;\r
+\r
+ static inline coordinate_type get(view_type const& view)\r
+ {\r
+ return geometry::get<Dimension1>(view.m_point);\r
+ }\r
+\r
+ static inline void set(view_type& view, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension1>(view.m_point, value);\r
+ }\r
+};\r
+\r
+template <typename Point, std::size_t Dimension1, std::size_t Dimension2>\r
+struct access\r
+ <\r
+ geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ >,\r
+ 1\r
+ >\r
+{\r
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;\r
+ typedef geometry::detail::two_dimensional_view\r
+ <\r
+ Point, Dimension1, Dimension2, point_tag\r
+ > view_type;\r
+\r
+ static inline coordinate_type get(view_type const& view)\r
+ {\r
+ return geometry::get<Dimension2>(view.m_point);\r
+ }\r
+\r
+ static inline void set(view_type& view, coordinate_type const& value)\r
+ {\r
+ geometry::set<Dimension2>(view.m_point, value);\r
+ }\r
+};\r
+\r
+\r
+} // namespace traits\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_TWO_DIMENSIONAL_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+// Silence warning C4512: assignment operator could not be generated\r
+#if defined(_MSC_VER)\r
+#pragma warning(push)\r
+#pragma warning(disable : 4512)\r
+#endif\r
+\r
+/*!\r
+\brief View on a range, not modifying anything\r
+\tparam Range original range\r
+\ingroup views\r
+*/\r
+template <typename Range>\r
+struct identity_view\r
+{\r
+ typedef typename boost::range_iterator<Range const>::type const_iterator;\r
+ typedef typename boost::range_iterator<Range>::type iterator;\r
+\r
+ explicit inline identity_view(Range& r)\r
+ : m_range(r)\r
+ {}\r
+\r
+ inline const_iterator begin() const { return boost::begin(m_range); }\r
+ inline const_iterator end() const { return boost::end(m_range); }\r
+\r
+ inline iterator begin() { return boost::begin(m_range); }\r
+ inline iterator end() { return boost::end(m_range); }\r
+private :\r
+ Range& m_range;\r
+};\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning(pop)\r
+#endif\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_REVERSIBLE_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_REVERSIBLE_VIEW_HPP\r
+\r
+\r
+#include <boost/version.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/range/adaptor/reversed.hpp>\r
+\r
+#include <boost/geometry/core/ring_type.hpp>\r
+#include <boost/geometry/core/tag.hpp>\r
+#include <boost/geometry/core/tags.hpp>\r
+\r
+#include <boost/geometry/views/identity_view.hpp>\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+/*!\r
+\brief Flag for iterating a reversible_view in forward or reverse direction\r
+\ingroup views\r
+*/\r
+enum iterate_direction { iterate_forward, iterate_reverse };\r
+\r
+/*!\r
+\brief View on a range, reversing direction if necessary\r
+\tparam Range original range\r
+\tparam Direction direction of iteration\r
+\ingroup views\r
+*/\r
+template <typename Range, iterate_direction Direction>\r
+struct reversible_view {};\r
+\r
+\r
+\r
+#ifndef DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+template <typename Range>\r
+struct reversible_view<Range, iterate_forward>\r
+{\r
+ typedef identity_view<Range> type;\r
+};\r
+\r
+\r
+template <typename Range>\r
+struct reversible_view<Range, iterate_reverse>\r
+{\r
+#if BOOST_VERSION > 104500\r
+ typedef boost::reversed_range<Range> type;\r
+#else\r
+ // For older versions of Boost\r
+ typedef boost::range_detail::reverse_range<Range> type;\r
+#endif\r
+};\r
+\r
+#endif // DOXYGEN_NO_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_REVERSIBLE_VIEW_HPP\r
--- /dev/null
+// Boost.Geometry (aka GGL, Generic Geometry Library)\r
+\r
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.\r
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.\r
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.\r
+\r
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library\r
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.\r
+\r
+// Use, modification and distribution is subject to the Boost Software License,\r
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at\r
+// http://www.boost.org/LICENSE_1_0.txt)\r
+\r
+#ifndef BOOST_GEOMETRY_VIEWS_SEGMENT_VIEW_HPP\r
+#define BOOST_GEOMETRY_VIEWS_SEGMENT_VIEW_HPP\r
+\r
+\r
+#include <boost/range.hpp>\r
+\r
+#include <boost/geometry/core/point_type.hpp>\r
+#include <boost/geometry/views/detail/points_view.hpp>\r
+#include <boost/geometry/algorithms/assign.hpp>\r
+\r
+\r
+namespace boost { namespace geometry\r
+{\r
+\r
+\r
+/*!\r
+\brief Makes a segment behave like a linestring or a range\r
+\details Adapts a segment to the Boost.Range concept, enabling the user to\r
+ iterate the two segment points. The segment_view is registered as a LineString Concept\r
+\tparam Segment \tparam_geometry{Segment}\r
+\ingroup views\r
+\r
+\qbk{before.synopsis,\r
+[heading Model of]\r
+[link geometry.reference.concepts.concept_linestring LineString Concept]\r
+}\r
+\r
+\qbk{[include reference/views/segment_view.qbk]}\r
+\r
+*/\r
+template <typename Segment>\r
+struct segment_view\r
+ : public detail::points_view\r
+ <\r
+ typename geometry::point_type<Segment>::type,\r
+ 2\r
+ >\r
+{\r
+ typedef typename geometry::point_type<Segment>::type point_type;\r
+\r
+ /// Constructor accepting the segment to adapt\r
+ explicit segment_view(Segment const& segment)\r
+ : detail::points_view<point_type, 2>(copy_policy(segment))\r
+ {}\r
+\r
+private :\r
+\r
+ class copy_policy\r
+ {\r
+ public :\r
+ inline copy_policy(Segment const& segment)\r
+ : m_segment(segment)\r
+ {}\r
+\r
+ inline void apply(point_type* points) const\r
+ {\r
+ geometry::detail::assign_point_from_index<0>(m_segment, points[0]);\r
+ geometry::detail::assign_point_from_index<1>(m_segment, points[1]);\r
+ }\r
+ private :\r
+ Segment const& m_segment;\r
+ };\r
+\r
+};\r
+\r
+\r
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+// All segment ranges can be handled as linestrings\r
+namespace traits\r
+{\r
+\r
+template<typename Segment>\r
+struct tag<segment_view<Segment> >\r
+{\r
+ typedef linestring_tag type;\r
+};\r
+\r
+}\r
+\r
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS\r
+\r
+\r
+}} // namespace boost::geometry\r
+\r
+\r
+#endif // BOOST_GEOMETRY_VIEWS_SEGMENT_VIEW_HPP\r