From: Luca Heltai Date: Mon, 23 Jul 2018 07:29:20 +0000 (+0200) Subject: Added boost/geometry. X-Git-Tag: v9.1.0-rc1~895^2~4 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=20414a01b9d6e9797a8784d38377cfebc552fca1;p=dealii.git Added boost/geometry. --- diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/append.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/append.hpp new file mode 100755 index 0000000000..086303aadc --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/append.hpp @@ -0,0 +1,370 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP +#define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace append +{ + +template +struct append_no_action +{ + static inline void apply(Geometry& , Point const& , + int = 0, int = 0) + { + } +}; + +template +struct append_point +{ + static inline void apply(Geometry& geometry, Point const& point, + int = 0, int = 0) + { + typename geometry::point_type::type copy; + geometry::detail::conversion::convert_point_to_point(point, copy); + traits::push_back::apply(geometry, copy); + } +}; + + +template +struct append_range +{ + typedef typename boost::range_value::type point_type; + + static inline void apply(Geometry& geometry, Range const& range, + int = 0, int = 0) + { + for (typename boost::range_iterator::type + it = boost::begin(range); + it != boost::end(range); + ++it) + { + append_point::apply(geometry, *it); + } + } +}; + + +template +struct point_to_polygon +{ + typedef typename ring_type::type ring_type; + + static inline void apply(Polygon& polygon, Point const& point, + int ring_index, int = 0) + { + if (ring_index == -1) + { + append_point::apply( + exterior_ring(polygon), point); + } + else if (ring_index < int(num_interior_rings(polygon))) + { + append_point::apply( + range::at(interior_rings(polygon), ring_index), point); + } + } +}; + + +template +struct range_to_polygon +{ + typedef typename ring_type::type ring_type; + + static inline void apply(Polygon& polygon, Range const& range, + int ring_index, int = 0) + { + if (ring_index == -1) + { + append_range::apply( + exterior_ring(polygon), range); + } + else if (ring_index < int(num_interior_rings(polygon))) + { + append_range::apply( + range::at(interior_rings(polygon), ring_index), range); + } + } +}; + + +}} // namespace detail::append +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +namespace splitted_dispatch +{ + +template +struct append_point + : detail::append::append_no_action +{}; + +template +struct append_point + : detail::append::append_point +{}; + +template +struct append_point + : detail::append::append_point +{}; + + +template +struct append_point + : detail::append::point_to_polygon +{}; + + +template +struct append_range + : detail::append::append_no_action +{}; + +template +struct append_range + : detail::append::append_range +{}; + +template +struct append_range + : detail::append::append_range +{}; + + +template +struct append_range + : detail::append::range_to_polygon +{}; + +} // namespace splitted_dispatch + + +// Default: append a range (or linestring or ring or whatever) to any geometry +template +< + typename Geometry, typename RangeOrPoint, + typename TagRangeOrPoint = typename tag::type +> +struct append + : splitted_dispatch::append_range::type, Geometry, RangeOrPoint> +{}; + +// Specialization for point to append a point to any geometry +template +struct append + : splitted_dispatch::append_point::type, Geometry, RangeOrPoint> +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace append +{ + +template +struct append_to_multigeometry +{ + static inline void apply(MultiGeometry& multigeometry, + RangeOrPoint const& range_or_point, + int ring_index, int multi_index) + { + + dispatch::append + < + typename boost::range_value::type, + RangeOrPoint + >::apply(range::at(multigeometry, multi_index), range_or_point, ring_index); + } +}; + +}} // namespace detail::append +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +namespace splitted_dispatch +{ + +template +struct append_point + : detail::append::append_point +{}; + +template +struct append_range + : detail::append::append_range +{}; + +template +struct append_point + : detail::append::append_to_multigeometry +{}; + +template +struct append_range + : detail::append::append_to_multigeometry +{}; + +template +struct append_point + : detail::append::append_to_multigeometry +{}; + +template +struct append_range + : detail::append::append_to_multigeometry +{}; + +} // namespace splitted_dispatch + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct append +{ + template + static inline void apply(Geometry& geometry, + RangeOrPoint const& range_or_point, + int ring_index, + int multi_index) + { + concepts::check(); + dispatch::append::apply(geometry, + range_or_point, + ring_index, + multi_index); + } +}; + + +template +struct append > +{ + template + struct visitor: boost::static_visitor + { + RangeOrPoint const& m_range_or_point; + int m_ring_index; + int m_multi_index; + + visitor(RangeOrPoint const& range_or_point, + int ring_index, + int multi_index): + m_range_or_point(range_or_point), + m_ring_index(ring_index), + m_multi_index(multi_index) + {} + + template + void operator()(Geometry& geometry) const + { + append::apply(geometry, + m_range_or_point, + m_ring_index, + m_multi_index); + } + }; + + template + static inline void apply(boost::variant& variant_geometry, + RangeOrPoint const& range_or_point, + int ring_index, + int multi_index) + { + boost::apply_visitor( + visitor( + range_or_point, + ring_index, + multi_index + ), + variant_geometry + ); + } +}; + +} // namespace resolve_variant; + + +/*! +\brief Appends one or more points to a linestring, ring, polygon, multi-geometry +\ingroup append +\tparam Geometry \tparam_geometry +\tparam RangeOrPoint Either a range or a point, fullfilling Boost.Range concept or Boost.Geometry Point Concept +\param geometry \param_geometry +\param range_or_point The point or range to add +\param ring_index The index of the ring in case of a polygon: + exterior ring (-1, the default) or interior ring index +\param multi_index The index of the geometry to which the points are appended + +\qbk{[include reference/algorithms/append.qbk]} +} + */ +template +inline void append(Geometry& geometry, RangeOrPoint const& range_or_point, + int ring_index = -1, int multi_index = 0) +{ + resolve_variant::append + ::apply(geometry, range_or_point, ring_index, multi_index); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/area.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/area.hpp new file mode 100755 index 0000000000..3daeacba34 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/area.hpp @@ -0,0 +1,324 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP +#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +// #include +#include + +#include +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace area +{ + +struct box_area +{ + template + static inline typename coordinate_type::type + apply(Box const& box, Strategy const&) + { + // Currently only works for 2D Cartesian boxes + assert_dimension(); + + return (get(box) - get(box)) + * (get(box) - get(box)); + } +}; + + +template +< + iterate_direction Direction, + closure_selector Closure +> +struct ring_area +{ + template + static inline typename Strategy::return_type + apply(Ring const& ring, Strategy const& strategy) + { + BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy) ); + assert_dimension(); + + // Ignore warning (because using static method sometimes) on strategy + boost::ignore_unused_variable_warning(strategy); + + // An open ring has at least three points, + // A closed ring has at least four points, + // if not, there is no (zero) area + if (boost::size(ring) + < core_detail::closure::minimum_ring_size::value) + { + return typename Strategy::return_type(); + } + + typedef typename reversible_view::type rview_type; + typedef typename closeable_view + < + rview_type const, Closure + >::type view_type; + typedef typename boost::range_iterator::type iterator_type; + + rview_type rview(ring); + view_type view(rview); + typename Strategy::state_type state; + iterator_type it = boost::begin(view); + iterator_type end = boost::end(view); + + for (iterator_type previous = it++; + it != end; + ++previous, ++it) + { + strategy.apply(*previous, *it, state); + } + + return strategy.result(state); + } +}; + + +}} // namespace detail::area + + +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct area : detail::calculate_null +{ + template + static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy) + { + return calculate_null::apply(geometry, strategy); + } +}; + + +template +struct area : detail::area::box_area +{}; + + +template +struct area + : detail::area::ring_area + < + order_as_direction::value>::value, + geometry::closure::value + > +{}; + + +template +struct area : detail::calculate_polygon_sum +{ + template + static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy) + { + return calculate_polygon_sum::apply< + typename Strategy::return_type, + detail::area::ring_area + < + order_as_direction::value>::value, + geometry::closure::value + > + >(polygon, strategy); + } +}; + + +template +struct area : detail::multi_sum +{ + template + static inline typename Strategy::return_type + apply(MultiGeometry const& multi, Strategy const& strategy) + { + return multi_sum::apply + < + typename Strategy::return_type, + area::type> + >(multi, strategy); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct area +{ + template + static inline typename Strategy::return_type apply(Geometry const& geometry, + Strategy const& strategy) + { + return dispatch::area::apply(geometry, strategy); + } +}; + +template +struct area > +{ + template + struct visitor: boost::static_visitor + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy): m_strategy(strategy) {} + + template + typename Strategy::return_type operator()(Geometry const& geometry) const + { + return area::apply(geometry, m_strategy); + } + }; + + template + static inline typename Strategy::return_type + apply(boost::variant const& geometry, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(strategy), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc{area} +\ingroup area +\details \details_calc{area}. \details_default_strategy + +The area algorithm calculates the surface area of all geometries having a surface, namely +box, polygon, ring, multipolygon. The units are the square of the units used for the points +defining the surface. If subject geometry is defined in meters, then area is calculated +in square meters. + +The area calculation can be done in all three common coordinate systems, Cartesian, Spherical +and Geographic as well. + +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\return \return_calc{area} + +\qbk{[include reference/algorithms/area.qbk]} +\qbk{[heading Examples]} +\qbk{[area] [area_output]} +*/ +template +inline typename default_area_result::type area(Geometry const& geometry) +{ + concepts::check(); + + // TODO put this into a resolve_strategy stage + // (and take the return type from resolve_variant) + typedef typename point_type::type point_type; + typedef typename strategy::area::services::default_strategy + < + typename cs_tag::type, + point_type + >::type strategy_type; + + // detail::throw_on_empty_input(geometry); + + return resolve_variant::area::apply(geometry, strategy_type()); +} + +/*! +\brief \brief_calc{area} \brief_strategy +\ingroup area +\details \details_calc{area} \brief_strategy. \details_strategy_reasons +\tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{Area} +\param geometry \param_geometry +\param strategy \param_strategy{area} +\return \return_calc{area} + +\qbk{distinguish,with strategy} + +\qbk{ +[include reference/algorithms/area.qbk] + +[heading Example] +[area_with_strategy] +[area_with_strategy_output] + +[heading Available Strategies] +\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)] +\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)] +} + */ +template +inline typename Strategy::return_type area( + Geometry const& geometry, Strategy const& strategy) +{ + concepts::check(); + + // detail::throw_on_empty_input(geometry); + + return resolve_variant::area::apply(geometry, strategy); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/assign.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/assign.hpp new file mode 100755 index 0000000000..6ec0d00b97 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/assign.hpp @@ -0,0 +1,379 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Samuel Debionne, Grenoble, France. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP +#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP + + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +/*! +\brief Assign a range of points to a linestring, ring or polygon +\note The point-type of the range might be different from the point-type of the geometry +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Range \tparam_range_point +\param geometry \param_geometry +\param range \param_range_point + +\qbk{ +[heading Notes] +[note Assign automatically clears the geometry before assigning (use append if you don't want that)] +[heading Example] +[assign_points] [assign_points_output] + +[heading See also] +\* [link geometry.reference.algorithms.append append] +} + */ +template +inline void assign_points(Geometry& geometry, Range const& range) +{ + concepts::check(); + + clear(geometry); + geometry::append(geometry, range, -1, 0); +} + + +/*! +\brief assign to a box inverse infinite +\details The assign_inverse function initialize a 2D or 3D box with large coordinates, the +min corner is very large, the max corner is very small. This is a convenient starting point to +collect the minimum bounding box of a geometry. +\ingroup assign +\tparam Geometry \tparam_geometry +\param geometry \param_geometry + +\qbk{ +[heading Example] +[assign_inverse] [assign_inverse_output] + +[heading See also] +\* [link geometry.reference.algorithms.make.make_inverse make_inverse] +} + */ +template +inline void assign_inverse(Geometry& geometry) +{ + concepts::check(); + + dispatch::assign_inverse + < + typename tag::type, + Geometry + >::apply(geometry); +} + +/*! +\brief assign zero values to a box, point +\ingroup assign +\details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero +\tparam Geometry \tparam_geometry +\param geometry \param_geometry + + */ +template +inline void assign_zero(Geometry& geometry) +{ + concepts::check(); + + dispatch::assign_zero + < + typename tag::type, + Geometry + >::apply(geometry); +} + +/*! +\brief Assign two coordinates to a geometry (usually a 2D point) +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Type \tparam_numeric to specify the coordinates +\param geometry \param_geometry +\param c1 \param_x +\param c2 \param_y + +\qbk{distinguish, 2 coordinate values} +\qbk{ +[heading Example] +[assign_2d_point] [assign_2d_point_output] + +[heading See also] +\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make] +} + */ +template +inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2) +{ + concepts::check(); + + dispatch::assign + < + typename tag::type, + Geometry, + geometry::dimension::type::value + >::apply(geometry, c1, c2); +} + +/*! +\brief Assign three values to a geometry (usually a 3D point) +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Type \tparam_numeric to specify the coordinates +\param geometry \param_geometry +\param c1 \param_x +\param c2 \param_y +\param c3 \param_z + +\qbk{distinguish, 3 coordinate values} +\qbk{ +[heading Example] +[assign_3d_point] [assign_3d_point_output] + +[heading See also] +\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make] +} + */ +template +inline void assign_values(Geometry& geometry, + Type const& c1, Type const& c2, Type const& c3) +{ + concepts::check(); + + dispatch::assign + < + typename tag::type, + Geometry, + geometry::dimension::type::value + >::apply(geometry, c1, c2, c3); +} + +/*! +\brief Assign four values to a geometry (usually a box or segment) +\ingroup assign +\tparam Geometry \tparam_geometry +\tparam Type \tparam_numeric to specify the coordinates +\param geometry \param_geometry +\param c1 First coordinate (usually x1) +\param c2 Second coordinate (usually y1) +\param c3 Third coordinate (usually x2) +\param c4 Fourth coordinate (usually y2) + +\qbk{distinguish, 4 coordinate values} + */ +template +inline void assign_values(Geometry& geometry, + Type const& c1, Type const& c2, Type const& c3, Type const& c4) +{ + concepts::check(); + + dispatch::assign + < + typename tag::type, + Geometry, + geometry::dimension::type::value + >::apply(geometry, c1, c2, c3, c4); +} + + + +namespace resolve_variant +{ + +template +struct assign +{ + static inline void + apply(Geometry1& geometry1, const Geometry2& geometry2) + { + concepts::check(); + concepts::check(); + concepts::check_concepts_and_equal_dimensions(); + + static bool const same_point_order + = point_order::value == point_order::value; + BOOST_MPL_ASSERT_MSG + ( + (same_point_order), + ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER, + (types) + ); + static bool const same_closure + = closure::value == closure::value; + BOOST_MPL_ASSERT_MSG + ( + (same_closure), + ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE, + (types) + ); + + dispatch::convert::apply(geometry2, geometry1); + } +}; + + +template +struct assign, Geometry2> +{ + struct visitor: static_visitor + { + Geometry2 const& m_geometry2; + + visitor(Geometry2 const& geometry2) + : m_geometry2(geometry2) + {} + + template + result_type operator()(Geometry1& geometry1) const + { + return assign + < + Geometry1, + Geometry2 + >::apply + (geometry1, m_geometry2); + } + }; + + static inline void + apply(variant& geometry1, + Geometry2 const& geometry2) + { + return boost::apply_visitor(visitor(geometry2), geometry1); + } +}; + + +template +struct assign > +{ + struct visitor: static_visitor + { + Geometry1& m_geometry1; + + visitor(Geometry1 const& geometry1) + : m_geometry1(geometry1) + {} + + template + result_type operator()(Geometry2 const& geometry2) const + { + return assign + < + Geometry1, + Geometry2 + >::apply + (m_geometry1, geometry2); + } + }; + + static inline void + apply(Geometry1& geometry1, + variant const& geometry2) + { + return boost::apply_visitor(visitor(geometry1), geometry2); + } +}; + + +template +struct assign, variant > +{ + struct visitor: static_visitor + { + template + result_type operator()( + Geometry1& geometry1, + Geometry2 const& geometry2) const + { + return assign + < + Geometry1, + Geometry2 + >::apply + (geometry1, geometry2); + } + }; + + static inline void + apply(variant& geometry1, + variant const& geometry2) + { + return boost::apply_visitor(visitor(), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief Assigns one geometry to another geometry +\details The assign algorithm assigns one geometry, e.g. a BOX, to another +geometry, e.g. a RING. This only works if it is possible and applicable. +\ingroup assign +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry (target) +\param geometry2 \param_geometry (source) + +\qbk{ +[heading Example] +[assign] [assign_output] + +[heading See also] +\* [link geometry.reference.algorithms.convert convert] +} + */ +template +inline void assign(Geometry1& geometry1, Geometry2 const& geometry2) +{ + resolve_variant::assign::apply(geometry1, geometry2); +} + + +}} // namespace boost::geometry + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/buffer.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/buffer.hpp new file mode 100755 index 0000000000..a963c9b43b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/buffer.hpp @@ -0,0 +1,292 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP + +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +template +struct box_loop +{ + typedef typename coordinate_type::type coordinate_type; + + static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out) + { + coordinate_type d = distance; + set(box_out, get(box_in) + d); + box_loop::apply(box_in, distance, box_out); + } +}; + +template +struct box_loop +{ + static inline void apply(BoxIn const&, T const&, BoxOut&) {} +}; + +// Extends a box with the same amount in all directions +template +inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out) +{ + assert_dimension_equal(); + + static const std::size_t N = dimension::value; + + box_loop::apply(box_in, -distance, box_out); + box_loop::apply(box_in, distance, box_out); +} + + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Input, + typename Output, + typename TagIn = typename tag::type, + typename TagOut = typename tag::type +> +struct buffer: not_implemented +{}; + + +template +struct buffer +{ + template + static inline void apply(BoxIn const& box_in, Distance const& distance, + Distance const& , BoxOut& box_out) + { + detail::buffer::buffer_box(box_in, distance, box_out); + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct buffer +{ + template + static inline void apply(Geometry const& geometry, + Distance const& distance, + Distance const& chord_length, + GeometryOut& out) + { + dispatch::buffer::apply(geometry, distance, chord_length, out); + } +}; + +template +struct buffer > +{ + template + struct visitor: boost::static_visitor + { + Distance const& m_distance; + Distance const& m_chord_length; + GeometryOut& m_out; + + visitor(Distance const& distance, + Distance const& chord_length, + GeometryOut& out) + : m_distance(distance), + m_chord_length(chord_length), + m_out(out) + {} + + template + void operator()(Geometry const& geometry) const + { + buffer::apply(geometry, m_distance, m_chord_length, m_out); + } + }; + + template + static inline void apply( + boost::variant const& geometry, + Distance const& distance, + Distance const& chord_length, + GeometryOut& out + ) + { + boost::apply_visitor(visitor(distance, chord_length, out), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc{buffer} +\ingroup buffer +\details \details_calc{buffer, \det_buffer}. +\tparam Input \tparam_geometry +\tparam Output \tparam_geometry +\tparam Distance \tparam_numeric +\param geometry_in \param_geometry +\param geometry_out \param_geometry +\param distance The distance to be used for the buffer +\param chord_length (optional) The length of the chord's in the generated arcs around points or bends + +\qbk{[include reference/algorithms/buffer.qbk]} + */ +template +inline void buffer(Input const& geometry_in, Output& geometry_out, + Distance const& distance, Distance const& chord_length = -1) +{ + concepts::check(); + concepts::check(); + + resolve_variant::buffer::apply(geometry_in, distance, chord_length, geometry_out); +} + +/*! +\brief \brief_calc{buffer} +\ingroup buffer +\details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}. +\tparam Input \tparam_geometry +\tparam Output \tparam_geometry +\tparam Distance \tparam_numeric +\param geometry \param_geometry +\param distance The distance to be used for the buffer +\param chord_length (optional) The length of the chord's in the generated arcs + around points or bends (RESERVED, NOT YET USED) +\return \return_calc{buffer} + */ +template +Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1) +{ + concepts::check(); + concepts::check(); + + Output geometry_out; + + resolve_variant::buffer::apply(geometry, distance, chord_length, geometry_out); + + return geometry_out; +} + +/*! +\brief \brief_calc{buffer} +\ingroup buffer +\details \details_calc{buffer, \det_buffer}. +\tparam GeometryIn \tparam_geometry +\tparam MultiPolygon \tparam_geometry{MultiPolygon} +\tparam DistanceStrategy A strategy defining distance (or radius) +\tparam SideStrategy A strategy defining creation along sides +\tparam JoinStrategy A strategy defining creation around convex corners +\tparam EndStrategy A strategy defining creation at linestring ends +\tparam PointStrategy A strategy defining creation around points +\param geometry_in \param_geometry +\param geometry_out output multi polygon (or std:: collection of polygons), + will contain a buffered version of the input geometry +\param distance_strategy The distance strategy to be used +\param side_strategy The side strategy to be used +\param join_strategy The join strategy to be used +\param end_strategy The end strategy to be used +\param point_strategy The point strategy to be used + +\qbk{distinguish,with strategies} +\qbk{[include reference/algorithms/buffer_with_strategies.qbk]} + */ +template +< + typename GeometryIn, + typename MultiPolygon, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy +> +inline void buffer(GeometryIn const& geometry_in, + MultiPolygon& geometry_out, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy) +{ + typedef typename boost::range_value::type polygon_type; + concepts::check(); + concepts::check(); + + typedef typename point_type::type point_type; + typedef typename rescale_policy_type::type rescale_policy_type; + + geometry_out.clear(); + + if (geometry::is_empty(geometry_in)) + { + // Then output geometry is kept empty as well + return; + } + + model::box box; + geometry::envelope(geometry_in, box); + geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy)); + + rescale_policy_type rescale_policy + = boost::geometry::get_rescale_policy(box); + + detail::buffer::buffer_inserter(geometry_in, range::back_inserter(geometry_out), + distance_strategy, + side_strategy, + join_strategy, + end_strategy, + point_strategy, + rescale_policy); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/centroid.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/centroid.hpp new file mode 100755 index 0000000000..130bc0a1ef --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/centroid.hpp @@ -0,0 +1,680 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP + + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW) + +/*! +\brief Centroid Exception +\ingroup centroid +\details The centroid_exception is thrown if the free centroid function is called with + geometries for which the centroid cannot be calculated. For example: a linestring + without points, a polygon without points, an empty multi-geometry. +\qbk{ +[heading See also] +\* [link geometry.reference.algorithms.centroid the centroid function] +} + + */ +class centroid_exception : public geometry::exception +{ +public: + + /*! + \brief The default constructor + */ + inline centroid_exception() {} + + /*! + \brief Returns the explanatory string. + \return Pointer to a null-terminated string with explanatory information. + */ + virtual char const* what() const throw() + { + return "Boost.Geometry Centroid calculation exception"; + } +}; + +#endif + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace centroid +{ + +struct centroid_point +{ + template + static inline void apply(Point const& point, PointCentroid& centroid, + Strategy const&) + { + geometry::convert(point, centroid); + } +}; + +template +< + typename Indexed, + typename Point, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::type::value +> +struct centroid_indexed_calculator +{ + typedef typename select_coordinate_type + < + Indexed, Point + >::type coordinate_type; + static inline void apply(Indexed const& indexed, Point& centroid) + { + coordinate_type const c1 = get(indexed); + coordinate_type const c2 = get(indexed); + coordinate_type m = c1 + c2; + coordinate_type const two = 2; + m /= two; + + set(centroid, m); + + centroid_indexed_calculator + < + Indexed, Point, Dimension + 1 + >::apply(indexed, centroid); + } +}; + + +template +struct centroid_indexed_calculator +{ + static inline void apply(Indexed const& , Point& ) + { + } +}; + + +struct centroid_indexed +{ + template + static inline void apply(Indexed const& indexed, Point& centroid, + Strategy const&) + { + centroid_indexed_calculator + < + Indexed, Point + >::apply(indexed, centroid); + } +}; + + +// There is one thing where centroid is different from e.g. within. +// If the ring has only one point, it might make sense that +// that point is the centroid. +template +inline bool range_ok(Range const& range, Point& centroid) +{ + std::size_t const n = boost::size(range); + if (n > 1) + { + return true; + } + else if (n <= 0) + { +#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW) + throw centroid_exception(); +#else + return false; +#endif + } + else // if (n == 1) + { + // Take over the first point in a "coordinate neutral way" + geometry::convert(*boost::begin(range), centroid); + return false; + } + //return true; // unreachable +} + +/*! + \brief Calculate the centroid of a Ring or a Linestring. +*/ +template +struct centroid_range_state +{ + template + static inline void apply(Ring const& ring, + PointTransformer const& transformer, + Strategy const& strategy, + typename Strategy::state_type& state) + { + boost::ignore_unused(strategy); + + typedef typename geometry::point_type::type point_type; + typedef typename closeable_view::type view_type; + + typedef typename boost::range_iterator::type iterator_type; + + view_type view(ring); + iterator_type it = boost::begin(view); + iterator_type end = boost::end(view); + + if (it != end) + { + typename PointTransformer::result_type + previous_pt = transformer.apply(*it); + + for ( ++it ; it != end ; ++it) + { + typename PointTransformer::result_type + pt = transformer.apply(*it); + + strategy.apply(static_cast(previous_pt), + static_cast(pt), + state); + + previous_pt = pt; + } + } + } +}; + +template +struct centroid_range +{ + template + static inline bool apply(Range const& range, Point& centroid, + Strategy const& strategy) + { + if (range_ok(range, centroid)) + { + // prepare translation transformer + translating_transformer transformer(*boost::begin(range)); + + typename Strategy::state_type state; + centroid_range_state::apply(range, transformer, + strategy, state); + + if ( strategy.result(state, centroid) ) + { + // translate the result back + transformer.apply_reverse(centroid); + return true; + } + } + + return false; + } +}; + + +/*! + \brief Centroid of a polygon. + \note Because outer ring is clockwise, inners are counter clockwise, + triangle approach is OK and works for polygons with rings. +*/ +struct centroid_polygon_state +{ + template + static inline void apply(Polygon const& poly, + PointTransformer const& transformer, + Strategy const& strategy, + typename Strategy::state_type& state) + { + typedef typename ring_type::type ring_type; + typedef centroid_range_state::value> per_ring; + + per_ring::apply(exterior_ring(poly), transformer, strategy, state); + + typename interior_return_type::type + rings = interior_rings(poly); + + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + per_ring::apply(*it, transformer, strategy, state); + } + } +}; + +struct centroid_polygon +{ + template + static inline bool apply(Polygon const& poly, Point& centroid, + Strategy const& strategy) + { + if (range_ok(exterior_ring(poly), centroid)) + { + // prepare translation transformer + translating_transformer + transformer(*boost::begin(exterior_ring(poly))); + + typename Strategy::state_type state; + centroid_polygon_state::apply(poly, transformer, strategy, state); + + if ( strategy.result(state, centroid) ) + { + // translate the result back + transformer.apply_reverse(centroid); + return true; + } + } + + return false; + } +}; + + +/*! + \brief Building block of a multi-point, to be used as Policy in the + more generec centroid_multi +*/ +struct centroid_multi_point_state +{ + template + static inline void apply(Point const& point, + PointTransformer const& transformer, + Strategy const& strategy, + typename Strategy::state_type& state) + { + boost::ignore_unused(strategy); + strategy.apply(static_cast(transformer.apply(point)), + state); + } +}; + + +/*! + \brief Generic implementation which calls a policy to calculate the + centroid of the total of its single-geometries + \details The Policy is, in general, the single-version, with state. So + detail::centroid::centroid_polygon_state is used as a policy for this + detail::centroid::centroid_multi + +*/ +template +struct centroid_multi +{ + template + static inline bool apply(Multi const& multi, + Point& centroid, + Strategy const& strategy) + { +#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW) + // If there is nothing in any of the ranges, it is not possible + // to calculate the centroid + if (geometry::is_empty(multi)) + { + throw centroid_exception(); + } +#endif + + // prepare translation transformer + translating_transformer transformer(multi); + + typename Strategy::state_type state; + + for (typename boost::range_iterator::type + it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + Policy::apply(*it, transformer, strategy, state); + } + + if ( strategy.result(state, centroid) ) + { + // translate the result back + transformer.apply_reverse(centroid); + return true; + } + + return false; + } +}; + + +template +struct centroid_linear_areal +{ + template + static inline void apply(Geometry const& geom, + Point& centroid, + Strategy const& strategy) + { + if ( ! Algorithm::apply(geom, centroid, strategy) ) + { + geometry::point_on_border(centroid, geom); + } + } +}; + + +}} // namespace detail::centroid +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct centroid: not_implemented +{}; + +template +struct centroid + : detail::centroid::centroid_point +{}; + +template +struct centroid + : detail::centroid::centroid_indexed +{}; + +template +struct centroid + : detail::centroid::centroid_indexed +{}; + +template +struct centroid + : detail::centroid::centroid_linear_areal + < + detail::centroid::centroid_range::value> + > +{}; + +template +struct centroid + : detail::centroid::centroid_linear_areal + < + detail::centroid::centroid_range + > +{}; + +template +struct centroid + : detail::centroid::centroid_linear_areal + < + detail::centroid::centroid_polygon + > +{}; + +template +struct centroid + : detail::centroid::centroid_linear_areal + < + detail::centroid::centroid_multi + < + detail::centroid::centroid_range_state + > + > +{}; + +template +struct centroid + : detail::centroid::centroid_linear_areal + < + detail::centroid::centroid_multi + < + detail::centroid::centroid_polygon_state + > + > +{}; + +template +struct centroid + : detail::centroid::centroid_multi + < + detail::centroid::centroid_multi_point_state + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy { + +template +struct centroid +{ + template + static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy) + { + dispatch::centroid::apply(geometry, out, strategy); + } + + template + static inline void apply(Geometry const& geometry, Point& out, default_strategy) + { + typedef typename strategy::centroid::services::default_strategy + < + typename cs_tag::type, + typename tag_cast + < + typename tag::type, + pointlike_tag, + linear_tag, + areal_tag + >::type, + dimension::type::value, + Point, + Geometry + >::type strategy_type; + + dispatch::centroid::apply(geometry, out, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template +struct centroid +{ + template + static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy) + { + concepts::check_concepts_and_equal_dimensions(); + resolve_strategy::centroid::apply(geometry, out, strategy); + } +}; + +template +struct centroid > +{ + template + struct visitor: boost::static_visitor + { + Point& m_out; + Strategy const& m_strategy; + + visitor(Point& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + void operator()(Geometry const& geometry) const + { + centroid::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline void + apply(boost::variant const& geometry, + Point& out, + Strategy const& strategy) + { + boost::apply_visitor(visitor(out, strategy), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc{centroid} \brief_strategy +\ingroup centroid +\details \details_calc{centroid,geometric center (or: center of mass)}. \details_strategy_reasons +\tparam Geometry \tparam_geometry +\tparam Point \tparam_point +\tparam Strategy \tparam_strategy{Centroid} +\param geometry \param_geometry +\param c \param_point \param_set{centroid} +\param strategy \param_strategy{centroid} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/centroid.qbk]} +\qbk{[include reference/algorithms/centroid_strategies.qbk]} +} + +*/ +template +inline void centroid(Geometry const& geometry, Point& c, + Strategy const& strategy) +{ + resolve_variant::centroid::apply(geometry, c, strategy); +} + + +/*! +\brief \brief_calc{centroid} +\ingroup centroid +\details \details_calc{centroid,geometric center (or: center of mass)}. \details_default_strategy +\tparam Geometry \tparam_geometry +\tparam Point \tparam_point +\param geometry \param_geometry +\param c The calculated centroid will be assigned to this point reference + +\qbk{[include reference/algorithms/centroid.qbk]} +\qbk{ +[heading Example] +[centroid] +[centroid_output] +} + */ +template +inline void centroid(Geometry const& geometry, Point& c) +{ + geometry::centroid(geometry, c, default_strategy()); +} + + +/*! +\brief \brief_calc{centroid} +\ingroup centroid +\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. +\tparam Point \tparam_point +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\return \return_calc{centroid} + +\qbk{[include reference/algorithms/centroid.qbk]} + */ +template +inline Point return_centroid(Geometry const& geometry) +{ + Point c; + geometry::centroid(geometry, c); + return c; +} + +/*! +\brief \brief_calc{centroid} \brief_strategy +\ingroup centroid +\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. \details_strategy_reasons +\tparam Point \tparam_point +\tparam Geometry \tparam_geometry +\tparam Strategy \tparam_strategy{centroid} +\param geometry \param_geometry +\param strategy \param_strategy{centroid} +\return \return_calc{centroid} + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/centroid.qbk]} +\qbk{[include reference/algorithms/centroid_strategies.qbk]} + */ +template +inline Point return_centroid(Geometry const& geometry, Strategy const& strategy) +{ + Point c; + geometry::centroid(geometry, c, strategy); + return c; +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/clear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/clear.hpp new file mode 100755 index 0000000000..7ef06a6f25 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/clear.hpp @@ -0,0 +1,197 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace clear +{ + +template +struct collection_clear +{ + static inline void apply(Geometry& geometry) + { + traits::clear::apply(geometry); + } +}; + +template +struct polygon_clear +{ + static inline void apply(Polygon& polygon) + { + traits::clear + < + typename boost::remove_reference + < + typename traits::interior_mutable_type::type + >::type + >::apply(interior_rings(polygon)); + traits::clear + < + typename boost::remove_reference + < + typename traits::ring_mutable_type::type + >::type + >::apply(exterior_ring(polygon)); + } +}; + +template +struct no_action +{ + static inline void apply(Geometry& ) + { + } +}; + + +}} // namespace detail::clear +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry, + typename Tag = typename tag_cast::type, multi_tag>::type +> +struct clear: not_implemented +{}; + +// Point/box/segment do not have clear. So specialize to do nothing. +template +struct clear + : detail::clear::no_action +{}; + +template +struct clear + : detail::clear::no_action +{}; + +template +struct clear + : detail::clear::no_action +{}; + +template +struct clear + : detail::clear::collection_clear +{}; + +template +struct clear + : detail::clear::collection_clear +{}; + + +// Polygon can (indirectly) use std for clear +template +struct clear + : detail::clear::polygon_clear +{}; + + +template +struct clear + : detail::clear::collection_clear +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct clear +{ + static inline void apply(Geometry& geometry) + { + dispatch::clear::apply(geometry); + } +}; + +template +struct clear > +{ + struct visitor: static_visitor + { + template + inline void operator()(Geometry& geometry) const + { + clear::apply(geometry); + } + }; + + static inline void apply(variant& geometry) + { + boost::apply_visitor(visitor(), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief Clears a linestring, ring or polygon (exterior+interiors) or multi* +\details Generic function to clear a geometry. All points will be removed from the collection or collections + making up the geometry. In most cases this is equivalent to the .clear() method of a std::vector<...>. In + the case of a polygon, this clear functionality is automatically called for the exterior ring, and for the + interior ring collection. In the case of a point, boxes and segments, nothing will happen. +\ingroup clear +\tparam Geometry \tparam_geometry +\param geometry \param_geometry which will be cleared +\note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero" + +\qbk{[include reference/algorithms/clear.qbk]} +*/ +template +inline void clear(Geometry& geometry) +{ + concepts::check(); + + resolve_variant::clear::apply(geometry); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/comparable_distance.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/comparable_distance.hpp new file mode 100755 index 0000000000..d08c3d47a0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/comparable_distance.hpp @@ -0,0 +1,25 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP + +#include +#include + +#endif // BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/convert.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/convert.hpp new file mode 100755 index 0000000000..0ec6089cd1 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/convert.hpp @@ -0,0 +1,559 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP + + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +// Silence warning C4127: conditional expression is constant +// Silence warning C4512: assignment operator could not be generated +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4127 4512) +#endif + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace conversion +{ + +template +< + typename Point, + typename Box, + std::size_t Index, + std::size_t Dimension, + std::size_t DimensionCount +> +struct point_to_box +{ + static inline void apply(Point const& point, Box& box) + { + typedef typename coordinate_type::type coordinate_type; + + set(box, + boost::numeric_cast(get(point))); + point_to_box + < + Point, Box, + Index, Dimension + 1, DimensionCount + >::apply(point, box); + } +}; + + +template +< + typename Point, + typename Box, + std::size_t Index, + std::size_t DimensionCount +> +struct point_to_box +{ + static inline void apply(Point const& , Box& ) + {} +}; + +template +struct box_to_range +{ + static inline void apply(Box const& box, Range& range) + { + traits::resize::apply(range, Close ? 5 : 4); + assign_box_corners_oriented(box, range); + if (Close) + { + range::at(range, 4) = range::at(range, 0); + } + } +}; + +template +struct segment_to_range +{ + static inline void apply(Segment const& segment, Range& range) + { + traits::resize::apply(range, 2); + + typename boost::range_iterator::type it = boost::begin(range); + + assign_point_from_index<0>(segment, *it); + ++it; + assign_point_from_index<1>(segment, *it); + } +}; + +template +< + typename Range1, + typename Range2, + bool Reverse = false +> +struct range_to_range +{ + typedef typename reversible_view + < + Range1 const, + Reverse ? iterate_reverse : iterate_forward + >::type rview_type; + typedef typename closeable_view + < + rview_type const, + geometry::closure::value + >::type view_type; + + static inline void apply(Range1 const& source, Range2& destination) + { + geometry::clear(destination); + + rview_type rview(source); + + // We consider input always as closed, and skip last + // point for open output. + view_type view(rview); + + typedef typename boost::range_size::type size_type; + size_type n = boost::size(view); + if (geometry::closure::value == geometry::open) + { + n--; + } + + // If size == 0 && geometry::open <=> n = numeric_limits::max() + // but ok, sice below it == end() + + size_type i = 0; + for (typename boost::range_iterator::type it + = boost::begin(view); + it != boost::end(view) && i < n; + ++it, ++i) + { + geometry::append(destination, *it); + } + } +}; + +template +struct polygon_to_polygon +{ + typedef range_to_range + < + typename geometry::ring_type::type, + typename geometry::ring_type::type, + geometry::point_order::value + != geometry::point_order::value + > per_ring; + + static inline void apply(Polygon1 const& source, Polygon2& destination) + { + // Clearing managed per ring, and in the resizing of interior rings + + per_ring::apply(geometry::exterior_ring(source), + geometry::exterior_ring(destination)); + + // Container should be resizeable + traits::resize + < + typename boost::remove_reference + < + typename traits::interior_mutable_type::type + >::type + >::apply(interior_rings(destination), num_interior_rings(source)); + + typename interior_return_type::type + rings_source = interior_rings(source); + typename interior_return_type::type + rings_dest = interior_rings(destination); + + typename detail::interior_iterator::type + it_source = boost::begin(rings_source); + typename detail::interior_iterator::type + it_dest = boost::begin(rings_dest); + + for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest) + { + per_ring::apply(*it_source, *it_dest); + } + } +}; + +template +struct single_to_multi: private Policy +{ + static inline void apply(Single const& single, Multi& multi) + { + traits::resize::apply(multi, 1); + Policy::apply(single, *boost::begin(multi)); + } +}; + + + +template +struct multi_to_multi: private Policy +{ + static inline void apply(Multi1 const& multi1, Multi2& multi2) + { + traits::resize::apply(multi2, boost::size(multi1)); + + typename boost::range_iterator::type it1 + = boost::begin(multi1); + typename boost::range_iterator::type it2 + = boost::begin(multi2); + + for (; it1 != boost::end(multi1); ++it1, ++it2) + { + Policy::apply(*it1, *it2); + } + } +}; + + +}} // namespace detail::conversion +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry1, typename Geometry2, + typename Tag1 = typename tag_cast::type, multi_tag>::type, + typename Tag2 = typename tag_cast::type, multi_tag>::type, + std::size_t DimensionCount = dimension::type::value, + bool UseAssignment = boost::is_same::value + && !boost::is_array::value +> +struct convert: not_implemented > +{}; + + +template +< + typename Geometry1, typename Geometry2, + typename Tag, + std::size_t DimensionCount +> +struct convert +{ + // Same geometry type -> copy whole geometry + static inline void apply(Geometry1 const& source, Geometry2& destination) + { + destination = source; + } +}; + + +template +< + typename Geometry1, typename Geometry2, + std::size_t DimensionCount +> +struct convert + : detail::conversion::point_to_point +{}; + + +template +< + typename Box1, typename Box2, + std::size_t DimensionCount +> +struct convert + : detail::conversion::indexed_to_indexed +{}; + + +template +< + typename Segment1, typename Segment2, + std::size_t DimensionCount +> +struct convert + : detail::conversion::indexed_to_indexed +{}; + + +template +struct convert + : detail::conversion::segment_to_range +{}; + + +template +struct convert + : detail::conversion::range_to_range + < + Ring1, + Ring2, + geometry::point_order::value + != geometry::point_order::value + > +{}; + +template +struct convert + : detail::conversion::range_to_range +{}; + +template +struct convert + : detail::conversion::polygon_to_polygon +{}; + +template +struct convert + : detail::conversion::box_to_range + < + Box, + Ring, + geometry::closure::value == closed, + geometry::point_order::value == counterclockwise + > +{}; + + +template +struct convert +{ + static inline void apply(Box const& box, Polygon& polygon) + { + typedef typename ring_type::type ring_type; + + convert + < + Box, ring_type, + box_tag, ring_tag, + 2, false + >::apply(box, exterior_ring(polygon)); + } +}; + + +template +struct convert +{ + static inline void apply(Point const& point, Box& box) + { + detail::conversion::point_to_box + < + Point, Box, min_corner, 0, DimensionCount + >::apply(point, box); + detail::conversion::point_to_box + < + Point, Box, max_corner, 0, DimensionCount + >::apply(point, box); + } +}; + + +template +struct convert +{ + static inline void apply(Ring const& ring, Polygon& polygon) + { + typedef typename ring_type::type ring_type; + convert + < + Ring, ring_type, + ring_tag, ring_tag, + DimensionCount, false + >::apply(ring, exterior_ring(polygon)); + } +}; + + +template +struct convert +{ + static inline void apply(Polygon const& polygon, Ring& ring) + { + typedef typename ring_type::type ring_type; + + convert + < + ring_type, Ring, + ring_tag, ring_tag, + DimensionCount, false + >::apply(exterior_ring(polygon), ring); + } +}; + + +// Dispatch for multi <-> multi, specifying their single-version as policy. +// Note that, even if the multi-types are mutually different, their single +// version types might be the same and therefore we call boost::is_same again + +template +struct convert + : detail::conversion::multi_to_multi + < + Multi1, + Multi2, + convert + < + typename boost::range_value::type, + typename boost::range_value::type, + typename single_tag_of + < + typename tag::type + >::type, + typename single_tag_of + < + typename tag::type + >::type, + DimensionCount + > + > +{}; + + +template +struct convert + : detail::conversion::single_to_multi + < + Single, + Multi, + convert + < + Single, + typename boost::range_value::type, + typename tag::type, + typename single_tag_of + < + typename tag::type + >::type, + DimensionCount, + false + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct convert +{ + static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2) + { + concepts::check_concepts_and_equal_dimensions(); + dispatch::convert::apply(geometry1, geometry2); + } +}; + +template +struct convert, Geometry2> +{ + struct visitor: static_visitor + { + Geometry2& m_geometry2; + + visitor(Geometry2& geometry2) + : m_geometry2(geometry2) + {} + + template + inline void operator()(Geometry1 const& geometry1) const + { + convert::apply(geometry1, m_geometry2); + } + }; + + static inline void apply( + boost::variant const& geometry1, + Geometry2& geometry2 + ) + { + boost::apply_visitor(visitor(geometry2), geometry1); + } +}; + +} + + +/*! +\brief Converts one geometry to another geometry +\details The convert algorithm converts one geometry, e.g. a BOX, to another +geometry, e.g. a RING. This only works if it is possible and applicable. +If the point-order is different, or the closure is different between two +geometry types, it will be converted correctly by explicitly reversing the +points or closing or opening the polygon rings. +\ingroup convert +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry (source) +\param geometry2 \param_geometry (target) + +\qbk{[include reference/algorithms/convert.qbk]} + */ +template +inline void convert(Geometry1 const& geometry1, Geometry2& geometry2) +{ + resolve_variant::convert::apply(geometry1, geometry2); +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/convex_hull.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/convex_hull.hpp new file mode 100755 index 0000000000..d9c0355a9e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/convex_hull.hpp @@ -0,0 +1,375 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace convex_hull +{ + +template +struct hull_insert +{ + + // Member template function (to avoid inconvenient declaration + // of output-iterator-type, from hull_to_geometry) + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator out, Strategy const& strategy) + { + typename Strategy::state_type state; + + strategy.apply(geometry, state); + strategy.result(state, out, Order == clockwise, Closure != open); + return out; + } +}; + +struct hull_to_geometry +{ + template + static inline void apply(Geometry const& geometry, OutputGeometry& out, + Strategy const& strategy) + { + hull_insert + < + geometry::point_order::value, + geometry::closure::value + >::apply(geometry, + range::back_inserter( + // Handle linestring, ring and polygon the same: + detail::as_range + < + typename range_type::type + >(out)), strategy); + } +}; + +}} // namespace detail::convex_hull +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry, + typename Tag = typename tag::type +> +struct convex_hull + : detail::convex_hull::hull_to_geometry +{}; + +template +struct convex_hull +{ + template + static inline void apply(Box const& box, OutputGeometry& out, + Strategy const& ) + { + static bool const Close + = geometry::closure::value == closed; + static bool const Reverse + = geometry::point_order::value == counterclockwise; + + // A hull for boxes is trivial. Any strategy is (currently) skipped. + boost::array::type, 4> range; + geometry::detail::assign_box_corners_oriented(box, range); + geometry::append(out, range); + if (BOOST_GEOMETRY_CONDITION(Close)) + { + geometry::append(out, *boost::begin(range)); + } + } +}; + + + +template +struct convex_hull_insert + : detail::convex_hull::hull_insert +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy { + +struct convex_hull +{ + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + dispatch::convex_hull::apply(geometry, out, strategy); + } + + template + static inline void apply(Geometry const& geometry, + OutputGeometry& out, + default_strategy) + { + typedef typename strategy_convex_hull< + Geometry, + typename point_type::type + >::type strategy_type; + + apply(geometry, out, strategy_type()); + } +}; + +struct convex_hull_insert +{ + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); + + return dispatch::convex_hull_insert< + geometry::point_order::value, + geometry::closure::value + >::apply(geometry, out, strategy); + } + + template + static inline OutputIterator apply(Geometry const& geometry, + OutputIterator& out, + default_strategy) + { + typedef typename strategy_convex_hull< + Geometry, + typename point_type::type + >::type strategy_type; + + return apply(geometry, out, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template +struct convex_hull +{ + template + static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy) + { + concepts::check_concepts_and_equal_dimensions< + const Geometry, + OutputGeometry + >(); + + resolve_strategy::convex_hull::apply(geometry, out, strategy); + } +}; + +template +struct convex_hull > +{ + template + struct visitor: boost::static_visitor + { + OutputGeometry& m_out; + Strategy const& m_strategy; + + visitor(OutputGeometry& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + void operator()(Geometry const& geometry) const + { + convex_hull::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline void + apply(boost::variant const& geometry, + OutputGeometry& out, + Strategy const& strategy) + { + boost::apply_visitor(visitor(out, strategy), geometry); + } +}; + +template +struct convex_hull_insert +{ + template + static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy) + { + // Concept: output point type = point type of input geometry + concepts::check(); + concepts::check::type>(); + + return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy); + } +}; + +template +struct convex_hull_insert > +{ + template + struct visitor: boost::static_visitor + { + OutputIterator& m_out; + Strategy const& m_strategy; + + visitor(OutputIterator& out, Strategy const& strategy) + : m_out(out), m_strategy(strategy) + {} + + template + OutputIterator operator()(Geometry const& geometry) const + { + return convex_hull_insert::apply(geometry, m_out, m_strategy); + } + }; + + template + static inline OutputIterator + apply(boost::variant const& geometry, + OutputIterator& out, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(out, strategy), geometry); + } +}; + +} // namespace resolve_variant + + +template +inline void convex_hull(Geometry const& geometry, + OutputGeometry& out, Strategy const& strategy) +{ + if (geometry::is_empty(geometry)) + { + // Leave output empty + return; + } + + resolve_variant::convex_hull::apply(geometry, out, strategy); +} + + +/*! +\brief \brief_calc{convex hull} +\ingroup convex_hull +\details \details_calc{convex_hull,convex hull}. +\tparam Geometry the input geometry type +\tparam OutputGeometry the output geometry type +\param geometry \param_geometry, input geometry +\param hull \param_geometry \param_set{convex hull} + +\qbk{[include reference/algorithms/convex_hull.qbk]} + */ +template +inline void convex_hull(Geometry const& geometry, + OutputGeometry& hull) +{ + geometry::convex_hull(geometry, hull, default_strategy()); +} + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace convex_hull +{ + + +template +inline OutputIterator convex_hull_insert(Geometry const& geometry, + OutputIterator out, Strategy const& strategy) +{ + return resolve_variant::convex_hull_insert + ::apply(geometry, out, strategy); +} + + +/*! +\brief Calculate the convex hull of a geometry, output-iterator version +\ingroup convex_hull +\tparam Geometry the input geometry type +\tparam OutputIterator: an output-iterator +\param geometry the geometry to calculate convex hull from +\param out an output iterator outputing points of the convex hull +\note This overloaded version outputs to an output iterator. +In this case, nothing is known about its point-type or + about its clockwise order. Therefore, the input point-type + and order are copied + + */ +template +inline OutputIterator convex_hull_insert(Geometry const& geometry, + OutputIterator out) +{ + return convex_hull_insert(geometry, out, default_strategy()); +} + + +}} // namespace detail::convex_hull +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/correct.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/correct.hpp new file mode 100755 index 0000000000..0b9d9bc12e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/correct.hpp @@ -0,0 +1,338 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP + + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +// Silence warning C4127: conditional expression is constant +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace correct +{ + +template +struct correct_nop +{ + static inline void apply(Geometry& ) + {} +}; + + +template +struct correct_box_loop +{ + typedef typename coordinate_type::type coordinate_type; + + static inline void apply(Box& box) + { + if (get(box) > get(box)) + { + // Swap the coordinates + coordinate_type max_value = get(box); + coordinate_type min_value = get(box); + set(box, min_value); + set(box, max_value); + } + + correct_box_loop + < + Box, Dimension + 1, DimensionCount + >::apply(box); + } +}; + + + +template +struct correct_box_loop +{ + static inline void apply(Box& ) + {} + +}; + + +// Correct a box: make min/max correct +template +struct correct_box +{ + + static inline void apply(Box& box) + { + // Currently only for Cartesian coordinates + // (or spherical without crossing dateline) + // Future version: adapt using strategies + correct_box_loop + < + Box, 0, dimension::type::value + >::apply(box); + } +}; + + +// Close a ring, if not closed +template +struct correct_ring +{ + typedef typename point_type::type point_type; + typedef typename coordinate_type::type coordinate_type; + + typedef typename strategy::area::services::default_strategy + < + typename cs_tag::type, + point_type + >::type strategy_type; + + typedef detail::area::ring_area + < + order_as_direction::value>::value, + geometry::closure::value + > ring_area_type; + + + static inline void apply(Ring& r) + { + // Check close-ness + if (boost::size(r) > 2) + { + // check if closed, if not, close it + bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1)); + closure_selector const s = geometry::closure::value; + + if (disjoint && (s == closed)) + { + geometry::append(r, *boost::begin(r)); + } + if (! disjoint && s != closed) + { + // Open it by removing last point + geometry::traits::resize::apply(r, boost::size(r) - 1); + } + } + // Check area + Predicate predicate; + typedef typename default_area_result::type area_result_type; + area_result_type const zero = area_result_type(); + if (predicate(ring_area_type::apply(r, strategy_type()), zero)) + { + std::reverse(boost::begin(r), boost::end(r)); + } + } +}; + +// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all +// inner rings counter clockwise (or vice versa depending on orientation) +template +struct correct_polygon +{ + typedef typename ring_type::type ring_type; + typedef typename default_area_result::type area_result_type; + + static inline void apply(Polygon& poly) + { + correct_ring + < + ring_type, + std::less + >::apply(exterior_ring(poly)); + + typename interior_return_type::type + rings = interior_rings(poly); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + correct_ring + < + ring_type, + std::greater + >::apply(*it); + } + } +}; + + +}} // namespace detail::correct +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template ::type> +struct correct: not_implemented +{}; + +template +struct correct + : detail::correct::correct_nop +{}; + +template +struct correct + : detail::correct::correct_nop +{}; + +template +struct correct + : detail::correct::correct_nop +{}; + + +template +struct correct + : detail::correct::correct_box +{}; + +template +struct correct + : detail::correct::correct_ring + < + Ring, + std::less::type> + > +{}; + +template +struct correct + : detail::correct::correct_polygon +{}; + + +template +struct correct + : detail::correct::correct_nop +{}; + + +template +struct correct + : detail::correct::correct_nop +{}; + + +template +struct correct + : detail::multi_modify + < + Geometry, + detail::correct::correct_polygon + < + typename boost::range_value::type + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct correct +{ + static inline void apply(Geometry& geometry) + { + concepts::check(); + dispatch::correct::apply(geometry); + } +}; + +template +struct correct > +{ + struct visitor: boost::static_visitor + { + template + void operator()(Geometry& geometry) const + { + correct::apply(geometry); + } + }; + + static inline void + apply(boost::variant& geometry) + { + boost::apply_visitor(visitor(), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief Corrects a geometry +\details Corrects a geometry: all rings which are wrongly oriented with respect + to their expected orientation are reversed. To all rings which do not have a + closing point and are typed as they should have one, the first point is + appended. Also boxes can be corrected. +\ingroup correct +\tparam Geometry \tparam_geometry +\param geometry \param_geometry which will be corrected if necessary + +\qbk{[include reference/algorithms/correct.qbk]} +*/ +template +inline void correct(Geometry& geometry) +{ + resolve_variant::correct::apply(geometry); +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/covered_by.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/covered_by.hpp new file mode 100755 index 0000000000..2c58273480 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/covered_by.hpp @@ -0,0 +1,473 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP + + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace covered_by { + +struct use_point_in_geometry +{ + template + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) + { + return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0; + } +}; + +struct use_relate +{ + template + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/) + { + return Strategy::apply(geometry1, geometry2); + } +}; + +}} // namespace detail::covered_by +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry1, + typename Geometry2, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct covered_by + : not_implemented +{}; + + +template +struct covered_by +{ + template + static inline bool apply(Point const& point, Box const& box, Strategy const& strategy) + { + ::boost::ignore_unused_variable_warning(strategy); + return strategy.apply(point, box); + } +}; + +template +struct covered_by +{ + template + static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) + { + assert_dimension_equal(); + ::boost::ignore_unused_variable_warning(strategy); + return strategy.apply(box1, box2); + } +}; + + +// P/P + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +// P/L + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +// P/A + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +template +struct covered_by + : public detail::covered_by::use_point_in_geometry +{}; + +// L/L + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +// L/A + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +// A/A + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +template +struct covered_by + : public detail::covered_by::use_relate +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy { + +struct covered_by +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + concepts::within::check + < + typename tag::type, + typename tag::type, + typename tag_cast::type, areal_tag>::type, + Strategy + >(); + concepts::check(); + concepts::check(); + assert_dimension_equal(); + + return dispatch::covered_by::apply(geometry1, + geometry2, + strategy); + } + + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename point_type::type point_type1; + typedef typename point_type::type point_type2; + + typedef typename strategy::covered_by::services::default_strategy + < + typename tag::type, + typename tag::type, + typename tag::type, + typename tag_cast::type, areal_tag>::type, + typename tag_cast + < + typename cs_tag::type, spherical_tag + >::type, + typename tag_cast + < + typename cs_tag::type, spherical_tag + >::type, + Geometry1, + Geometry2 + >::type strategy_type; + + return covered_by::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template +struct covered_by +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return resolve_strategy::covered_by + ::apply(geometry1, geometry2, strategy); + } +}; + +template +struct covered_by, Geometry2> +{ + template + struct visitor: boost::static_visitor + { + Geometry2 const& m_geometry2; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, Strategy const& strategy) + : m_geometry2(geometry2), m_strategy(strategy) {} + + template + bool operator()(Geometry1 const& geometry1) const + { + return covered_by + ::apply(geometry1, m_geometry2, m_strategy); + } + }; + + template + static inline bool + apply(boost::variant const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(geometry2, strategy), geometry1); + } +}; + +template +struct covered_by > +{ + template + struct visitor: boost::static_visitor + { + Geometry1 const& m_geometry1; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, Strategy const& strategy) + : m_geometry1(geometry1), m_strategy(strategy) {} + + template + bool operator()(Geometry2 const& geometry2) const + { + return covered_by + ::apply(m_geometry1, geometry2, m_strategy); + } + }; + + template + static inline bool + apply(Geometry1 const& geometry1, + boost::variant const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(geometry1, strategy), geometry2); + } +}; + +template < + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct covered_by< + boost::variant, + boost::variant +> +{ + template + struct visitor: boost::static_visitor + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy): m_strategy(strategy) {} + + template + bool operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return covered_by + ::apply(geometry1, geometry2, m_strategy); + } + }; + + template + static inline bool + apply(boost::variant const& geometry1, + boost::variant const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(strategy), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_check12{is inside or on border} +\ingroup covered_by +\details \details_check12{covered_by, is inside or on border}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry which might be inside or on the border of the second geometry +\param geometry2 \param_geometry which might cover the first geometry +\return true if geometry1 is inside of or on the border of geometry2, + else false +\note The default strategy is used for covered_by detection + +\qbk{[include reference/algorithms/covered_by.qbk]} + + */ +template +inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + return resolve_variant::covered_by + ::apply(geometry1, geometry2, default_strategy()); +} + +/*! +\brief \brief_check12{is inside or on border} \brief_strategy +\ingroup covered_by +\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry which might be inside or on the border of the second geometry +\param geometry2 \param_geometry which might cover the first geometry +\param strategy strategy to be used +\return true if geometry1 is inside of or on the border of geometry2, + else false + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/covered_by.qbk]} + +*/ +template +inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2, + Strategy const& strategy) +{ + return resolve_variant::covered_by + ::apply(geometry1, geometry2, strategy); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/crosses.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/crosses.hpp new file mode 100755 index 0000000000..dd38c3c45c --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/crosses.hpp @@ -0,0 +1,192 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry1, + typename Geometry2, + typename Tag1 = typename tag::type, + typename Tag2 = typename tag::type +> +struct crosses + : detail::relate::relate_impl + < + detail::de9im::static_mask_crosses_type, + Geometry1, + Geometry2 + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant +{ + template + struct crosses + { + static inline bool + apply( + const Geometry1& geometry1, + const Geometry2& geometry2) + { + concepts::check(); + concepts::check(); + + return dispatch::crosses::apply(geometry1, geometry2); + } + }; + + + template + struct crosses, Geometry2> + { + struct visitor: static_visitor + { + Geometry2 const& m_geometry2; + + visitor(Geometry2 const& geometry2) + : m_geometry2(geometry2) + {} + + template + result_type operator()(Geometry1 const& geometry1) const + { + return crosses + < + Geometry1, + Geometry2 + >::apply(geometry1, m_geometry2); + } + }; + + static inline bool + apply(variant const& geometry1, + Geometry2 const& geometry2) + { + return boost::apply_visitor(visitor(geometry2), geometry1); + } + }; + + + template + struct crosses > + { + struct visitor: static_visitor + { + Geometry1 const& m_geometry1; + + visitor(Geometry1 const& geometry1) + : m_geometry1(geometry1) + {} + + template + result_type operator()(Geometry2 const& geometry2) const + { + return crosses + < + Geometry1, + Geometry2 + >::apply(m_geometry1, geometry2); + } + }; + + static inline bool + apply(Geometry1 const& geometry1, + const variant& geometry2) + { + return boost::apply_visitor(visitor(geometry1), geometry2); + } + }; + + + template + struct crosses, variant > + { + struct visitor: static_visitor + { + template + result_type operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return crosses + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2); + } + }; + + static inline bool + apply(const variant& geometry1, + const variant& geometry2) + { + return boost::apply_visitor(visitor(), geometry1, geometry2); + } + }; + +} // namespace resolve_variant + + +/*! +\brief \brief_check2{crosses} +\ingroup crosses +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return \return_check2{crosses} + +\qbk{[include reference/algorithms/crosses.qbk]} +*/ +template +inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + return resolve_variant::crosses::apply(geometry1, geometry2); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/andoyer_inverse.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/andoyer_inverse.hpp new file mode 100755 index 0000000000..7fb02c2b68 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/andoyer_inverse.hpp @@ -0,0 +1,205 @@ +// Boost.Geometry + +// Copyright (c) 2015-2016 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP + + +#include + +#include +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry { namespace detail +{ + +/*! +\brief The solution of the inverse problem of geodesics on latlong coordinates, + Forsyth-Andoyer-Lambert type approximation with first order terms. +\author See + - Technical Report: PAUL D. THOMAS, MATHEMATICAL MODELS FOR NAVIGATION SYSTEMS, 1965 + http://www.dtic.mil/docs/citations/AD0627893 + - Technical Report: PAUL D. THOMAS, SPHEROIDAL GEODESICS, REFERENCE SYSTEMS, AND LOCAL GEOMETRY, 1970 + http://www.dtic.mil/docs/citations/AD703541 +*/ + +template +struct andoyer_inverse +{ + typedef result_inverse result_type; + + template + static inline result_type apply(T1 const& lon1, + T1 const& lat1, + T2 const& lon2, + T2 const& lat2, + Spheroid const& spheroid) + { + CT const c0 = CT(0); + CT const c1 = CT(1); + CT const pi = math::pi(); + + result_type result; + + // coordinates in radians + + if ( math::equals(lon1, lon2) && math::equals(lat1, lat2) ) + { + result.set(c0, c0); + return result; + } + + CT const dlon = lon2 - lon1; + CT const sin_dlon = sin(dlon); + CT const cos_dlon = cos(dlon); + CT const sin_lat1 = sin(lat1); + CT const cos_lat1 = cos(lat1); + CT const sin_lat2 = sin(lat2); + CT const cos_lat2 = cos(lat2); + + // H,G,T = infinity if cos_d = 1 or cos_d = -1 + // lat1 == +-90 && lat2 == +-90 + // lat1 == lat2 && lon1 == lon2 + CT cos_d = sin_lat1*sin_lat2 + cos_lat1*cos_lat2*cos_dlon; + // on some platforms cos_d may be outside valid range + if (cos_d < -c1) + cos_d = -c1; + else if (cos_d > c1) + cos_d = c1; + + CT const d = acos(cos_d); // [0, pi] + CT const sin_d = sin(d); // [-1, 1] + + CT const f = detail::flattening(spheroid); + + if ( BOOST_GEOMETRY_CONDITION(EnableDistance) ) + { + CT const K = math::sqr(sin_lat1-sin_lat2); + CT const L = math::sqr(sin_lat1+sin_lat2); + CT const three_sin_d = CT(3) * sin_d; + + CT const one_minus_cos_d = c1 - cos_d; + CT const one_plus_cos_d = c1 + cos_d; + // cos_d = 1 or cos_d = -1 means that the points are antipodal + + CT const H = math::equals(one_minus_cos_d, c0) ? + c0 : + (d + three_sin_d) / one_minus_cos_d; + CT const G = math::equals(one_plus_cos_d, c0) ? + c0 : + (d - three_sin_d) / one_plus_cos_d; + + CT const dd = -(f/CT(4))*(H*K+G*L); + + CT const a = get_radius<0>(spheroid); + + result.distance = a * (d + dd); + } + else + { + result.distance = c0; + } + + if ( BOOST_GEOMETRY_CONDITION(EnableAzimuth) ) + { + // sin_d = 0 <=> antipodal points + if (math::equals(sin_d, c0)) + { + // T = inf + // dA = inf + // azimuth = -inf + if (lat1 <= lat2) + result.azimuth = c0; + else + result.azimuth = pi; + } + else + { + CT const c2 = CT(2); + + CT A = c0; + CT U = c0; + if ( ! math::equals(cos_lat2, c0) ) + { + CT const tan_lat2 = sin_lat2/cos_lat2; + CT const M = cos_lat1*tan_lat2-sin_lat1*cos_dlon; + A = atan2(sin_dlon, M); + CT const sin_2A = sin(c2*A); + U = (f/ c2)*math::sqr(cos_lat1)*sin_2A; + } + + CT V = c0; + if ( ! math::equals(cos_lat1, c0) ) + { + CT const tan_lat1 = sin_lat1/cos_lat1; + CT const N = cos_lat2*tan_lat1-sin_lat2*cos_dlon; + CT const B = atan2(sin_dlon, N); + CT const sin_2B = sin(c2*B); + V = (f/ c2)*math::sqr(cos_lat2)*sin_2B; + } + + CT const T = d / sin_d; + CT const dA = V*T-U; + + result.azimuth = A - dA; + + // even with sin_d == 0 checked above if the second point + // is somewhere in the antipodal area T may still be great + // therefore dA may be great and the resulting azimuth + // may be some more or less arbitrary angle + if (A >= c0) // A indicates Eastern hemisphere + { + if (dA >= c0) // A altered towards 0 + { + if ((result.azimuth) < c0) + result.azimuth = c0; + } + else // dA < 0, A altered towards pi + { + if (result.azimuth > pi) + result.azimuth = pi; + } + } + else // A indicates Western hemisphere + { + if (dA <= c0) // A altered towards 0 + { + if (result.azimuth > c0) + result.azimuth = c0; + } + else // dA > 0, A altered towards -pi + { + CT const minus_pi = -pi; + if ((result.azimuth) < minus_pi) + result.azimuth = minus_pi; + } + } + } + } + else + { + result.azimuth = c0; + } + + return result; + } +}; + +}}} // namespace boost::geometry::detail + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ANDOYER_INVERSE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/as_range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/as_range.hpp new file mode 100755 index 0000000000..4e963d24ee --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/as_range.hpp @@ -0,0 +1,105 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP + + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct as_range +{ + static inline typename add_const_if_c::type& get( + typename add_const_if_c::type& input) + { + return input; + } +}; + + +template +struct as_range +{ + static inline typename add_const_if_c::type& get( + typename add_const_if_c::type& input) + { + return exterior_ring(input); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +// Will probably be replaced by the more generic "view_as", therefore in detail +namespace detail +{ + +/*! +\brief Function getting either the range (ring, linestring) itself +or the outer ring (polygon) +\details Utility to handle polygon's outer ring as a range +\ingroup utility +*/ +template +inline Range& as_range(Geometry& input) +{ + return dispatch::as_range + < + typename tag::type, + Geometry, + Range, + false + >::get(input); +} + + +/*! +\brief Function getting either the range (ring, linestring) itself +or the outer ring (polygon), const version +\details Utility to handle polygon's outer ring as a range +\ingroup utility +*/ +template +inline Range const& as_range(Geometry const& input) +{ + return dispatch::as_range + < + typename tag::type, + Geometry, + Range, + true + >::get(input); +} + +} + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_box_corners.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_box_corners.hpp new file mode 100755 index 0000000000..9d73c02b80 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_box_corners.hpp @@ -0,0 +1,107 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP + + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ +// Note: this is moved to namespace detail because the names and parameter orders +// are not yet 100% clear. + +/*! +\brief Assign the four points of a 2D box +\ingroup assign +\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT + so this is how it is implemented. +\tparam Box \tparam_box +\tparam Point \tparam_point +\param box \param_box +\param lower_left point being assigned to lower left coordinates of the box +\param lower_right point being assigned to lower right coordinates of the box +\param upper_left point being assigned to upper left coordinates of the box +\param upper_right point being assigned to upper right coordinates of the box + +\qbk{ +[heading Example] +[assign_box_corners] [assign_box_corners_output] +} +*/ +template +inline void assign_box_corners(Box const& box, + Point& lower_left, Point& lower_right, + Point& upper_left, Point& upper_right) +{ + concepts::check(); + concepts::check(); + + detail::assign::assign_box_2d_corner + (box, lower_left); + detail::assign::assign_box_2d_corner + (box, lower_right); + detail::assign::assign_box_2d_corner + (box, upper_left); + detail::assign::assign_box_2d_corner + (box, upper_right); +} + +// Silence warning C4127: conditional expression is constant +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + + +template +inline void assign_box_corners_oriented(Box const& box, Range& corners) +{ + if (Reverse) + { + // make counterclockwise ll,lr,ur,ul + assign_box_corners(box, + range::at(corners, 0), range::at(corners, 1), + range::at(corners, 3), range::at(corners, 2)); + } + else + { + // make clockwise ll,ul,ur,lr + assign_box_corners(box, + range::at(corners, 0), range::at(corners, 3), + range::at(corners, 1), range::at(corners, 2)); + } +} +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp new file mode 100755 index 0000000000..9a33bce1ad --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp @@ -0,0 +1,94 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP + + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +/*! +\brief Assign a box or segment with the value of a point +\ingroup assign +\tparam Index indicates which box-corner, min_corner (0) or max_corner (1) + or which point of segment (0/1) +\tparam Point \tparam_point +\tparam Geometry \tparam_box_or_segment +\param point \param_point +\param geometry \param_box_or_segment + +\qbk{ +[heading Example] +[assign_point_to_index] [assign_point_to_index_output] +} +*/ +template +inline void assign_point_to_index(Point const& point, Geometry& geometry) +{ + concepts::check(); + concepts::check(); + + detail::assign::assign_point_to_index + < + Geometry, Point, Index, 0, dimension::type::value + >::apply(point, geometry); +} + + +/*! +\brief Assign a point with a point of a box or segment +\ingroup assign +\tparam Index indicates which box-corner, min_corner (0) or max_corner (1) + or which point of segment (0/1) +\tparam Geometry \tparam_box_or_segment +\tparam Point \tparam_point +\param geometry \param_box_or_segment +\param point \param_point + +\qbk{ +[heading Example] +[assign_point_from_index] [assign_point_from_index_output] +} +*/ +template +inline void assign_point_from_index(Geometry const& geometry, Point& point) +{ + concepts::check(); + concepts::check(); + + detail::assign::assign_point_from_index + < + Geometry, Point, Index, 0, dimension::type::value + >::apply(geometry, point); +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_values.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_values.hpp new file mode 100755 index 0000000000..676338623d --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/assign_values.hpp @@ -0,0 +1,336 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP + + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace assign +{ + + +template +struct initialize +{ + template + static inline void apply(Box& box, typename coordinate_type::type const& value) + { + geometry::set(box, value); + initialize::apply(box, value); + } +}; + + +template +struct initialize +{ + template + static inline void apply(Box&, typename coordinate_type::type const&) + {} +}; + + +struct assign_zero_point +{ + template + static inline void apply(Point& point) + { + geometry::assign_value(point, 0); + } +}; + + +struct assign_inverse_box_or_segment +{ + + template + static inline void apply(BoxOrSegment& geometry) + { + typedef typename point_type::type point_type; + typedef typename coordinate_type::type bound_type; + + initialize<0, 0, dimension::type::value>::apply( + geometry, boost::numeric::bounds::highest() + ); + initialize<1, 0, dimension::type::value>::apply( + geometry, boost::numeric::bounds::lowest() + ); + } +}; + + +struct assign_zero_box_or_segment +{ + template + static inline void apply(BoxOrSegment& geometry) + { + typedef typename coordinate_type::type coordinate_type; + + initialize<0, 0, dimension::type::value>::apply( + geometry, coordinate_type() + ); + initialize<1, 0, dimension::type::value>::apply( + geometry, coordinate_type() + ); + } +}; + + +template +< + std::size_t Corner1, std::size_t Corner2, + typename Box, typename Point +> +inline void assign_box_2d_corner(Box const& box, Point& point) +{ + // Be sure both are 2-Dimensional + assert_dimension(); + assert_dimension(); + + // Copy coordinates + typedef typename coordinate_type::type coordinate_type; + + geometry::set<0>(point, boost::numeric_cast(get(box))); + geometry::set<1>(point, boost::numeric_cast(get(box))); +} + + + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct assign_point_to_index +{ + + static inline void apply(Point const& point, Geometry& geometry) + { + geometry::set(geometry, boost::numeric_cast + < + typename coordinate_type::type + >(geometry::get(point))); + + assign_point_to_index + < + Geometry, Point, Index, Dimension + 1, DimensionCount + >::apply(point, geometry); + } +}; + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t DimensionCount +> +struct assign_point_to_index + < + Geometry, Point, + Index, + DimensionCount, DimensionCount + > +{ + static inline void apply(Point const& , Geometry& ) + { + } +}; + + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct assign_point_from_index +{ + + static inline void apply(Geometry const& geometry, Point& point) + { + geometry::set( point, boost::numeric_cast + < + typename coordinate_type::type + >(geometry::get(geometry))); + + assign_point_from_index + < + Geometry, Point, Index, Dimension + 1, DimensionCount + >::apply(geometry, point); + } +}; + +template +< + typename Geometry, typename Point, + std::size_t Index, + std::size_t DimensionCount +> +struct assign_point_from_index + < + Geometry, Point, + Index, + DimensionCount, DimensionCount + > +{ + static inline void apply(Geometry const&, Point&) + { + } +}; + + +template +struct assign_2d_box_or_segment +{ + typedef typename coordinate_type::type coordinate_type; + + // Here we assign 4 coordinates to a box of segment + // -> Most logical is: x1,y1,x2,y2 + // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED) + + template + static inline void apply(Geometry& geometry, + Type const& x1, Type const& y1, Type const& x2, Type const& y2) + { + geometry::set<0, 0>(geometry, boost::numeric_cast(x1)); + geometry::set<0, 1>(geometry, boost::numeric_cast(y1)); + geometry::set<1, 0>(geometry, boost::numeric_cast(x2)); + geometry::set<1, 1>(geometry, boost::numeric_cast(y2)); + } +}; + + +}} // namespace detail::assign +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct assign +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types) + ); +}; + +template +struct assign +{ + typedef typename coordinate_type::type coordinate_type; + + template + static inline void apply(Point& point, T const& c1, T const& c2) + { + set<0>(point, boost::numeric_cast(c1)); + set<1>(point, boost::numeric_cast(c2)); + } +}; + +template +struct assign +{ + typedef typename coordinate_type::type coordinate_type; + + template + static inline void apply(Point& point, T const& c1, T const& c2, T const& c3) + { + set<0>(point, boost::numeric_cast(c1)); + set<1>(point, boost::numeric_cast(c2)); + set<2>(point, boost::numeric_cast(c3)); + } +}; + +template +struct assign + : detail::assign::assign_2d_box_or_segment +{}; + +template +struct assign + : detail::assign::assign_2d_box_or_segment +{}; + + + +template +struct assign_zero {}; + + +template +struct assign_zero + : detail::assign::assign_zero_point +{}; + +template +struct assign_zero + : detail::assign::assign_zero_box_or_segment +{}; + +template +struct assign_zero + : detail::assign::assign_zero_box_or_segment +{}; + + +template +struct assign_inverse {}; + +template +struct assign_inverse + : detail::assign::assign_inverse_box_or_segment +{}; + +template +struct assign_inverse + : detail::assign::assign_inverse_box_or_segment +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/azimuth.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/azimuth.hpp new file mode 100755 index 0000000000..6611b9a6ef --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/azimuth.hpp @@ -0,0 +1,158 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP + +#include +#include +#include +#include + +#include + +#include +#include + +namespace boost { namespace geometry +{ + +// An azimuth is an angle between a vector/segment from origin to a point of +// interest and a reference vector. Typically north-based azimuth is used. +// North direction is used as a reference, angle is measured clockwise +// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS +// the reference vector is Y axis, angle is measured clockwise. +// http://en.wikipedia.org/wiki/Azimuth + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch +{ + +template +struct azimuth + : not_implemented +{}; + +template +struct azimuth +{ + template + static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid) + { + return geometry::detail::vincenty_inverse().apply + ( get_as_radian<0>(p1), get_as_radian<1>(p1), + get_as_radian<0>(p2), get_as_radian<1>(p2), + spheroid ).azimuth; + } + + template + static inline ReturnType apply(P1 const& p1, P2 const& p2) + { + return apply(p1, p2, srs::spheroid()); + } +}; + +template +struct azimuth +{ + template + static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/) + { + // http://williams.best.vwh.net/avform.htm#Crs + ReturnType dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1); + ReturnType cos_p2lat = cos(get_as_radian<1>(p2)); + + // An optimization which should kick in often for Boxes + //if ( math::equals(dlon, ReturnType(0)) ) + //if ( get<0>(p1) == get<0>(p2) ) + //{ + // return - sin(get_as_radian<1>(p1)) * cos_p2lat); + //} + + // "An alternative formula, not requiring the pre-computation of d" + // In the formula below dlon is used as "d" + return atan2(sin(dlon) * cos_p2lat, + cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2)) + - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon)); + } + + template + static inline ReturnType apply(P1 const& p1, P2 const& p2) + { + return apply(p1, p2, 0); // dummy model + } +}; + +template +struct azimuth + : azimuth +{}; + +template +struct azimuth +{ + template + static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/) + { + ReturnType x = get<0>(p2) - get<0>(p1); + ReturnType y = get<1>(p2) - get<1>(p1); + + // NOTE: azimuth 0 is at Y axis, increasing right + // as in spherical/geographic where 0 is at North axis + return atan2(x, y); + } + + template + static inline ReturnType apply(P1 const& p1, P2 const& p2) + { + return apply(p1, p2, 0); // dummy model + } +}; + +} // detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +/// Calculate azimuth between two points. +/// The result is in radians. +template +inline ReturnType azimuth(Point1 const& p1, Point2 const& p2) +{ + return detail_dispatch::azimuth + < + ReturnType, + typename geometry::cs_tag::type + >::apply(p1, p2); +} + +/// Calculate azimuth between two points. +/// The result is in radians. +template +inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model) +{ + return detail_dispatch::azimuth + < + ReturnType, + typename geometry::cs_tag::type + >::apply(p1, p2, model); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp new file mode 100755 index 0000000000..dcc103a564 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -0,0 +1,986 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP + +#include +#include + + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX) +#include +#endif + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +template +inline void simplify_input(Range const& range, + DistanceStrategy const& distance, + Range& simplified) +{ + // We have to simplify the ring before to avoid very small-scaled + // features in the original (convex/concave/convex) being enlarged + // in a very large scale and causing issues (IP's within pieces). + // This might be reconsidered later. Simplifying with a very small + // distance (1%% of the buffer) will never be visible in the result, + // if it is using round joins. For miter joins they are even more + // sensitive to small scale input features, however the result will + // look better. + // It also gets rid of duplicate points +#if ! defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX) + geometry::simplify(range, simplified, distance.simplify_distance()); +#else + + typedef typename boost::range_value::type point_type; + typedef strategy::distance::detail::projected_point_ax<> ax_type; + typedef typename strategy::distance::services::return_type + < + strategy::distance::detail::projected_point_ax<>, + point_type, + point_type + >::type return_type; + + typedef strategy::distance::detail::projected_point_ax_less + < + return_type + > comparator_type; + + typedef strategy::simplify::detail::douglas_peucker + < + point_type, + strategy::distance::detail::projected_point_ax<>, + comparator_type + > dp_ax; + + return_type max_distance(distance.simplify_distance() * 2.0, + distance.simplify_distance()); + comparator_type comparator(max_distance); + dp_ax strategy(comparator); + + geometry::simplify(range, simplified, max_distance, strategy); +#endif + + if (boost::size(simplified) == 2 + && geometry::equals(geometry::range::front(simplified), + geometry::range::back(simplified))) + { + traits::resize::apply(simplified, 1); + } +} + + +template +struct buffer_range +{ + typedef typename point_type::type output_point_type; + typedef typename coordinate_type::type coordinate_type; + + template + < + typename Collection, + typename Point, + typename DistanceStrategy, + typename JoinStrategy, + typename EndStrategy, + typename RobustPolicy + > + static inline + void add_join(Collection& collection, + Point const& penultimate_input, + Point const& previous_input, + output_point_type const& prev_perp1, + output_point_type const& prev_perp2, + Point const& input, + output_point_type const& perp1, + output_point_type const& perp2, + strategy::buffer::buffer_side_selector side, + DistanceStrategy const& distance, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + RobustPolicy const& ) + { + output_point_type intersection_point; + geometry::assign_zero(intersection_point); + + strategy::buffer::join_selector join + = get_join_type(penultimate_input, previous_input, input); + if (join == strategy::buffer::join_convex) + { + // Calculate the intersection-point formed by the two sides. + // It might be that the two sides are not convex, but continue + // or spikey, we then change the join-type + join = line_line_intersection::apply( + perp1, perp2, prev_perp1, prev_perp2, + intersection_point); + + } + + switch(join) + { + case strategy::buffer::join_continue : + // No join, we get two consecutive sides + break; + case strategy::buffer::join_concave : + { + std::vector range_out; + range_out.push_back(prev_perp2); + range_out.push_back(previous_input); + collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out); + + range_out.clear(); + range_out.push_back(previous_input); + range_out.push_back(perp1); + collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out); + } + break; + case strategy::buffer::join_spike : + { + // For linestrings, only add spike at one side to avoid + // duplicates + std::vector range_out; + end_strategy.apply(penultimate_input, prev_perp2, previous_input, perp1, side, distance, range_out); + collection.add_endcap(end_strategy, range_out, previous_input); + collection.set_current_ring_concave(); + } + break; + case strategy::buffer::join_convex : + { + // The corner is convex, we create a join + // TODO (future) - avoid a separate vector, add the piece directly + std::vector range_out; + if (join_strategy.apply(intersection_point, + previous_input, prev_perp2, perp1, + distance.apply(previous_input, input, side), + range_out)) + { + collection.add_piece(strategy::buffer::buffered_join, + previous_input, range_out); + } + } + break; + } + } + + static inline strategy::buffer::join_selector get_join_type( + output_point_type const& p0, + output_point_type const& p1, + output_point_type const& p2) + { + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + + int const side = side_strategy::apply(p0, p1, p2); + return side == -1 ? strategy::buffer::join_convex + : side == 1 ? strategy::buffer::join_concave + : parallel_continue + ( + get<0>(p2) - get<0>(p1), + get<1>(p2) - get<1>(p1), + get<0>(p1) - get<0>(p0), + get<1>(p1) - get<1>(p0) + ) ? strategy::buffer::join_continue + : strategy::buffer::join_spike; + } + + template + < + typename Collection, + typename Iterator, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename RobustPolicy + > + static inline strategy::buffer::result_code iterate(Collection& collection, + Iterator begin, Iterator end, + strategy::buffer::buffer_side_selector side, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + RobustPolicy const& robust_policy, + output_point_type& first_p1, + output_point_type& first_p2, + output_point_type& last_p1, + output_point_type& last_p2) + { + boost::ignore_unused(side_strategy); + + typedef typename std::iterator_traits + < + Iterator + >::value_type point_type; + + point_type second_point, penultimate_point, ultimate_point; // last two points from begin/end + + /* + * last.p1 last.p2 these are the "previous (last) perpendicular points" + * -------------- + * | | + * *------------*____ <- *prev + * pup | | p1 "current perpendicular point 1" + * | | + * | | this forms a "side", a side is a piece + * | | + * *____| p2 + * + * ^ + * *it + * + * pup: penultimate_point + */ + + strategy::buffer::result_code result = strategy::buffer::result_no_output; + bool first = true; + + Iterator it = begin; + + std::vector generated_side; + generated_side.reserve(2); + + for (Iterator prev = it++; it != end; ++it) + { + generated_side.clear(); + strategy::buffer::result_code error_code + = side_strategy.apply(*prev, *it, side, + distance_strategy, generated_side); + + if (error_code == strategy::buffer::result_no_output) + { + // Because input is simplified, this is improbable, + // but it can happen for degenerate geometries + // Further handling of this side is skipped + continue; + } + else if (error_code == strategy::buffer::result_error_numerical) + { + return error_code; + } + + BOOST_GEOMETRY_ASSERT(! generated_side.empty()); + + result = strategy::buffer::result_normal; + + if (! first) + { + add_join(collection, + penultimate_point, + *prev, last_p1, last_p2, + *it, generated_side.front(), generated_side.back(), + side, + distance_strategy, join_strategy, end_strategy, + robust_policy); + } + + collection.add_side_piece(*prev, *it, generated_side, first); + + penultimate_point = *prev; + ultimate_point = *it; + last_p1 = generated_side.front(); + last_p2 = generated_side.back(); + prev = it; + if (first) + { + first = false; + second_point = *it; + first_p1 = generated_side.front(); + first_p2 = generated_side.back(); + } + } + return result; + } +}; + +template +< + typename Multi, + typename PolygonOutput, + typename Policy +> +struct buffer_multi +{ + template + < + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline void apply(Multi const& multi, + Collection& collection, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) + { + for (typename boost::range_iterator::type + it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + Policy::apply(*it, collection, + distance_strategy, side_strategy, + join_strategy, end_strategy, point_strategy, + robust_policy); + } + } +}; + +struct visit_pieces_default_policy +{ + template + static inline void apply(Collection const&, int) + {} +}; + +template +< + typename OutputPointType, + typename Point, + typename Collection, + typename DistanceStrategy, + typename PointStrategy +> +inline void buffer_point(Point const& point, Collection& collection, + DistanceStrategy const& distance_strategy, + PointStrategy const& point_strategy) +{ + collection.start_new_ring(); + std::vector range_out; + point_strategy.apply(point, distance_strategy, range_out); + collection.add_piece(strategy::buffer::buffered_point, range_out, false); + collection.set_piece_center(point); + collection.finish_ring(strategy::buffer::result_normal); +} + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Tag, + typename RingInput, + typename RingOutput +> +struct buffer_inserter +{}; + + + +template +< + typename Point, + typename RingOutput +> +struct buffer_inserter +{ + template + < + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline void apply(Point const& point, Collection& collection, + DistanceStrategy const& distance_strategy, + SideStrategy const& , + JoinStrategy const& , + EndStrategy const& , + PointStrategy const& point_strategy, + RobustPolicy const& ) + { + detail::buffer::buffer_point + < + typename point_type::type + >(point, collection, distance_strategy, point_strategy); + } +}; + + +template +< + typename RingInput, + typename RingOutput +> +struct buffer_inserter +{ + typedef typename point_type::type output_point_type; + + template + < + typename Collection, + typename Iterator, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename RobustPolicy + > + static inline strategy::buffer::result_code iterate(Collection& collection, + Iterator begin, Iterator end, + strategy::buffer::buffer_side_selector side, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + RobustPolicy const& robust_policy) + { + output_point_type first_p1, first_p2, last_p1, last_p2; + + typedef detail::buffer::buffer_range buffer_range; + + strategy::buffer::result_code result + = buffer_range::iterate(collection, begin, end, + side, + distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, + first_p1, first_p2, last_p1, last_p2); + + // Generate closing join + if (result == strategy::buffer::result_normal) + { + buffer_range::add_join(collection, + *(end - 2), + *(end - 1), last_p1, last_p2, + *(begin + 1), first_p1, first_p2, + side, + distance_strategy, join_strategy, end_strategy, + robust_policy); + } + + // Buffer is closed automatically by last closing corner + return result; + } + + template + < + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline strategy::buffer::result_code apply(RingInput const& ring, + Collection& collection, + DistanceStrategy const& distance, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) + { + RingInput simplified; + detail::buffer::simplify_input(ring, distance, simplified); + + strategy::buffer::result_code code = strategy::buffer::result_no_output; + + std::size_t n = boost::size(simplified); + std::size_t const min_points = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + + if (n >= min_points) + { + detail::normalized_view view(simplified); + if (distance.negative()) + { + // Walk backwards (rings will be reversed afterwards) + code = iterate(collection, boost::rbegin(view), boost::rend(view), + strategy::buffer::buffer_side_right, + distance, side_strategy, join_strategy, end_strategy, robust_policy); + } + else + { + code = iterate(collection, boost::begin(view), boost::end(view), + strategy::buffer::buffer_side_left, + distance, side_strategy, join_strategy, end_strategy, robust_policy); + } + } + + if (code == strategy::buffer::result_no_output && n >= 1) + { + // Use point_strategy to buffer degenerated ring + detail::buffer::buffer_point + ( + geometry::range::front(simplified), + collection, distance, point_strategy + ); + } + return code; + } +}; + + +template +< + typename Linestring, + typename Polygon +> +struct buffer_inserter +{ + typedef typename ring_type::type output_ring_type; + typedef typename point_type::type output_point_type; + typedef typename point_type::type input_point_type; + + template + < + typename Collection, + typename Iterator, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename RobustPolicy + > + static inline strategy::buffer::result_code iterate(Collection& collection, + Iterator begin, Iterator end, + strategy::buffer::buffer_side_selector side, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + RobustPolicy const& robust_policy, + output_point_type& first_p1) + { + input_point_type const& ultimate_point = *(end - 1); + input_point_type const& penultimate_point = *(end - 2); + + // For the end-cap, we need to have the last perpendicular point on the + // other side of the linestring. If it is the second pass (right), + // we have it already from the first phase (left). + // But for the first pass, we have to generate it + output_point_type reverse_p1; + if (side == strategy::buffer::buffer_side_right) + { + reverse_p1 = first_p1; + } + else + { + std::vector generated_side; + strategy::buffer::result_code code + = side_strategy.apply(ultimate_point, penultimate_point, + strategy::buffer::buffer_side_right, + distance_strategy, generated_side); + if (code != strategy::buffer::result_normal) + { + // No output or numerical error + return code; + } + reverse_p1 = generated_side.front(); + } + + output_point_type first_p2, last_p1, last_p2; + + strategy::buffer::result_code result + = detail::buffer::buffer_range::iterate(collection, + begin, end, side, + distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy, + first_p1, first_p2, last_p1, last_p2); + + if (result == strategy::buffer::result_normal) + { + std::vector range_out; + end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out); + collection.add_endcap(end_strategy, range_out, ultimate_point); + } + return result; + } + + template + < + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection, + DistanceStrategy const& distance, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) + { + Linestring simplified; + detail::buffer::simplify_input(linestring, distance, simplified); + + strategy::buffer::result_code code = strategy::buffer::result_no_output; + std::size_t n = boost::size(simplified); + if (n > 1) + { + collection.start_new_ring(); + output_point_type first_p1; + code = iterate(collection, + boost::begin(simplified), boost::end(simplified), + strategy::buffer::buffer_side_left, + distance, side_strategy, join_strategy, end_strategy, robust_policy, + first_p1); + + if (code == strategy::buffer::result_normal) + { + code = iterate(collection, + boost::rbegin(simplified), boost::rend(simplified), + strategy::buffer::buffer_side_right, + distance, side_strategy, join_strategy, end_strategy, robust_policy, + first_p1); + } + collection.finish_ring(code); + } + if (code == strategy::buffer::result_no_output && n >= 1) + { + // Use point_strategy to buffer degenerated linestring + detail::buffer::buffer_point + ( + geometry::range::front(simplified), + collection, distance, point_strategy + ); + } + return code; + } +}; + + +template +< + typename PolygonInput, + typename PolygonOutput +> +struct buffer_inserter +{ +private: + typedef typename ring_type::type input_ring_type; + typedef typename ring_type::type output_ring_type; + + typedef buffer_inserter policy; + + + template + < + typename Iterator, + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline + void iterate(Iterator begin, Iterator end, + Collection& collection, + DistanceStrategy const& distance, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy, + bool is_interior) + { + for (Iterator it = begin; it != end; ++it) + { + collection.start_new_ring(); + strategy::buffer::result_code const code + = policy::apply(*it, collection, distance, side_strategy, + join_strategy, end_strategy, point_strategy, + robust_policy); + + collection.finish_ring(code, is_interior); + } + } + + template + < + typename InteriorRings, + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline + void apply_interior_rings(InteriorRings const& interior_rings, + Collection& collection, + DistanceStrategy const& distance, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) + { + iterate(boost::begin(interior_rings), boost::end(interior_rings), + collection, distance, side_strategy, + join_strategy, end_strategy, point_strategy, + robust_policy, true); + } + +public: + template + < + typename Collection, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy + > + static inline void apply(PolygonInput const& polygon, + Collection& collection, + DistanceStrategy const& distance, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) + { + { + collection.start_new_ring(); + + strategy::buffer::result_code const code + = policy::apply(exterior_ring(polygon), collection, + distance, side_strategy, + join_strategy, end_strategy, point_strategy, + robust_policy); + + collection.finish_ring(code, false, + geometry::num_interior_rings(polygon) > 0u); + } + + apply_interior_rings(interior_rings(polygon), + collection, distance, side_strategy, + join_strategy, end_strategy, point_strategy, + robust_policy); + } +}; + + +template +< + typename Multi, + typename PolygonOutput +> +struct buffer_inserter + : public detail::buffer::buffer_multi + < + Multi, + PolygonOutput, + dispatch::buffer_inserter + < + typename single_tag_of + < + typename tag::type + >::type, + typename boost::range_value::type, + typename geometry::ring_type::type + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +template +< + typename GeometryOutput, + typename GeometryInput, + typename OutputIterator, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy, + typename VisitPiecesPolicy +> +inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy, + VisitPiecesPolicy& visit_pieces_policy + ) +{ + boost::ignore_unused(visit_pieces_policy); + + typedef detail::buffer::buffered_piece_collection + < + typename geometry::ring_type::type, + RobustPolicy + > collection_type; + collection_type collection(robust_policy); + collection_type const& const_collection = collection; + + bool const areal = boost::is_same + < + typename tag_cast::type, areal_tag>::type, + areal_tag + >::type::value; + bool const linear = boost::is_same + < + typename tag_cast::type, linear_tag>::type, + linear_tag + >::type::value; + + dispatch::buffer_inserter + < + typename tag_cast + < + typename tag::type, + multi_tag + >::type, + GeometryInput, + GeometryOutput + >::apply(geometry_input, collection, + distance_strategy, side_strategy, join_strategy, + end_strategy, point_strategy, + robust_policy); + + collection.get_turns(); + collection.classify_turns(linear); + if (BOOST_GEOMETRY_CONDITION(areal)) + { + collection.check_remaining_points(distance_strategy); + } + + // Visit the piece collection. This does nothing (by default), but + // optionally a debugging tool can be attached (e.g. console or svg), + // or the piece collection can be unit-tested + // phase 0: turns (before discarded) + visit_pieces_policy.apply(const_collection, 0); + + collection.discard_rings(); + collection.block_turns(); + collection.enrich(); + + // phase 1: turns (after enrichment/clustering) + visit_pieces_policy.apply(const_collection, 1); + + collection.traverse(); + + // Reverse all offsetted rings / traversed rings if: + // - they were generated on the negative side (deflate) of polygons + // - the output is counter clockwise + // and avoid reversing twice + bool reverse = distance_strategy.negative() && areal; + if (BOOST_GEOMETRY_CONDITION( + geometry::point_order::value == counterclockwise)) + { + reverse = ! reverse; + } + if (reverse) + { + collection.reverse(); + } + + if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal)) + { + collection.discard_nonintersecting_deflated_rings(); + } + + collection.template assign(out); + + // Visit collection again + // phase 2: rings (after traversing) + visit_pieces_policy.apply(const_collection, 2); +} + +template +< + typename GeometryOutput, + typename GeometryInput, + typename OutputIterator, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy, + typename RobustPolicy +> +inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy, + RobustPolicy const& robust_policy) +{ + detail::buffer::visit_pieces_default_policy visitor; + buffer_inserter(geometry_input, out, + distance_strategy, side_strategy, join_strategy, + end_strategy, point_strategy, + robust_policy, visitor); +} +#endif // DOXYGEN_NO_DETAIL + +}} // namespace detail::buffer + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_INSERTER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp new file mode 100755 index 0000000000..b2ab3105a4 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp @@ -0,0 +1,235 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP + +#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) +# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION +#endif + +#include + +#include + +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + + +enum intersection_location_type +{ + location_ok, inside_buffer, location_discard +}; + +class backtrack_for_buffer +{ +public : + typedef detail::overlay::backtrack_state state_type; + + template + < + typename Operation, + typename Rings, + typename Turns, + typename Geometry, + typename RobustPolicy, + typename Visitor + > + static inline void apply(std::size_t size_at_start, + Rings& rings, typename boost::range_value::type& ring, + Turns& turns, + typename boost::range_value::type const& /*turn*/, + Operation& operation, + detail::overlay::traverse_error_type /*traverse_error*/, + Geometry const& , + Geometry const& , + RobustPolicy const& , + state_type& state, + Visitor& /*visitor*/ + ) + { +#if defined(BOOST_GEOMETRY_COUNT_BACKTRACK_WARNINGS) +extern int g_backtrack_warning_count; +g_backtrack_warning_count++; +#endif +//std::cout << "!"; +//std::cout << "WARNING " << traverse_error_string(traverse_error) << std::endl; + + state.m_good = false; + + // Make bad output clean + rings.resize(size_at_start); + ring.clear(); + + // Reject this as a starting point + operation.visited.set_rejected(); + + // And clear all visit info + clear_visit_info(turns); + } +}; + +struct buffer_overlay_visitor +{ +public : + void print(char const* /*header*/) + { + } + + template + void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/) + { + } + + template + void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/) + { + } + + template + void visit_turns(int , Turns const& ) {} + + template + void visit_clusters(Clusters const& , Turns const& ) {} + + template + void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/) + { + } + + template + void visit_traverse_reject(Turns const& , Turn const& , Operation const& , + detail::overlay::traverse_error_type ) + {} +}; + + +// Should follow traversal-turn-concept (enrichment, visit structure) +// and adds index in piece vector to find it back +template +struct buffer_turn_operation + : public detail::overlay::traversal_turn_operation +{ + signed_size_type piece_index; + signed_size_type index_in_robust_ring; + + inline buffer_turn_operation() + : piece_index(-1) + , index_in_robust_ring(-1) + {} +}; + +// Version for buffer including type of location, is_opposite, and helper variables +template +struct buffer_turn_info + : public detail::overlay::turn_info + < + Point, + SegmentRatio, + buffer_turn_operation + > +{ + typedef Point point_type; + typedef RobustPoint robust_point_type; + + std::size_t turn_index; // TODO: this might go if partition can operate on non-const input + + RobustPoint robust_point; +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + // Will (most probably) be removed later + RobustPoint mapped_robust_point; // alas... we still need to adapt our points, offsetting them 1 integer to be co-located with neighbours +#endif + + + inline RobustPoint const& get_robust_point() const + { +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + return mapped_robust_point; +#endif + return robust_point; + } + + intersection_location_type location; + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + robust_point_type rob_pi, rob_pj, rob_qi, rob_qj; +#endif + + std::size_t count_within; + + bool within_original; + std::size_t count_on_original_boundary; + signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring + + std::size_t count_on_offsetted; + std::size_t count_on_helper; +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + std::size_t count_within_near_offsetted; +#endif + + bool remove_on_multi; + + // Obsolete: + std::size_t count_on_occupied; + std::size_t count_on_multi; + + inline buffer_turn_info() + : turn_index(0) + , location(location_ok) + , count_within(0) + , within_original(false) + , count_on_original_boundary(0) + , count_in_original(0) + , count_on_offsetted(0) + , count_on_helper(0) +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + , count_within_near_offsetted(0) +#endif + , remove_on_multi(false) + , count_on_occupied(0) + , count_on_multi(0) + {} +}; + +struct buffer_operation_less +{ + template + inline bool operator()(Turn const& left, Turn const& right) const + { + segment_identifier const& sl = left.seg_id; + segment_identifier const& sr = right.seg_id; + + // Sort them descending + return sl == sr + ? left.fraction < right.fraction + : sl < sr; + } +}; + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp new file mode 100755 index 0000000000..b29f74bcb6 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -0,0 +1,1438 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2016. +// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +enum segment_relation_code +{ + segment_relation_on_left, + segment_relation_on_right, + segment_relation_within, + segment_relation_disjoint +}; + +/* + * Terminology + * + * Suppose we make a buffer (using blocked corners) of this rectangle: + * + * +-------+ + * | | + * | rect | + * | | + * +-------+ + * + * For the sides we get these four buffered side-pieces (marked with s) + * and four buffered corner pieces (marked with c) + * + * c---+---s---+---c + * | | piece | | <- see below for details of the middle top-side-piece + * +---+-------+---+ + * | | | | + * s | rect | s <- two side pieces left/right of rect + * | | | | + * +---+-------+---+ + * | | piece | | <- one side-piece below, and two corner pieces + * c---+---s---+---c + * + * The outer part of the picture above, using all pieces, + * form together the offsetted ring (marked with o below) + * The 8 pieces are part of the piece collection and use for inside-checks + * The inner parts form (using 1 or 2 points per piece, often co-located) + * form together the robust_polygons (marked with r below) + * The remaining piece-segments are helper-segments (marked with h) + * + * ooooooooooooooooo + * o h h o + * ohhhrrrrrrrrrhhho + * o r r o + * o r r o + * o r r o + * ohhhrrrrrrrrrhhho + * o h h o + * ooooooooooooooooo + * + */ + + +template +struct buffered_piece_collection +{ + typedef buffered_piece_collection this_type; + + typedef typename geometry::point_type::type point_type; + typedef typename geometry::coordinate_type::type coordinate_type; + typedef typename geometry::robust_point_type + < + point_type, + RobustPolicy + >::type robust_point_type; + + // Robust ring/polygon type, always clockwise + typedef geometry::model::ring robust_ring_type; + typedef geometry::model::box robust_box_type; + + typedef typename default_comparable_distance_result + < + robust_point_type + >::type robust_comparable_radius_type; + + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + + typedef typename geometry::rescale_policy_type + < + typename geometry::point_type::type + >::type rescale_policy_type; + + typedef typename geometry::segment_ratio_type + < + point_type, + RobustPolicy + >::type segment_ratio_type; + + typedef buffer_turn_info + < + point_type, + robust_point_type, + segment_ratio_type + > buffer_turn_info_type; + + typedef buffer_turn_operation + < + point_type, + segment_ratio_type + > buffer_turn_operation_type; + + typedef std::vector turn_vector_type; + + struct robust_turn + { + std::size_t turn_index; + int operation_index; + robust_point_type point; + segment_identifier seg_id; + segment_ratio_type fraction; + }; + + struct piece + { + typedef robust_ring_type piece_robust_ring_type; + typedef geometry::section section_type; + + strategy::buffer::piece_type type; + signed_size_type index; + + signed_size_type left_index; // points to previous piece of same ring + signed_size_type right_index; // points to next piece of same ring + + // The next two members (1, 2) form together a complete clockwise ring + // for each piece (with one dupped point) + // The complete clockwise ring is also included as a robust ring (3) + + // 1: half, part of offsetted_rings + segment_identifier first_seg_id; + signed_size_type last_segment_index; // no segment-identifier - it is the same as first_seg_id + signed_size_type offsetted_count; // part in robust_ring which is part of offsetted ring + +#if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS) + // 2: half, not part of offsetted rings - part of robust ring + std::vector helper_points; // 4 points for side, 3 points for join - 0 points for flat-end +#endif + + bool is_convex; + bool is_monotonic_increasing[2]; // 0=x, 1=y + bool is_monotonic_decreasing[2]; // 0=x, 1=y + + // Monotonic sections of pieces around points + std::vector sections; + + // Robust representations + // 3: complete ring + robust_ring_type robust_ring; + + robust_box_type robust_envelope; + robust_box_type robust_offsetted_envelope; + + std::vector robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead + + robust_point_type robust_center; + robust_comparable_radius_type robust_min_comparable_radius; + robust_comparable_radius_type robust_max_comparable_radius; + + piece() + : type(strategy::buffer::piece_type_unknown) + , index(-1) + , left_index(-1) + , right_index(-1) + , last_segment_index(-1) + , offsetted_count(-1) + , is_convex(false) + , robust_min_comparable_radius(0) + , robust_max_comparable_radius(0) + { + is_monotonic_increasing[0] = false; + is_monotonic_increasing[1] = false; + is_monotonic_decreasing[0] = false; + is_monotonic_decreasing[1] = false; + } + }; + + struct robust_original + { + typedef robust_ring_type original_robust_ring_type; + typedef geometry::sections sections_type; + + inline robust_original() + : m_is_interior(false) + , m_has_interiors(true) + {} + + inline robust_original(robust_ring_type const& ring, + bool is_interior, bool has_interiors) + : m_ring(ring) + , m_is_interior(is_interior) + , m_has_interiors(has_interiors) + { + geometry::envelope(m_ring, m_box); + + // create monotonic sections in x-dimension + // The dimension is critical because the direction is later used + // in the optimization for within checks using winding strategy + // and this strategy is scanning in x direction. + typedef boost::mpl::vector_c dimensions; + geometry::sectionalize(m_ring, + detail::no_rescale_policy(), m_sections); + } + + robust_ring_type m_ring; + robust_box_type m_box; + sections_type m_sections; + + bool m_is_interior; + bool m_has_interiors; + }; + + typedef std::vector piece_vector_type; + + piece_vector_type m_pieces; + turn_vector_type m_turns; + signed_size_type m_first_piece_index; + + buffered_ring_collection > offsetted_rings; // indexed by multi_index + std::vector robust_originals; // robust representation of the original(s) + robust_ring_type current_robust_ring; + buffered_ring_collection traversed_rings; + segment_identifier current_segment_id; + + // Specificly for offsetted rings around points + // but also for large joins with many points + typedef geometry::sections sections_type; + sections_type monotonic_sections; + + // Define the clusters, mapping cluster_id -> turns + typedef std::map + < + signed_size_type, + detail::overlay::cluster_info + > cluster_type; + + cluster_type m_clusters; + + + RobustPolicy const& m_robust_policy; + + struct redundant_turn + { + inline bool operator()(buffer_turn_info_type const& turn) const + { + return turn.remove_on_multi; + } + }; + + buffered_piece_collection(RobustPolicy const& robust_policy) + : m_first_piece_index(-1) + , m_robust_policy(robust_policy) + {} + + +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + // Will (most probably) be removed later + template + inline void adapt_mapped_robust_point(OccupationMap const& map, + buffer_turn_info_type& turn, int distance) const + { + for (int x = -distance; x <= distance; x++) + { + for (int y = -distance; y <= distance; y++) + { + robust_point_type rp = turn.robust_point; + geometry::set<0>(rp, geometry::get<0>(rp) + x); + geometry::set<1>(rp, geometry::get<1>(rp) + y); + if (map.find(rp) != map.end()) + { + turn.mapped_robust_point = rp; + return; + } + } + } + } +#endif + + inline void get_occupation( +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + int distance = 0 +#endif + ) + { + typedef occupation_info > + buffer_occupation_info; + + typedef std::map + < + robust_point_type, + buffer_occupation_info, + geometry::less + > occupation_map_type; + + occupation_map_type occupation_map; + + // 1: Add all intersection points to occupation map + typedef typename boost::range_iterator::type + iterator_type; + + for (iterator_type it = boost::begin(m_turns); + it != boost::end(m_turns); + ++it) + { + if (it->location == location_ok) + { +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + if (distance > 0 && ! occupation_map.empty()) + { + adapt_mapped_robust_point(occupation_map, *it, distance); + } +#endif + occupation_map[it->get_robust_point()].count++; + } + } + + // Remove all points with one or more u/u points from the map + // (Alternatively, we could NOT do this here and change all u/u + // behaviour in overlay. Currently nothing is done: each polygon is + // just followed there. We could also always switch polygons there. For + // buffer behaviour, where 3 pieces might meet of which 2 (or more) form + // a u/u turn, this last option would have been better, probably). + for (iterator_type it = boost::begin(m_turns); + it != boost::end(m_turns); + ++it) + { + if (it->both(detail::overlay::operation_union)) + { + typename occupation_map_type::iterator mit = + occupation_map.find(it->get_robust_point()); + + if (mit != occupation_map.end()) + { + occupation_map.erase(mit); + } + } + } + + // 2: Remove all points from map which has only one + typename occupation_map_type::iterator it = occupation_map.begin(); + while (it != occupation_map.end()) + { + if (it->second.count <= 1) + { + typename occupation_map_type::iterator to_erase = it; + ++it; + occupation_map.erase(to_erase); + } + else + { + ++it; + } + } + + if (occupation_map.empty()) + { + return; + } + + // 3: Add vectors (incoming->intersection-point, + // intersection-point -> outgoing) + // for all (co-located) points still present in the map + + for (iterator_type it = boost::begin(m_turns); + it != boost::end(m_turns); + ++it) + { + typename occupation_map_type::iterator mit = + occupation_map.find(it->get_robust_point()); + + if (mit != occupation_map.end()) + { + buffer_occupation_info& info = mit->second; + for (int i = 0; i < 2; i++) + { + add_incoming_and_outgoing_angles(it->get_robust_point(), *it, + m_pieces, + i, it->operations[i].seg_id, + info); + } + + it->count_on_multi++; + } + } + +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + // X: Check rounding issues + if (distance == 0) + { + for (typename occupation_map_type::const_iterator it = occupation_map.begin(); + it != occupation_map.end(); ++it) + { + if (it->second.has_rounding_issues(it->first)) + { + if(distance == 0) + { + get_occupation(distance + 1); + return; + } + } + } + } +#endif + + // Get left turns from all clusters + for (typename occupation_map_type::iterator it = occupation_map.begin(); + it != occupation_map.end(); ++it) + { + it->second.get_left_turns(it->first, m_turns); + } + } + + inline void classify_turns(bool linear) + { + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it) + { + if (it->count_within > 0) + { + it->location = inside_buffer; + } + if (it->count_on_original_boundary > 0 && ! linear) + { + it->location = inside_buffer; + } +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + if (it->count_within_near_offsetted > 0) + { + // Within can have in rare cases a rounding issue. We don't discard this + // point, so it can be used to continue started rings in traversal. But + // will never start a new ring from this type of points. + it->operations[0].enriched.startable = false; + it->operations[1].enriched.startable = false; + } +#endif + } + } + + template + inline void check_remaining_points(DistanceStrategy const& distance_strategy) + { + // Check if a turn is inside any of the originals + + turn_in_original_visitor visitor(m_turns); + geometry::partition + < + robust_box_type, + turn_get_box, turn_in_original_ovelaps_box, + original_get_box, original_ovelaps_box, + include_turn_policy, detail::partition::include_all_policy + >::apply(m_turns, robust_originals, visitor); + + bool const deflate = distance_strategy.negative(); + + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it) + { + buffer_turn_info_type& turn = *it; + if (turn.location == location_ok) + { + if (deflate && turn.count_in_original <= 0) + { + // For deflate: it is not in original, discard + turn.location = location_discard; + } + else if (! deflate && turn.count_in_original > 0) + { + // For inflate: it is in original, discard + turn.location = location_discard; + } + } + } + } + + inline bool assert_indices_in_robust_rings() const + { + geometry::equal_to comparator; + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it) + { + for (int i = 0; i < 2; i++) + { + robust_point_type const &p1 + = m_pieces[it->operations[i].piece_index].robust_ring + [it->operations[i].index_in_robust_ring]; + robust_point_type const &p2 = it->robust_point; + if (! comparator(p1, p2)) + { + return false; + } + } + } + return true; + } + + inline void insert_rescaled_piece_turns() + { + // Add rescaled turn points to corresponding pieces + // (after this, each turn occurs twice) + std::size_t index = 0; + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index) + { + geometry::recalculate(it->robust_point, it->point, m_robust_policy); +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + it->mapped_robust_point = it->robust_point; +#endif + + robust_turn turn; + it->turn_index = index; + turn.turn_index = index; + turn.point = it->robust_point; + for (int i = 0; i < 2; i++) + { + turn.operation_index = i; + turn.seg_id = it->operations[i].seg_id; + turn.fraction = it->operations[i].fraction; + + piece& pc = m_pieces[it->operations[i].piece_index]; + pc.robust_turns.push_back(turn); + + // Take into account for the box (intersection points should fall inside, + // but in theory they can be one off because of rounding + geometry::expand(pc.robust_envelope, it->robust_point); + geometry::expand(pc.robust_offsetted_envelope, it->robust_point); + } + } + +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // Insert all rescaled turn-points into these rings, to form a + // reliable integer-based ring. All turns can be compared (inside) to this + // rings to see if they are inside. + + for (typename boost::range_iterator::type + it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it) + { + piece& pc = *it; + signed_size_type piece_segment_index = pc.first_seg_id.segment_index; + if (! pc.robust_turns.empty()) + { + if (pc.robust_turns.size() > 1u) + { + std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less()); + } + // Walk through them, in reverse to insert at right index + signed_size_type index_offset = static_cast(pc.robust_turns.size()) - 1; + for (typename boost::range_reverse_iterator >::type + rit = boost::const_rbegin(pc.robust_turns); + rit != boost::const_rend(pc.robust_turns); + ++rit, --index_offset) + { + signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index; + BOOST_GEOMETRY_ASSERT + ( + index_in_vector > 0 + && index_in_vector < pc.offsetted_count + ); + + pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point); + pc.offsetted_count++; + + m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset; + } + } + } + + BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings()); +#endif + } + + template + static inline void determine_monotonicity(piece& pc, + robust_point_type const& current, + robust_point_type const& next) + { + if (geometry::get(current) >= geometry::get(next)) + { + pc.is_monotonic_increasing[Dimension] = false; + } + if (geometry::get(current) <= geometry::get(next)) + { + pc.is_monotonic_decreasing[Dimension] = false; + } + } + + static inline void determine_properties(piece& pc) + { + pc.is_monotonic_increasing[0] = true; + pc.is_monotonic_increasing[1] = true; + pc.is_monotonic_decreasing[0] = true; + pc.is_monotonic_decreasing[1] = true; + + pc.is_convex = geometry::is_convex(pc.robust_ring); + + if (pc.offsetted_count < 2) + { + return; + } + + typename robust_ring_type::const_iterator current = pc.robust_ring.begin(); + typename robust_ring_type::const_iterator next = current + 1; + + for (signed_size_type i = 1; i < pc.offsetted_count; i++) + { + determine_monotonicity<0>(pc, *current, *next); + determine_monotonicity<1>(pc, *current, *next); + current = next; + ++next; + } + } + + void determine_properties() + { + for (typename piece_vector_type::iterator it = boost::begin(m_pieces); + it != boost::end(m_pieces); + ++it) + { + determine_properties(*it); + } + } + + inline void reverse_negative_robust_rings() + { + for (typename piece_vector_type::iterator it = boost::begin(m_pieces); + it != boost::end(m_pieces); + ++it) + { + piece& pc = *it; + if (geometry::area(pc.robust_ring) < 0) + { + // Rings can be ccw: + // - in a concave piece + // - in a line-buffer with a negative buffer-distance + std::reverse(pc.robust_ring.begin(), pc.robust_ring.end()); + } + } + } + + inline void prepare_buffered_point_piece(piece& pc) + { + // create monotonic sections in y-dimension + typedef boost::mpl::vector_c dimensions; + geometry::sectionalize(pc.robust_ring, + detail::no_rescale_policy(), pc.sections); + + // Determine min/max radius + typedef geometry::model::referring_segment + robust_segment_type; + + typename robust_ring_type::const_iterator current = pc.robust_ring.begin(); + typename robust_ring_type::const_iterator next = current + 1; + + for (signed_size_type i = 1; i < pc.offsetted_count; i++) + { + robust_segment_type s(*current, *next); + robust_comparable_radius_type const d + = geometry::comparable_distance(pc.robust_center, s); + + if (i == 1 || d < pc.robust_min_comparable_radius) + { + pc.robust_min_comparable_radius = d; + } + if (i == 1 || d > pc.robust_max_comparable_radius) + { + pc.robust_max_comparable_radius = d; + } + + current = next; + ++next; + } + } + + inline void prepare_buffered_point_pieces() + { + for (typename piece_vector_type::iterator it = boost::begin(m_pieces); + it != boost::end(m_pieces); + ++it) + { + if (it->type == geometry::strategy::buffer::buffered_point) + { + prepare_buffered_point_piece(*it); + } + } + } + + inline void get_turns() + { + for(typename boost::range_iterator::type it + = boost::begin(monotonic_sections); + it != boost::end(monotonic_sections); + ++it) + { + enlarge_box(it->bounding_box, 1); + } + + { + // Calculate the turns + piece_turn_visitor + < + piece_vector_type, + buffered_ring_collection >, + turn_vector_type, + RobustPolicy + > visitor(m_pieces, offsetted_rings, m_turns, m_robust_policy); + + geometry::partition + < + robust_box_type, + detail::section::get_section_box, + detail::section::overlaps_section_box + >::apply(monotonic_sections, visitor); + } + + insert_rescaled_piece_turns(); + + reverse_negative_robust_rings(); + + determine_properties(); + + prepare_buffered_point_pieces(); + + { + // Check if it is inside any of the pieces + turn_in_piece_visitor + < + turn_vector_type, piece_vector_type + > visitor(m_turns, m_pieces); + + geometry::partition + < + robust_box_type, + turn_get_box, turn_ovelaps_box, + piece_get_box, piece_ovelaps_box + >::apply(m_turns, m_pieces, visitor); + + } + } + + inline void start_new_ring() + { + signed_size_type const n = static_cast(offsetted_rings.size()); + current_segment_id.source_index = 0; + current_segment_id.multi_index = n; + current_segment_id.ring_index = -1; + current_segment_id.segment_index = 0; + + offsetted_rings.resize(n + 1); + current_robust_ring.clear(); + + m_first_piece_index = static_cast(boost::size(m_pieces)); + } + + inline void abort_ring() + { + // Remove all created pieces for this ring, sections, last offsetted + while (! m_pieces.empty() + && m_pieces.back().first_seg_id.multi_index + == current_segment_id.multi_index) + { + m_pieces.erase(m_pieces.end() - 1); + } + + while (! monotonic_sections.empty() + && monotonic_sections.back().ring_id.multi_index + == current_segment_id.multi_index) + { + monotonic_sections.erase(monotonic_sections.end() - 1); + } + + offsetted_rings.erase(offsetted_rings.end() - 1); + current_robust_ring.clear(); + + m_first_piece_index = -1; + } + + inline void update_closing_point() + { + BOOST_GEOMETRY_ASSERT(! offsetted_rings.empty()); + buffered_ring& added = offsetted_rings.back(); + if (! boost::empty(added)) + { + range::back(added) = range::front(added); + } + } + + inline void update_last_point(point_type const& p, + buffered_ring& ring) + { + // For the first point of a new piece, and there were already + // points in the offsetted ring, for some piece types the first point + // is a duplicate of the last point of the previous piece. + + // TODO: disable that, that point should not be added + + // For now, it is made equal because due to numerical instability, + // it can be a tiny bit off, possibly causing a self-intersection + + BOOST_GEOMETRY_ASSERT(boost::size(m_pieces) > 0); + if (! ring.empty() + && current_segment_id.segment_index + == m_pieces.back().first_seg_id.segment_index) + { + ring.back() = p; + } + } + + inline void set_piece_center(point_type const& center) + { + BOOST_GEOMETRY_ASSERT(! m_pieces.empty()); + geometry::recalculate(m_pieces.back().robust_center, center, + m_robust_policy); + } + + inline void finish_ring(strategy::buffer::result_code code, + bool is_interior = false, bool has_interiors = false) + { + if (code == strategy::buffer::result_error_numerical) + { + abort_ring(); + return; + } + + if (m_first_piece_index == -1) + { + return; + } + + if (m_first_piece_index < static_cast(boost::size(m_pieces))) + { + // If piece was added + // Reassign left-of-first and right-of-last + geometry::range::at(m_pieces, m_first_piece_index).left_index + = static_cast(boost::size(m_pieces)) - 1; + geometry::range::back(m_pieces).right_index = m_first_piece_index; + } + m_first_piece_index = -1; + + update_closing_point(); + + if (! current_robust_ring.empty()) + { + BOOST_GEOMETRY_ASSERT + ( + geometry::equals(current_robust_ring.front(), + current_robust_ring.back()) + ); + + robust_originals.push_back( + robust_original(current_robust_ring, + is_interior, has_interiors)); + } + } + + inline void set_current_ring_concave() + { + BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0); + offsetted_rings.back().has_concave = true; + } + + inline signed_size_type add_point(point_type const& p) + { + BOOST_GEOMETRY_ASSERT(boost::size(offsetted_rings) > 0); + + buffered_ring& current_ring = offsetted_rings.back(); + update_last_point(p, current_ring); + + current_segment_id.segment_index++; + current_ring.push_back(p); + return static_cast(current_ring.size()); + } + + //------------------------------------------------------------------------- + + inline piece& create_piece(strategy::buffer::piece_type type, + bool decrease_segment_index_by_one) + { + if (type == strategy::buffer::buffered_concave) + { + offsetted_rings.back().has_concave = true; + } + + piece pc; + pc.type = type; + pc.index = static_cast(boost::size(m_pieces)); + + current_segment_id.piece_index = pc.index; + + pc.first_seg_id = current_segment_id; + + + // Assign left/right (for first/last piece per ring they will be re-assigned later) + pc.left_index = pc.index - 1; + pc.right_index = pc.index + 1; + + std::size_t const n = boost::size(offsetted_rings.back()); + pc.first_seg_id.segment_index = decrease_segment_index_by_one ? n - 1 : n; + pc.last_segment_index = pc.first_seg_id.segment_index; + + m_pieces.push_back(pc); + return m_pieces.back(); + } + + inline void init_rescale_piece(piece& pc, std::size_t helper_points_size) + { + if (pc.first_seg_id.segment_index < 0) + { + // This indicates an error situation: an earlier piece was empty + // It currently does not happen + // std::cout << "EMPTY " << pc.type << " " << pc.index << " " << pc.first_seg_id.multi_index << std::endl; + pc.offsetted_count = 0; + return; + } + + BOOST_GEOMETRY_ASSERT(pc.first_seg_id.multi_index >= 0); + BOOST_GEOMETRY_ASSERT(pc.last_segment_index >= 0); + + pc.offsetted_count = pc.last_segment_index - pc.first_seg_id.segment_index; + BOOST_GEOMETRY_ASSERT(pc.offsetted_count >= 0); + + pc.robust_ring.reserve(pc.offsetted_count + helper_points_size); + + // Add rescaled offsetted segments + { + buffered_ring const& ring = offsetted_rings[pc.first_seg_id.multi_index]; + + typedef typename boost::range_iterator >::type it_type; + for (it_type it = boost::begin(ring) + pc.first_seg_id.segment_index; + it != boost::begin(ring) + pc.last_segment_index; + ++it) + { + robust_point_type point; + geometry::recalculate(point, *it, m_robust_policy); + pc.robust_ring.push_back(point); + } + } + } + + inline robust_point_type add_helper_point(piece& pc, const point_type& point) + { +#if defined(BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS) + pc.helper_points.push_back(point); +#endif + + robust_point_type rob_point; + geometry::recalculate(rob_point, point, m_robust_policy); + pc.robust_ring.push_back(rob_point); + return rob_point; + } + + // TODO: this is shared with sectionalize, move to somewhere else (assign?) + template + inline void enlarge_box(Box& box, Value value) + { + geometry::set<0, 0>(box, geometry::get<0, 0>(box) - value); + geometry::set<0, 1>(box, geometry::get<0, 1>(box) - value); + geometry::set<1, 0>(box, geometry::get<1, 0>(box) + value); + geometry::set<1, 1>(box, geometry::get<1, 1>(box) + value); + } + + inline void calculate_robust_envelope(piece& pc) + { + if (pc.offsetted_count == 0) + { + return; + } + + geometry::envelope(pc.robust_ring, pc.robust_envelope); + + geometry::assign_inverse(pc.robust_offsetted_envelope); + for (signed_size_type i = 0; i < pc.offsetted_count; i++) + { + geometry::expand(pc.robust_offsetted_envelope, pc.robust_ring[i]); + } + + // Take roundings into account, enlarge boxes with 1 integer + enlarge_box(pc.robust_envelope, 1); + enlarge_box(pc.robust_offsetted_envelope, 1); + } + + inline void sectionalize(piece& pc) + { + + buffered_ring const& ring = offsetted_rings.back(); + + typedef geometry::detail::sectionalize::sectionalize_part + < + point_type, + boost::mpl::vector_c // x,y dimension + > sectionalizer; + + // Create a ring-identifier. The source-index is the piece index + // The multi_index is as in this collection (the ring), but not used here + // The ring_index is not used + ring_identifier ring_id(pc.index, pc.first_seg_id.multi_index, -1); + + sectionalizer::apply(monotonic_sections, + boost::begin(ring) + pc.first_seg_id.segment_index, + boost::begin(ring) + pc.last_segment_index, + m_robust_policy, + ring_id, 10); + } + + inline void finish_piece(piece& pc) + { + init_rescale_piece(pc, 0u); + calculate_robust_envelope(pc); + sectionalize(pc); + } + + inline void finish_piece(piece& pc, + const point_type& point1, + const point_type& point2, + const point_type& point3) + { + init_rescale_piece(pc, 3u); + if (pc.offsetted_count == 0) + { + return; + } + + add_helper_point(pc, point1); + robust_point_type mid_point = add_helper_point(pc, point2); + add_helper_point(pc, point3); + calculate_robust_envelope(pc); + sectionalize(pc); + + current_robust_ring.push_back(mid_point); + } + + inline void finish_piece(piece& pc, + const point_type& point1, + const point_type& point2, + const point_type& point3, + const point_type& point4) + { + init_rescale_piece(pc, 4u); + add_helper_point(pc, point1); + robust_point_type mid_point2 = add_helper_point(pc, point2); + robust_point_type mid_point1 = add_helper_point(pc, point3); + add_helper_point(pc, point4); + sectionalize(pc); + calculate_robust_envelope(pc); + + // Add mid-points in other order to current helper_ring + current_robust_ring.push_back(mid_point1); + current_robust_ring.push_back(mid_point2); + } + + inline void add_piece(strategy::buffer::piece_type type, point_type const& p, + point_type const& b1, point_type const& b2) + { + piece& pc = create_piece(type, false); + add_point(b1); + pc.last_segment_index = add_point(b2); + finish_piece(pc, b2, p, b1); + } + + template + inline void add_range_to_piece(piece& pc, Range const& range, bool add_front) + { + BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u); + + typename Range::const_iterator it = boost::begin(range); + + // If it follows a non-join (so basically the same piece-type) point b1 should be added. + // There should be two intersections later and it should be discarded. + // But for now we need it to calculate intersections + if (add_front) + { + add_point(*it); + } + + for (++it; it != boost::end(range); ++it) + { + pc.last_segment_index = add_point(*it); + } + } + + + template + inline void add_piece(strategy::buffer::piece_type type, Range const& range, + bool decrease_segment_index_by_one) + { + piece& pc = create_piece(type, decrease_segment_index_by_one); + + if (boost::size(range) > 0u) + { + add_range_to_piece(pc, range, offsetted_rings.back().empty()); + } + finish_piece(pc); + } + + template + inline void add_side_piece(point_type const& p1, point_type const& p2, + Range const& range, bool first) + { + BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u); + + piece& pc = create_piece(strategy::buffer::buffered_segment, ! first); + add_range_to_piece(pc, range, first); + finish_piece(pc, range.back(), p2, p1, range.front()); + } + + template + inline void add_piece(strategy::buffer::piece_type type, + point_type const& p, Range const& range) + { + piece& pc = create_piece(type, true); + + if (boost::size(range) > 0u) + { + add_range_to_piece(pc, range, offsetted_rings.back().empty()); + finish_piece(pc, range.back(), p, range.front()); + } + else + { + finish_piece(pc); + } + } + + template + inline void add_endcap(EndcapStrategy const& strategy, Range const& range, + point_type const& end_point) + { + boost::ignore_unused(strategy); + + if (range.empty()) + { + return; + } + strategy::buffer::piece_type pt = strategy.get_piece_type(); + if (pt == strategy::buffer::buffered_flat_end) + { + // It is flat, should just be added, without helper segments + add_piece(pt, range, true); + } + else + { + // Normal case, it has an "inside", helper segments should be added + add_piece(pt, end_point, range); + } + } + + //------------------------------------------------------------------------- + + inline void enrich() + { + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy_type; + + enrich_intersection_points(m_turns, + m_clusters, offsetted_rings, offsetted_rings, + m_robust_policy, side_strategy_type()); + } + + // Discards all rings which do have not-OK intersection points only. + // Those can never be traversed and should not be part of the output. + inline void discard_rings() + { + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it) + { + if (it->location != location_ok) + { + offsetted_rings[it->operations[0].seg_id.multi_index].has_discarded_intersections = true; + offsetted_rings[it->operations[1].seg_id.multi_index].has_discarded_intersections = true; + } + else + { + offsetted_rings[it->operations[0].seg_id.multi_index].has_accepted_intersections = true; + offsetted_rings[it->operations[1].seg_id.multi_index].has_accepted_intersections = true; + } + } + } + + inline bool point_coveredby_original(point_type const& point) + { + robust_point_type any_point; + geometry::recalculate(any_point, point, m_robust_policy); + + signed_size_type count_in_original = 0; + + // Check of the robust point of this outputted ring is in + // any of the robust original rings + // This can go quadratic if the input has many rings, and there + // are many untouched deflated rings around + for (typename std::vector::const_iterator it + = robust_originals.begin(); + it != robust_originals.end(); + ++it) + { + robust_original const& original = *it; + if (detail::disjoint::disjoint_point_box(any_point, + original.m_box)) + { + continue; + } + + int const geometry_code + = detail::within::point_in_geometry(any_point, + original.m_ring); + + if (geometry_code == -1) + { + // Outside, continue + continue; + } + + // Apply for possibly nested interior rings + if (original.m_is_interior) + { + count_in_original--; + } + else if (original.m_has_interiors) + { + count_in_original++; + } + else + { + // Exterior ring without interior rings + return true; + } + } + return count_in_original > 0; + } + + // For a deflate, all rings around inner rings which are untouched + // (no intersections/turns) and which are OUTSIDE the original should + // be discarded + inline void discard_nonintersecting_deflated_rings() + { + for(typename buffered_ring_collection >::iterator it + = boost::begin(offsetted_rings); + it != boost::end(offsetted_rings); + ++it) + { + buffered_ring& ring = *it; + if (! ring.has_intersections() + && boost::size(ring) > 0u + && geometry::area(ring) < 0) + { + if (! point_coveredby_original(geometry::range::front(ring))) + { + ring.is_untouched_outside_original = true; + } + } + } + } + + inline void block_turns() + { + // To fix left-turn issues like #rt_u13 + // But currently it causes more other issues than it fixes +// m_turns.erase +// ( +// std::remove_if(boost::begin(m_turns), boost::end(m_turns), +// redundant_turn()), +// boost::end(m_turns) +// ); + + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it) + { + buffer_turn_info_type& turn = *it; + if (turn.location != location_ok) + { + // Discard this turn (don't set it to blocked to avoid colocated + // clusters being discarded afterwards + turn.discarded = true; + } + } + } + + inline void traverse() + { + typedef detail::overlay::traverse + < + false, false, + buffered_ring_collection >, + buffered_ring_collection >, + overlay_buffer, + backtrack_for_buffer + > traverser; + + traversed_rings.clear(); + buffer_overlay_visitor visitor; + traverser::apply(offsetted_rings, offsetted_rings, + m_robust_policy, m_turns, traversed_rings, + m_clusters, visitor); + } + + inline void reverse() + { + for(typename buffered_ring_collection >::iterator it = boost::begin(offsetted_rings); + it != boost::end(offsetted_rings); + ++it) + { + if (! it->has_intersections()) + { + std::reverse(it->begin(), it->end()); + } + } + for (typename boost::range_iterator >::type + it = boost::begin(traversed_rings); + it != boost::end(traversed_rings); + ++it) + { + std::reverse(it->begin(), it->end()); + } + + } + + template + inline OutputIterator assign(OutputIterator out) const + { + typedef detail::overlay::ring_properties properties; + + std::map selected; + + // Select all rings which do not have any self-intersection + // Inner rings, for deflate, which do not have intersections, and + // which are outside originals, are skipped + // (other ones should be traversed) + signed_size_type index = 0; + for(typename buffered_ring_collection >::const_iterator it = boost::begin(offsetted_rings); + it != boost::end(offsetted_rings); + ++it, ++index) + { + if (! it->has_intersections() + && ! it->is_untouched_outside_original) + { + properties p = properties(*it); + if (p.valid) + { + ring_identifier id(0, index, -1); + selected[id] = p; + } + } + } + + // Select all created rings + index = 0; + for (typename boost::range_iterator const>::type + it = boost::begin(traversed_rings); + it != boost::end(traversed_rings); + ++it, ++index) + { + properties p = properties(*it); + if (p.valid) + { + ring_identifier id(2, index, -1); + selected[id] = p; + } + } + + detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true); + return detail::overlay::add_rings(selected, offsetted_rings, traversed_rings, out); + } + +}; + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_PIECE_COLLECTION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp new file mode 100755 index 0000000000..aef2f2a533 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp @@ -0,0 +1,282 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING + + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +struct buffered_ring_collection_tag : polygonal_tag, multi_tag +{}; + + +template +struct buffered_ring : public Ring +{ + bool has_concave; + bool has_accepted_intersections; + bool has_discarded_intersections; + bool is_untouched_outside_original; + + inline buffered_ring() + : has_concave(false) + , has_accepted_intersections(false) + , has_discarded_intersections(false) + , is_untouched_outside_original(false) + {} + + inline bool discarded() const + { + return has_discarded_intersections && ! has_accepted_intersections; + } + inline bool has_intersections() const + { + return has_discarded_intersections || has_accepted_intersections; + } +}; + +// This is a collection now special for overlay (needs vector of rings) +template +struct buffered_ring_collection : public std::vector +{ +}; + +}} // namespace detail::buffer + + +// Turn off concept checking (for now) +namespace dispatch +{ +template +struct check +{ +}; + +} + + +#endif // DOXYGEN_NO_DETAIL + + + +// Register the types +namespace traits +{ + + +template +struct tag > +{ + typedef ring_tag type; +}; + + +template +struct point_order > +{ + static const order_selector value = geometry::point_order::value; +}; + + +template +struct closure > +{ + static const closure_selector value = geometry::closure::value; +}; + + +template +struct point_type > +{ + typedef typename geometry::point_type::type type; +}; + +template +struct tag > +{ + typedef geometry::detail::buffer::buffered_ring_collection_tag type; +}; + + +} // namespace traits + + + + +namespace core_dispatch +{ + +template +struct ring_type +< + detail::buffer::buffered_ring_collection_tag, + detail::buffer::buffered_ring_collection +> +{ + typedef Ring type; +}; + + +// There is a specific tag, so this specialization cannot be placed in traits +template +struct point_order + > > +{ + static const order_selector value + = core_dispatch::point_order::value; +}; + + +} + + +template <> +struct single_tag_of +{ + typedef ring_tag type; +}; + + +namespace dispatch +{ + +template +< + typename MultiRing, + bool Reverse, + typename SegmentIdentifier, + typename PointOut +> +struct copy_segment_point + < + detail::buffer::buffered_ring_collection_tag, + MultiRing, + Reverse, + SegmentIdentifier, + PointOut + > + : detail::copy_segments::copy_segment_point_multi + < + MultiRing, + SegmentIdentifier, + PointOut, + detail::copy_segments::copy_segment_point_range + < + typename boost::range_value::type, + Reverse, + SegmentIdentifier, + PointOut + > + > +{}; + + +template +struct copy_segments + < + detail::buffer::buffered_ring_collection_tag, + Reverse + > + : detail::copy_segments::copy_segments_multi + < + detail::copy_segments::copy_segments_ring + > +{}; + +template +struct within +< + Point, + MultiGeometry, + point_tag, + detail::buffer::buffered_ring_collection_tag +> +{ + template + static inline bool apply(Point const& point, + MultiGeometry const& multi, Strategy const& strategy) + { + return detail::within::point_in_geometry(point, multi, strategy) == 1; + } +}; + + +template +struct is_empty + : detail::is_empty::multi_is_empty +{}; + + +template +struct envelope + : detail::envelope::envelope_multi_range + < + detail::envelope::envelope_range + > +{}; + + +} // namespace dispatch + +namespace detail { namespace overlay +{ + +template<> +struct get_ring +{ + template + static inline typename ring_type::type const& apply( + ring_identifier const& id, + MultiGeometry const& multi_ring) + { + BOOST_GEOMETRY_ASSERT + ( + id.multi_index >= 0 + && id.multi_index < int(boost::size(multi_ring)) + ); + return get_ring::apply(id, multi_ring[id.multi_index]); + } +}; + +}} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp new file mode 100755 index 0000000000..5217d2adc4 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -0,0 +1,294 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) +struct buffer_assign_turn +{ + static bool const include_no_turn = false; + static bool const include_degenerate = false; + static bool const include_opposite = false; + + template + < + typename Info, + typename Point1, + typename Point2, + typename IntersectionInfo + > + static inline void apply(Info& info, + Point1 const& /*p1*/, + Point2 const& /*p2*/, + IntersectionInfo const& iinfo) + { + info.rob_pi = iinfo.rpi(); + info.rob_pj = iinfo.rpj(); + info.rob_qi = iinfo.rqi(); + info.rob_qj = iinfo.rqj(); + } + +}; +#endif + +template +< + typename Pieces, + typename Rings, + typename Turns, + typename RobustPolicy +> +class piece_turn_visitor +{ + Pieces const& m_pieces; + Rings const& m_rings; + Turns& m_turns; + RobustPolicy const& m_robust_policy; + + template + inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const + { + if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index) + { + return false; + } + + return piece1.index == piece2.left_index + || piece1.index == piece2.right_index; + } + + template + inline bool is_on_same_convex_ring(Piece const& piece1, Piece const& piece2) const + { + if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index) + { + return false; + } + + return ! m_rings[piece1.first_seg_id.multi_index].has_concave; + } + + template + inline void move_to_next_point(Range const& range, Iterator& next) const + { + ++next; + if (next == boost::end(range)) + { + next = boost::begin(range) + 1; + } + } + + template + inline Iterator next_point(Range const& range, Iterator it) const + { + Iterator result = it; + move_to_next_point(range, result); + // TODO: we could use either piece-boundaries, or comparison with + // robust points, to check if the point equals the last one + while(geometry::equals(*it, *result)) + { + move_to_next_point(range, result); + } + return result; + } + + template + inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond, + signed_size_type& index, int dir, Box const& other_bounding_box) + { + for(; it_begin != it_beyond + && it_begin + 1 != it_beyond + && detail::section::preceding(dir, *(it_begin + 1), + other_bounding_box, m_robust_policy); + ++it_begin, index++) + {} + } + + template + inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond, + int dir, Box const& other_bounding_box) + { + while (it_beyond != it_begin + && it_beyond - 1 != it_begin + && it_beyond - 2 != it_begin) + { + if (detail::section::exceeding(dir, *(it_beyond - 2), + other_bounding_box, m_robust_policy)) + { + --it_beyond; + } + else + { + return; + } + } + } + + template + inline void calculate_turns(Piece const& piece1, Piece const& piece2, + Section const& section1, Section const& section2) + { + typedef typename boost::range_value::type ring_type; + typedef typename boost::range_value::type turn_type; + typedef typename boost::range_iterator::type iterator; + + signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index; + signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index; + if (piece1_first_index < 0 || piece2_first_index < 0) + { + return; + } + + // Get indices of part of offsetted_rings for this monotonic section: + signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index; + signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index; + + // index of last point in section, beyond-end is one further + signed_size_type const sec1_last_index = piece1_first_index + section1.end_index; + signed_size_type const sec2_last_index = piece2_first_index + section2.end_index; + + // get geometry and iterators over these sections + ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index]; + iterator it1_first = boost::begin(ring1) + sec1_first_index; + iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1; + + ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index]; + iterator it2_first = boost::begin(ring2) + sec2_first_index; + iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1; + + // Set begin/end of monotonic ranges, in both x/y directions + signed_size_type index1 = sec1_first_index; + move_begin_iterator<0>(it1_first, it1_beyond, index1, + section1.directions[0], section2.bounding_box); + move_end_iterator<0>(it1_first, it1_beyond, + section1.directions[0], section2.bounding_box); + move_begin_iterator<1>(it1_first, it1_beyond, index1, + section1.directions[1], section2.bounding_box); + move_end_iterator<1>(it1_first, it1_beyond, + section1.directions[1], section2.bounding_box); + + signed_size_type index2 = sec2_first_index; + move_begin_iterator<0>(it2_first, it2_beyond, index2, + section2.directions[0], section1.bounding_box); + move_end_iterator<0>(it2_first, it2_beyond, + section2.directions[0], section1.bounding_box); + move_begin_iterator<1>(it2_first, it2_beyond, index2, + section2.directions[1], section1.bounding_box); + move_end_iterator<1>(it2_first, it2_beyond, + section2.directions[1], section1.bounding_box); + + turn_type the_model; + the_model.operations[0].piece_index = piece1.index; + the_model.operations[0].seg_id = piece1.first_seg_id; + the_model.operations[0].seg_id.segment_index = index1; // override + + iterator it1 = it1_first; + for (iterator prev1 = it1++; + it1 != it1_beyond; + prev1 = it1++, the_model.operations[0].seg_id.segment_index++) + { + the_model.operations[1].piece_index = piece2.index; + the_model.operations[1].seg_id = piece2.first_seg_id; + the_model.operations[1].seg_id.segment_index = index2; // override + + iterator next1 = next_point(ring1, it1); + + iterator it2 = it2_first; + for (iterator prev2 = it2++; + it2 != it2_beyond; + prev2 = it2++, the_model.operations[1].seg_id.segment_index++) + { + iterator next2 = next_point(ring2, it2); + + // TODO: internally get_turn_info calculates robust points. + // But they are already calculated. + // We should be able to use them. + // this means passing them to this visitor, + // and iterating in sync with them... + typedef detail::overlay::get_turn_info + < +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + buffer_assign_turn +#else + detail::overlay::assign_null_policy +#endif + > turn_policy; + + turn_policy::apply(*prev1, *it1, *next1, + *prev2, *it2, *next2, + false, false, false, false, + the_model, m_robust_policy, + std::back_inserter(m_turns)); + } + } + } + +public: + + piece_turn_visitor(Pieces const& pieces, + Rings const& ring_collection, + Turns& turns, + RobustPolicy const& robust_policy) + : m_pieces(pieces) + , m_rings(ring_collection) + , m_turns(turns) + , m_robust_policy(robust_policy) + {} + + template + inline void apply(Section const& section1, Section const& section2, + bool first = true) + { + boost::ignore_unused_variable_warning(first); + + typedef typename boost::range_value::type piece_type; + piece_type const& piece1 = m_pieces[section1.ring_id.source_index]; + piece_type const& piece2 = m_pieces[section2.ring_id.source_index]; + + if ( piece1.index == piece2.index + || is_adjacent(piece1, piece2) + || is_on_same_convex_ring(piece1, piece2) + || detail::disjoint::disjoint_box_box(section1.bounding_box, + section2.bounding_box) ) + { + return; + } + + calculate_turns(piece1, piece2, section1, section2); + } +}; + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp new file mode 100755 index 0000000000..f02c39a7df --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp @@ -0,0 +1,88 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP + + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + + +// TODO: once change this to proper strategy +// It is different from current segment intersection because these are not segments but lines +// If we have the Line concept, we can create a strategy +// Assumes a convex corner +struct line_line_intersection +{ + + template + static inline strategy::buffer::join_selector apply(Point const& pi, Point const& pj, + Point const& qi, Point const& qj, Point& ip) + { + // See http://mathworld.wolfram.com/Line-LineIntersection.html + typedef typename coordinate_type::type coordinate_type; + + coordinate_type const denominator + = determinant(get<0>(pi) - get<0>(pj), + get<1>(pi) - get<1>(pj), + get<0>(qi) - get<0>(qj), + get<1>(qi) - get<1>(qj)); + + // Even if the corner was checked before (so it is convex now), that + // was done on the original geometry. This function runs on the buffered + // geometries, where sides are generated and might be slightly off. In + // Floating Point, that slightly might just exceed the limit and we have + // to check it again. + + // For round joins, it will not be used at all. + // For miter joints, there is a miter limit + // If segments are parallel/collinear we must be distinguish two cases: + // they continue each other, or they form a spike + if (math::equals(denominator, coordinate_type())) + { + return parallel_continue(get<0>(qj) - get<0>(qi), + get<1>(qj) - get<1>(qi), + get<0>(pj) - get<0>(pi), + get<1>(pj) - get<1>(pi)) + ? strategy::buffer::join_continue + : strategy::buffer::join_spike + ; + } + + coordinate_type d1 = determinant(get<0>(pi), get<1>(pi), get<0>(pj), get<1>(pj)); + coordinate_type d2 = determinant(get<0>(qi), get<1>(qi), get<0>(qj), get<1>(qj)); + + double const multiplier = 1.0 / denominator; + + set<0>(ip, determinant(d1, get<0>(pi) - get<0>(pj), d2, get<0>(qi) - get<0>(qj)) * multiplier); + set<1>(ip, determinant(d1, get<1>(pi) - get<1>(pj), d2, get<1>(qi) - get<1>(qj)) * multiplier); + + return strategy::buffer::join_convex; + } +}; + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/parallel_continue.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/parallel_continue.hpp new file mode 100755 index 0000000000..c4567b521b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/parallel_continue.hpp @@ -0,0 +1,33 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +template +inline bool parallel_continue(T dx1, T dy1, T dx2, T dy2) +{ + T const dot = dx1 * dx2 + dy1 * dy2; + return dot > 0; +} + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp new file mode 100755 index 0000000000..0a286f6843 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp @@ -0,0 +1,275 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2016. +// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR + + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +struct original_get_box +{ + template + static inline void apply(Box& total, Original const& original) + { + geometry::expand(total, original.m_box); + } +}; + +struct original_ovelaps_box +{ + template + static inline bool apply(Box const& box, Original const& original) + { + return ! detail::disjoint::disjoint_box_box(box, original.m_box); + } +}; + +struct include_turn_policy +{ + template + static inline bool apply(Turn const& turn) + { + return turn.location == location_ok; + } +}; + +struct turn_in_original_ovelaps_box +{ + template + static inline bool apply(Box const& box, Turn const& turn) + { + if (turn.location != location_ok || turn.within_original) + { + // Skip all points already processed + return false; + } + + return ! geometry::detail::disjoint::disjoint_point_box( + turn.robust_point, box); + } +}; + +//! Check if specified is in range of specified iterators +//! Return value of strategy (true if we can bail out) +template +< + typename Strategy, + typename State, + typename Point, + typename Iterator +> +inline bool point_in_range(Strategy& strategy, State& state, + Point const& point, Iterator begin, Iterator end) +{ + boost::ignore_unused(strategy); + + Iterator it = begin; + for (Iterator previous = it++; it != end; ++previous, ++it) + { + if (! strategy.apply(point, *previous, *it, state)) + { + // We're probably on the boundary + return false; + } + } + return true; +} + +template +< + typename Strategy, + typename State, + typename Point, + typename CoordinateType, + typename Iterator +> +inline bool point_in_section(Strategy& strategy, State& state, + Point const& point, CoordinateType const& point_x, + Iterator begin, Iterator end, + int direction) +{ + if (direction == 0) + { + // Not a monotonic section, or no change in X-direction + return point_in_range(strategy, state, point, begin, end); + } + + // We're in a monotonic section in x-direction + Iterator it = begin; + + for (Iterator previous = it++; it != end; ++previous, ++it) + { + // Depending on sections.direction we can quit for this section + CoordinateType const previous_x = geometry::get<0>(*previous); + + if (direction == 1 && point_x < previous_x) + { + // Section goes upwards, x increases, point is is below section + return true; + } + else if (direction == -1 && point_x > previous_x) + { + // Section goes downwards, x decreases, point is above section + return true; + } + + if (! strategy.apply(point, *previous, *it, state)) + { + // We're probably on the boundary + return false; + } + } + return true; +} + + +template +inline int point_in_original(Point const& point, Original const& original) +{ + // The winding strategy is scanning in x direction + // therefore it's critical to pass direction calculated + // for x dimension below. + typedef strategy::within::winding strategy_type; + + typename strategy_type::state_type state; + strategy_type strategy; + + if (boost::size(original.m_sections) == 0 + || boost::size(original.m_ring) - boost::size(original.m_sections) < 16) + { + // There are no sections, or it does not profit to walk over sections + // instead of over points. Boundary of 16 is arbitrary but can influence + // performance + point_in_range(strategy, state, point, + original.m_ring.begin(), original.m_ring.end()); + return strategy.result(state); + } + + typedef typename Original::sections_type sections_type; + typedef typename boost::range_iterator::type iterator_type; + typedef typename boost::range_value::type section_type; + typedef typename geometry::coordinate_type::type coordinate_type; + + coordinate_type const point_x = geometry::get<0>(point); + + // Walk through all monotonic sections of this original + for (iterator_type it = boost::begin(original.m_sections); + it != boost::end(original.m_sections); + ++it) + { + section_type const& section = *it; + + if (! section.duplicate + && section.begin_index < section.end_index + && point_x >= geometry::get(section.bounding_box) + && point_x <= geometry::get(section.bounding_box)) + { + // x-coordinate of point overlaps with section + if (! point_in_section(strategy, state, point, point_x, + boost::begin(original.m_ring) + section.begin_index, + boost::begin(original.m_ring) + section.end_index + 1, + section.directions[0])) + { + // We're probably on the boundary + break; + } + } + } + + return strategy.result(state); +} + + +template +class turn_in_original_visitor +{ +public: + turn_in_original_visitor(Turns& turns) + : m_mutable_turns(turns) + {} + + template + inline void apply(Turn const& turn, Original const& original, bool first = true) + { + boost::ignore_unused_variable_warning(first); + + if (turn.location != location_ok || turn.within_original) + { + // Skip all points already processed + return; + } + + if (geometry::disjoint(turn.robust_point, original.m_box)) + { + // Skip all disjoint + return; + } + + int const code = point_in_original(turn.robust_point, original); + + if (code == -1) + { + return; + } + + Turn& mutable_turn = m_mutable_turns[turn.turn_index]; + + if (code == 0) + { + // On border of original: always discard + mutable_turn.location = location_discard; + } + + // Point is inside an original ring + if (original.m_is_interior) + { + mutable_turn.count_in_original--; + } + else if (original.m_has_interiors) + { + mutable_turn.count_in_original++; + } + else + { + // It is an exterior ring and there are no interior rings. + // Then we are completely ready with this turn + mutable_turn.within_original = true; + mutable_turn.count_in_original = 1; + } + } + +private : + Turns& m_mutable_turns; +}; + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp new file mode 100755 index 0000000000..247d66bfce --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -0,0 +1,803 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2016. +// Modifications copyright (c) 2016 Oracle and/or its affiliates. +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR + + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) +#include +#endif + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace buffer +{ + +struct piece_get_box +{ + template + static inline void apply(Box& total, Piece const& piece) + { + geometry::expand(total, piece.robust_envelope); + } +}; + +struct piece_ovelaps_box +{ + template + static inline bool apply(Box const& box, Piece const& piece) + { + if (piece.type == strategy::buffer::buffered_flat_end + || piece.type == strategy::buffer::buffered_concave) + { + // Turns cannot be inside a flat end (though they can be on border) + // Neither we need to check if they are inside concave helper pieces + + // Skip all pieces not used as soon as possible + return false; + } + + return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope); + } +}; + +struct turn_get_box +{ + template + static inline void apply(Box& total, Turn const& turn) + { + geometry::expand(total, turn.robust_point); + } +}; + +struct turn_ovelaps_box +{ + template + static inline bool apply(Box const& box, Turn const& turn) + { + return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box); + } +}; + + +enum analyse_result +{ + analyse_unknown, + analyse_continue, + analyse_disjoint, + analyse_within, + analyse_on_original_boundary, + analyse_on_offsetted +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + , analyse_near_offsetted +#endif +}; + +template +inline bool in_box(Point const& previous, + Point const& current, Point const& point) +{ + // Get its box (TODO: this can be prepared-on-demand later) + typedef geometry::model::box box_type; + box_type box; + geometry::assign_inverse(box); + geometry::expand(box, previous); + geometry::expand(box, current); + + return geometry::covered_by(point, box); +} + +template +inline analyse_result check_segment(Point const& previous, + Point const& current, Turn const& turn, + bool from_monotonic) +{ + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); + segment_type const r(previous, current); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 0) + { + return analyse_on_offsetted; + } + if (side == -1 && from_monotonic) + { + return analyse_within; + } + if (side == 1 && from_monotonic) + { + return analyse_disjoint; + } + return analyse_continue; + +#else + + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + typedef typename geometry::coordinate_type::type coordinate_type; + + coordinate_type const twice_area + = side_strategy::template side_value + < + coordinate_type, + coordinate_type + >(previous, current, turn.robust_point); + + if (twice_area == 0) + { + // Collinear, only on segment if it is covered by its bbox + if (in_box(previous, current, turn.robust_point)) + { + return analyse_on_offsetted; + } + } + else if (twice_area < 0) + { + // It is in the triangle right-of the segment where the + // segment is the hypothenusa. Check if it is close + // (within rounding-area) + if (twice_area * twice_area < geometry::comparable_distance(previous, current) + && in_box(previous, current, turn.robust_point)) + { + return analyse_near_offsetted; + } + else if (from_monotonic) + { + return analyse_within; + } + } + else if (twice_area > 0 && from_monotonic) + { + // Left of segment + return analyse_disjoint; + } + + // Not monotonic, on left or right side: continue analysing + return analyse_continue; +#endif +} + + +class analyse_turn_wrt_point_piece +{ +public : + template + static inline analyse_result apply(Turn const& turn, Piece const& piece) + { + typedef typename Piece::section_type section_type; + typedef typename Turn::robust_point_type point_type; + typedef typename geometry::coordinate_type::type coordinate_type; + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); +#else + typedef strategy::within::winding strategy_type; + + typename strategy_type::state_type state; + strategy_type strategy; + boost::ignore_unused(strategy); +#endif + + BOOST_GEOMETRY_ASSERT(! piece.sections.empty()); + + coordinate_type const point_x = geometry::get<0>(turn.robust_point); + + for (std::size_t s = 0; s < piece.sections.size(); s++) + { + section_type const& section = piece.sections[s]; + // If point within horizontal range of monotonic section: + if (! section.duplicate + && section.begin_index < section.end_index + && point_x >= geometry::get(section.bounding_box) - 1 + && point_x <= geometry::get(section.bounding_box) + 1) + { + for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++) + { + point_type const& previous = piece.robust_ring[i - 1]; + point_type const& current = piece.robust_ring[i]; + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + + // First check if it is in range - if it is not, the + // expensive side_of_intersection does not need to be + // applied + coordinate_type x1 = geometry::get<0>(previous); + coordinate_type x2 = geometry::get<0>(current); + + if (x1 > x2) + { + std::swap(x1, x2); + } + + if (point_x >= x1 - 1 && point_x <= x2 + 1) + { + segment_type const r(previous, current); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + // Sections are monotonic in x-dimension + if (side == 1) + { + // Left on segment + return analyse_disjoint; + } + else if (side == 0) + { + // Collinear - TODO: check if really on segment + return analyse_on_offsetted; + } + } +#else + analyse_result code = check_segment(previous, current, turn, false); + if (code != analyse_continue) + { + return code; + } + + // Get the state (to determine it is within), we don't have + // to cover the on-segment case (covered above) + strategy.apply(turn.robust_point, previous, current, state); +#endif + } + } + } + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // It is nowhere outside, and not on segment, so it is within + return analyse_within; +#else + int const code = strategy.result(state); + if (code == 1) + { + return analyse_within; + } + else if (code == -1) + { + return analyse_disjoint; + } + + // Should normally not occur - on-segment is covered + return analyse_unknown; +#endif + } + +}; + +class analyse_turn_wrt_piece +{ + template + static inline analyse_result check_helper_segment(Point const& s1, + Point const& s2, Turn const& turn, + bool is_original, + Point const& offsetted) + { + boost::ignore_unused(offsetted); +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + typedef geometry::model::referring_segment segment_type; + segment_type const p(turn.rob_pi, turn.rob_pj); + segment_type const q(turn.rob_qi, turn.rob_qj); + segment_type const r(s1, s2); + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 1) + { + // left of segment + return analyse_disjoint; + } + else if (side == 0) + { + // If is collinear, either on segment or before/after + typedef geometry::model::box box_type; + + box_type box; + geometry::assign_inverse(box); + geometry::expand(box, s1); + geometry::expand(box, s2); + + if (geometry::covered_by(turn.robust_point, box)) + { + // Points on helper-segments are considered as within + // Points on original boundary are processed differently + return is_original + ? analyse_on_original_boundary + : analyse_within; + } + + // It is collinear but not on the segment. Because these + // segments are convex, it is outside + // Unless the offsetted ring is collinear or concave w.r.t. + // helper-segment but that scenario is not yet supported + return analyse_disjoint; + } + + // right of segment + return analyse_continue; +#else + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + + switch(side_strategy::apply(s1, s2, turn.robust_point)) + { + case 1 : + return analyse_disjoint; // left of segment + case 0 : + { + // If is collinear, either on segment or before/after + typedef geometry::model::box box_type; + + box_type box; + geometry::assign_inverse(box); + geometry::expand(box, s1); + geometry::expand(box, s2); + + if (geometry::covered_by(turn.robust_point, box)) + { + // It is on the segment + if (! is_original + && geometry::comparable_distance(turn.robust_point, offsetted) <= 1) + { + // It is close to the offsetted-boundary, take + // any rounding-issues into account + return analyse_near_offsetted; + } + + // Points on helper-segments are considered as within + // Points on original boundary are processed differently + return is_original + ? analyse_on_original_boundary + : analyse_within; + } + + // It is collinear but not on the segment. Because these + // segments are convex, it is outside + // Unless the offsetted ring is collinear or concave w.r.t. + // helper-segment but that scenario is not yet supported + return analyse_disjoint; + } + break; + } + + // right of segment + return analyse_continue; +#endif + } + + template + static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece) + { + typedef typename Turn::robust_point_type point_type; + geometry::equal_to comparator; + + point_type points[4]; + + signed_size_type helper_count = static_cast(piece.robust_ring.size()) + - piece.offsetted_count; + if (helper_count == 4) + { + for (int i = 0; i < 4; i++) + { + points[i] = piece.robust_ring[piece.offsetted_count + i]; + } + } + else if (helper_count == 3) + { + // Triangular piece, assign points but assign second twice + for (int i = 0; i < 4; i++) + { + int index = i < 2 ? i : i - 1; + points[i] = piece.robust_ring[piece.offsetted_count + index]; + } + } + else + { + // Some pieces (e.g. around points) do not have helper segments. + // Others should have 3 (join) or 4 (side) + return analyse_continue; + } + + // First check point-equality + point_type const& point = turn.robust_point; + if (comparator(point, points[0]) || comparator(point, points[3])) + { + return analyse_on_offsetted; + } + if (comparator(point, points[1]) || comparator(point, points[2])) + { + return analyse_on_original_boundary; + } + + // Right side of the piece + analyse_result result + = check_helper_segment(points[0], points[1], turn, + false, points[0]); + if (result != analyse_continue) + { + return result; + } + + // Left side of the piece + result = check_helper_segment(points[2], points[3], turn, + false, points[3]); + if (result != analyse_continue) + { + return result; + } + + if (! comparator(points[1], points[2])) + { + // Side of the piece at side of original geometry + result = check_helper_segment(points[1], points[2], turn, + true, point); + if (result != analyse_continue) + { + return result; + } + } + + // We are within the \/ or |_| shaped piece, where the top is the + // offsetted ring. + if (! geometry::covered_by(point, piece.robust_offsetted_envelope)) + { + // Not in offsetted-area. This makes a cheap check possible + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + + switch(side_strategy::apply(points[3], points[0], point)) + { + case 1 : return analyse_disjoint; + case -1 : return analyse_within; + case 0 : return analyse_disjoint; + } + } + + return analyse_continue; + } + + template + static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare) + { + typedef typename Piece::piece_robust_ring_type ring_type; + typedef typename ring_type::const_iterator it_type; + it_type end = piece.robust_ring.begin() + piece.offsetted_count; + it_type it = std::lower_bound(piece.robust_ring.begin(), + end, + turn.robust_point, + compare); + + if (it != end + && it != piece.robust_ring.begin()) + { + // iterator points to point larger than point + // w.r.t. specified direction, and prev points to a point smaller + // We now know if it is inside/outside + it_type prev = it - 1; + return check_segment(*prev, *it, turn, true); + } + return analyse_continue; + } + +public : + template + static inline analyse_result apply(Turn const& turn, Piece const& piece) + { + typedef typename Turn::robust_point_type point_type; + analyse_result code = check_helper_segments(turn, piece); + if (code != analyse_continue) + { + return code; + } + + geometry::equal_to comparator; + + if (piece.offsetted_count > 8) + { + // If the offset contains some points and is monotonic, we try + // to avoid walking all points linearly. + // We try it only once. + if (piece.is_monotonic_increasing[0]) + { + code = check_monotonic(turn, piece, geometry::less()); + if (code != analyse_continue) return code; + } + else if (piece.is_monotonic_increasing[1]) + { + code = check_monotonic(turn, piece, geometry::less()); + if (code != analyse_continue) return code; + } + else if (piece.is_monotonic_decreasing[0]) + { + code = check_monotonic(turn, piece, geometry::greater()); + if (code != analyse_continue) return code; + } + else if (piece.is_monotonic_decreasing[1]) + { + code = check_monotonic(turn, piece, geometry::greater()); + if (code != analyse_continue) return code; + } + } + + // It is small or not monotonic, walk linearly through offset + // TODO: this will be combined with winding strategy + + for (signed_size_type i = 1; i < piece.offsetted_count; i++) + { + point_type const& previous = piece.robust_ring[i - 1]; + point_type const& current = piece.robust_ring[i]; + + // The robust ring can contain duplicates + // (on which any side or side-value would return 0) + if (! comparator(previous, current)) + { + code = check_segment(previous, current, turn, false); + if (code != analyse_continue) + { + return code; + } + } + } + + return analyse_unknown; + } + +}; + + +template +class turn_in_piece_visitor +{ + Turns& m_turns; // because partition is currently operating on const input only + Pieces const& m_pieces; // to check for piece-type + + template + inline bool skip(Operation const& op, Piece const& piece) const + { + if (op.piece_index == piece.index) + { + return true; + } + Piece const& pc = m_pieces[op.piece_index]; + if (pc.left_index == piece.index || pc.right_index == piece.index) + { + if (pc.type == strategy::buffer::buffered_flat_end) + { + // If it is a flat end, don't compare against its neighbor: + // it will always be located on one of the helper segments + return true; + } + if (pc.type == strategy::buffer::buffered_concave) + { + // If it is concave, the same applies: the IP will be + // located on one of the helper segments + return true; + } + } + + return false; + } + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // NOTE: this function returns a side value in {-1, 0, 1} + template + static inline int turn_in_convex_piece(Turn const& turn, + Piece const& piece) + { + typedef typename Turn::robust_point_type point_type; + typedef typename Piece::piece_robust_ring_type ring_type; + typedef geometry::model::referring_segment segment; + + segment const p(turn.rob_pi, turn.rob_pj); + segment const q(turn.rob_qi, turn.rob_qj); + + typedef typename boost::range_iterator::type iterator_type; + iterator_type it = boost::begin(piece.robust_ring); + iterator_type end = boost::end(piece.robust_ring); + + // A robust ring is always closed, and always clockwise + for (iterator_type previous = it++; it != end; ++previous, ++it) + { + geometry::equal_to comparator; + if (comparator(*previous, *it)) + { + // Points are the same + continue; + } + + segment r(*previous, *it); + + int const side = strategy::side::side_of_intersection::apply(p, q, r, + turn.robust_point); + + if (side == 1) + { + // IP is left of segment, so it is outside + return -1; // outside + } + else if (side == 0) + { + // IP is collinear with segment. TODO: we should analyze this further + // For now we use the fallback point + if (in_box(*previous, *it, turn.robust_point)) + { + return 0; + } + else + { + return -1; // outside + } + } + } + return 1; // inside + } +#endif + + +public: + + inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces) + : m_turns(turns) + , m_pieces(pieces) + {} + + template + inline void apply(Turn const& turn, Piece const& piece, bool first = true) + { + boost::ignore_unused_variable_warning(first); + + if (turn.count_within > 0) + { + // Already inside - no need to check again + return; + } + + if (piece.type == strategy::buffer::buffered_flat_end + || piece.type == strategy::buffer::buffered_concave) + { + // Turns cannot be located within flat-end or concave pieces + return; + } + + if (! geometry::covered_by(turn.robust_point, piece.robust_envelope)) + { + // Easy check: if the turn is not in the envelope, we can safely return + return; + } + + if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece)) + { + return; + } + + // TODO: mutable_piece to make some on-demand preparations in analyse + Turn& mutable_turn = m_turns[turn.turn_index]; + + if (piece.type == geometry::strategy::buffer::buffered_point) + { + // Optimization for buffer around points: if distance from center + // is not between min/max radius, the result is clear + typedef typename default_comparable_distance_result + < + typename Turn::robust_point_type + >::type distance_type; + + distance_type const cd + = geometry::comparable_distance(piece.robust_center, + turn.robust_point); + + if (cd < piece.robust_min_comparable_radius) + { + mutable_turn.count_within++; + return; + } + if (cd > piece.robust_max_comparable_radius) + { + return; + } + } + + analyse_result analyse_code = + piece.type == geometry::strategy::buffer::buffered_point + ? analyse_turn_wrt_point_piece::apply(turn, piece) + : analyse_turn_wrt_piece::apply(turn, piece); + + switch(analyse_code) + { + case analyse_disjoint : + return; + case analyse_on_offsetted : + mutable_turn.count_on_offsetted++; // value is not used anymore + return; + case analyse_on_original_boundary : + mutable_turn.count_on_original_boundary++; + return; + case analyse_within : + mutable_turn.count_within++; + return; +#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + case analyse_near_offsetted : + mutable_turn.count_within_near_offsetted++; + return; +#endif + default : + break; + } + +#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION) + // We don't know (yet) + int geometry_code = 0; + if (piece.is_convex) + { + geometry_code = turn_in_convex_piece(turn, piece); + } + else + { + + // TODO: this point_in_geometry is a performance-bottleneck here and + // will be replaced completely by extending analyse_piece functionality + geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); + } +#else + int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring); +#endif + + if (geometry_code == 1) + { + mutable_turn.count_within++; + } + } +}; + + +}} // namespace detail::buffer +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/calculate_null.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/calculate_null.hpp new file mode 100755 index 0000000000..00d87af139 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/calculate_null.hpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct calculate_null +{ + template + static inline ReturnType apply(Geometry const& , Strategy const&) + { + return ReturnType(); + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/calculate_sum.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/calculate_sum.hpp new file mode 100755 index 0000000000..fc8121a85d --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/calculate_sum.hpp @@ -0,0 +1,58 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +class calculate_polygon_sum +{ + template + static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy) + { + ReturnType sum = ReturnType(); + for (typename boost::range_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + sum += Policy::apply(*it, strategy); + } + return sum; + } + +public : + template + static inline ReturnType apply(Polygon const& poly, Strategy const& strategy) + { + return Policy::apply(exterior_ring(poly), strategy) + + sum_interior_rings(interior_rings(poly), strategy) + ; + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp new file mode 100755 index 0000000000..3680881acf --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp @@ -0,0 +1,119 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP + + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace centroid +{ + + +// NOTE: There is no need to translate in other coordinate systems than +// cartesian. But if it was needed then one should translate using +// CS-specific technique, e.g. in spherical/geographic a translation +// vector should contain coordinates being multiplies of 2PI or 360 deg. +template ::type, + areal_tag + >::type, + typename CSTag = typename cs_tag::type> +struct translating_transformer +{ + typedef typename geometry::point_type::type point_type; + typedef boost::reference_wrapper result_type; + + explicit translating_transformer(Geometry const&) {} + explicit translating_transformer(point_type const&) {} + + result_type apply(point_type const& pt) const + { + return result_type(pt); + } + + template + void apply_reverse(ResPt &) const {} +}; + +// Specialization for Areal Geometries in cartesian CS +template +struct translating_transformer +{ + typedef typename geometry::point_type::type point_type; + typedef point_type result_type; + + explicit translating_transformer(Geometry const& geom) + : m_origin(NULL) + { + geometry::point_iterator + pt_it = geometry::points_begin(geom); + if ( pt_it != geometry::points_end(geom) ) + { + m_origin = boost::addressof(*pt_it); + } + } + + explicit translating_transformer(point_type const& origin) + : m_origin(boost::addressof(origin)) + {} + + result_type apply(point_type const& pt) const + { + point_type res = pt; + if ( m_origin ) + geometry::subtract_point(res, *m_origin); + return res; + } + + template + void apply_reverse(ResPt & res_pt) const + { + if ( m_origin ) + geometry::add_point(res_pt, *m_origin); + } + + const point_type * m_origin; +}; + + +}} // namespace detail::centroid +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/check_iterator_range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/check_iterator_range.hpp new file mode 100755 index 0000000000..66d2305923 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/check_iterator_range.hpp @@ -0,0 +1,71 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +// Check whether (each element of) an iterator range satisfies a given +// predicate. +// The predicate must be implemented as having a static apply unary +// method that returns a bool. +// By default an empty range is accepted +template +struct check_iterator_range +{ + template + static inline bool apply(InputIterator first, InputIterator beyond) + { + for (InputIterator it = first; it != beyond; ++it) + { + if (! Predicate::apply(*it)) + { + return false; + } + } + return AllowEmptyRange || first != beyond; + } + + + // version where we can pass a predicate object + template + static inline bool apply(InputIterator first, + InputIterator beyond, + Predicate const& predicate) + { + // in case predicate's apply method is static, MSVC will + // complain that predicate is not used + boost::ignore_unused(predicate); + + for (InputIterator it = first; it != beyond; ++it) + { + if (! predicate.apply(*it)) + { + return false; + } + } + return AllowEmptyRange || first != beyond; + } +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp new file mode 100755 index 0000000000..187620af77 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp @@ -0,0 +1,145 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP + +#include + +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace closest_feature +{ + + + +// returns the range iterator the realizes the closest +// distance between the geometry and the element of the range +class geometry_to_range +{ +private: + template + < + typename Geometry, + typename RangeIterator, + typename Strategy, + typename Distance + > + static inline void apply(Geometry const& geometry, + RangeIterator first, + RangeIterator last, + Strategy const& strategy, + RangeIterator& it_min, + Distance& dist_min) + { + BOOST_GEOMETRY_ASSERT( first != last ); + + Distance const zero = Distance(0); + + // start with first distance + it_min = first; + dist_min = dispatch::distance + < + Geometry, + typename std::iterator_traits::value_type, + Strategy + >::apply(geometry, *it_min, strategy); + + // check if other elements in the range are closer + for (RangeIterator it = ++first; it != last; ++it) + { + Distance dist = dispatch::distance + < + Geometry, + typename std::iterator_traits::value_type, + Strategy + >::apply(geometry, *it, strategy); + + if (geometry::math::equals(dist, zero)) + { + dist_min = dist; + it_min = it; + return; + } + else if (dist < dist_min) + { + dist_min = dist; + it_min = it; + } + } + } + +public: + template + < + typename Geometry, + typename RangeIterator, + typename Strategy, + typename Distance + > + static inline RangeIterator apply(Geometry const& geometry, + RangeIterator first, + RangeIterator last, + Strategy const& strategy, + Distance& dist_min) + { + RangeIterator it_min; + apply(geometry, first, last, strategy, it_min, dist_min); + + return it_min; + } + + + template + < + typename Geometry, + typename RangeIterator, + typename Strategy + > + static inline RangeIterator apply(Geometry const& geometry, + RangeIterator first, + RangeIterator last, + Strategy const& strategy) + { + typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type + < + typename std::iterator_traits + < + RangeIterator + >::value_type + >::type + >::type dist_min; + + return apply(geometry, first, last, strategy, dist_min); + } +}; + + + +}} // namespace detail::closest_feature +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp new file mode 100755 index 0000000000..3f6137c7f0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp @@ -0,0 +1,250 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP + +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace closest_feature +{ + + +// returns the segment (pair of iterators) that realizes the closest +// distance of the point to the range +template +< + typename Point, + typename Range, + closure_selector Closure, + typename Strategy +> +class point_to_point_range +{ +protected: + typedef typename boost::range_iterator::type iterator_type; + + template + static inline void apply(Point const& point, + iterator_type first, + iterator_type last, + Strategy const& strategy, + iterator_type& it_min1, + iterator_type& it_min2, + Distance& dist_min) + { + BOOST_GEOMETRY_ASSERT( first != last ); + + Distance const zero = Distance(0); + + iterator_type it = first; + iterator_type prev = it++; + if (it == last) + { + it_min1 = it_min2 = first; + dist_min = strategy.apply(point, *first, *first); + return; + } + + // start with first segment distance + dist_min = strategy.apply(point, *prev, *it); + iterator_type prev_min_dist = prev; + + // check if other segments are closer + for (++prev, ++it; it != last; ++prev, ++it) + { + Distance dist = strategy.apply(point, *prev, *it); + if (geometry::math::equals(dist, zero)) + { + dist_min = zero; + it_min1 = prev; + it_min2 = it; + return; + } + else if (dist < dist_min) + { + dist_min = dist; + prev_min_dist = prev; + } + } + + it_min1 = it_min2 = prev_min_dist; + ++it_min2; + } + +public: + typedef typename std::pair return_type; + + template + static inline return_type apply(Point const& point, + iterator_type first, + iterator_type last, + Strategy const& strategy, + Distance& dist_min) + { + iterator_type it_min1, it_min2; + apply(point, first, last, strategy, it_min1, it_min2, dist_min); + + return std::make_pair(it_min1, it_min2); + } + + static inline return_type apply(Point const& point, + iterator_type first, + iterator_type last, + Strategy const& strategy) + { + typename strategy::distance::services::return_type + < + Strategy, + Point, + typename boost::range_value::type + >::type dist_min; + + return apply(point, first, last, strategy, dist_min); + } + + template + static inline return_type apply(Point const& point, + Range const& range, + Strategy const& strategy, + Distance& dist_min) + { + return apply(point, + boost::begin(range), + boost::end(range), + strategy, + dist_min); + } + + static inline return_type apply(Point const& point, + Range const& range, + Strategy const& strategy) + { + return apply(point, boost::begin(range), boost::end(range), strategy); + } +}; + + + +// specialization for open ranges +template +class point_to_point_range + : point_to_point_range +{ +private: + typedef point_to_point_range base_type; + typedef typename base_type::iterator_type iterator_type; + + template + static inline void apply(Point const& point, + iterator_type first, + iterator_type last, + Strategy const& strategy, + iterator_type& it_min1, + iterator_type& it_min2, + Distance& dist_min) + { + BOOST_GEOMETRY_ASSERT( first != last ); + + base_type::apply(point, first, last, strategy, + it_min1, it_min2, dist_min); + + iterator_type it_back = --last; + Distance const zero = Distance(0); + Distance dist = strategy.apply(point, *it_back, *first); + + if (geometry::math::equals(dist, zero)) + { + dist_min = zero; + it_min1 = it_back; + it_min2 = first; + } + else if (dist < dist_min) + { + dist_min = dist; + it_min1 = it_back; + it_min2 = first; + } + } + +public: + typedef typename std::pair return_type; + + template + static inline return_type apply(Point const& point, + iterator_type first, + iterator_type last, + Strategy const& strategy, + Distance& dist_min) + { + iterator_type it_min1, it_min2; + + apply(point, first, last, strategy, it_min1, it_min2, dist_min); + + return std::make_pair(it_min1, it_min2); + } + + static inline return_type apply(Point const& point, + iterator_type first, + iterator_type last, + Strategy const& strategy) + { + typedef typename strategy::distance::services::return_type + < + Strategy, + Point, + typename boost::range_value::type + >::type distance_return_type; + + distance_return_type dist_min; + + return apply(point, first, last, strategy, dist_min); + } + + template + static inline return_type apply(Point const& point, + Range const& range, + Strategy const& strategy, + Distance& dist_min) + { + return apply(point, + boost::begin(range), + boost::end(range), + strategy, + dist_min); + } + + static inline return_type apply(Point const& point, + Range const& range, + Strategy const& strategy) + { + return apply(point, boost::begin(range), boost::end(range), strategy); + } +}; + + +}} // namespace detail::closest_feature +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp new file mode 100755 index 0000000000..6777364461 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp @@ -0,0 +1,196 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP + +#include + +#include +#include + +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace closest_feature +{ + + +// returns a pair of a objects where the first is an object of the +// r-tree range and the second an object of the query range that +// realizes the closest feature of the two ranges +class range_to_range_rtree +{ +private: + template + < + typename RTreeRangeIterator, + typename QueryRangeIterator, + typename Strategy, + typename RTreeValueType, + typename Distance + > + static inline void apply(RTreeRangeIterator rtree_first, + RTreeRangeIterator rtree_last, + QueryRangeIterator queries_first, + QueryRangeIterator queries_last, + Strategy const& strategy, + RTreeValueType& rtree_min, + QueryRangeIterator& qit_min, + Distance& dist_min) + { + typedef index::rtree > rtree_type; + + BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last ); + BOOST_GEOMETRY_ASSERT( queries_first != queries_last ); + + Distance const zero = Distance(0); + dist_min = zero; + + // create -- packing algorithm + rtree_type rt(rtree_first, rtree_last); + + RTreeValueType t_v; + bool first = true; + + for (QueryRangeIterator qit = queries_first; + qit != queries_last; ++qit, first = false) + { + std::size_t n = rt.query(index::nearest(*qit, 1), &t_v); + + BOOST_GEOMETRY_ASSERT( n > 0 ); + // n above is unused outside BOOST_GEOMETRY_ASSERT, + // hence the call to boost::ignore_unused below + // + // however, t_v (initialized by the call to rt.query(...)) + // is used below, which is why we cannot put the call to + // rt.query(...) inside BOOST_GEOMETRY_ASSERT + boost::ignore_unused(n); + + Distance dist = dispatch::distance + < + RTreeValueType, + typename std::iterator_traits + < + QueryRangeIterator + >::value_type, + Strategy + >::apply(t_v, *qit, strategy); + + if (first || dist < dist_min) + { + dist_min = dist; + rtree_min = t_v; + qit_min = qit; + if ( math::equals(dist_min, zero) ) + { + return; + } + } + } + } + +public: + template + struct return_type + { + typedef std::pair + < + typename std::iterator_traits::value_type, + QueryRangeIterator + > type; + }; + + + template + < + typename RTreeRangeIterator, + typename QueryRangeIterator, + typename Strategy, + typename Distance + > + static inline typename return_type + < + RTreeRangeIterator, QueryRangeIterator + >::type apply(RTreeRangeIterator rtree_first, + RTreeRangeIterator rtree_last, + QueryRangeIterator queries_first, + QueryRangeIterator queries_last, + Strategy const& strategy, + Distance& dist_min) + { + typedef typename std::iterator_traits + < + RTreeRangeIterator + >::value_type rtree_value_type; + + rtree_value_type rtree_min; + QueryRangeIterator qit_min; + + apply(rtree_first, rtree_last, queries_first, queries_last, + strategy, rtree_min, qit_min, dist_min); + + return std::make_pair(rtree_min, qit_min); + } + + + template + < + typename RTreeRangeIterator, + typename QueryRangeIterator, + typename Strategy + > + static inline typename return_type + < + RTreeRangeIterator, QueryRangeIterator + >::type apply(RTreeRangeIterator rtree_first, + RTreeRangeIterator rtree_last, + QueryRangeIterator queries_first, + QueryRangeIterator queries_last, + Strategy const& strategy) + { + typedef typename std::iterator_traits + < + RTreeRangeIterator + >::value_type rtree_value_type; + + typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type + < + typename std::iterator_traits + < + QueryRangeIterator + >::value_type + >::type + >::type dist_min; + + return apply(rtree_first, rtree_last, queries_first, queries_last, + strategy, dist_min); + } +}; + + +}} // namespace detail::closest_feature +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/comparable_distance/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/comparable_distance/implementation.hpp new file mode 100755 index 0000000000..33999e096e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/comparable_distance/implementation.hpp @@ -0,0 +1,24 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP + +#include + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp new file mode 100755 index 0000000000..e2972fa393 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp @@ -0,0 +1,363 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +namespace resolve_strategy +{ + +struct comparable_distance +{ + template + static inline + typename comparable_distance_result::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy_type; + + return dispatch::distance + < + Geometry1, Geometry2, comparable_strategy_type + >::apply(geometry1, + geometry2, + strategy::distance::services::get_comparable + < + Strategy + >::apply(strategy)); + } + + template + static inline typename comparable_distance_result + < + Geometry1, Geometry2, default_strategy + >::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename strategy::distance::services::comparable_type + < + typename detail::distance::default_strategy + < + Geometry1, Geometry2 + >::type + >::type comparable_strategy_type; + + return dispatch::distance + < + Geometry1, Geometry2, comparable_strategy_type + >::apply(geometry1, geometry2, comparable_strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant +{ + + +template +struct comparable_distance +{ + template + static inline + typename comparable_distance_result::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return resolve_strategy::comparable_distance::apply(geometry1, + geometry2, + strategy); + } +}; + + +template +struct comparable_distance + < + boost::variant, + Geometry2 + > +{ + template + struct visitor: static_visitor + < + typename comparable_distance_result + < + boost::variant, + Geometry2, + Strategy + >::type + > + { + Geometry2 const& m_geometry2; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Strategy const& strategy) + : m_geometry2(geometry2), + m_strategy(strategy) + {} + + template + typename comparable_distance_result + < + Geometry1, Geometry2, Strategy + >::type + operator()(Geometry1 const& geometry1) const + { + return comparable_distance + < + Geometry1, + Geometry2 + >::template apply + < + Strategy + >(geometry1, m_geometry2, m_strategy); + } + }; + + template + static inline typename comparable_distance_result + < + boost::variant, + Geometry2, + Strategy + >::type + apply(boost::variant const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(geometry2, strategy), geometry1); + } +}; + + +template +struct comparable_distance + < + Geometry1, + boost::variant + > +{ + template + struct visitor: static_visitor + < + typename comparable_distance_result + < + Geometry1, + boost::variant, + Strategy + >::type + > + { + Geometry1 const& m_geometry1; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Strategy const& strategy) + : m_geometry1(geometry1), + m_strategy(strategy) + {} + + template + typename comparable_distance_result + < + Geometry1, Geometry2, Strategy + >::type + operator()(Geometry2 const& geometry2) const + { + return comparable_distance + < + Geometry1, + Geometry2 + >::template apply + < + Strategy + >(m_geometry1, geometry2, m_strategy); + } + }; + + template + static inline typename comparable_distance_result + < + Geometry1, + boost::variant, + Strategy + >::type + apply(Geometry1 const& geometry1, + boost::variant const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(geometry1, strategy), geometry2); + } +}; + + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct comparable_distance + < + boost::variant, + boost::variant + > +{ + template + struct visitor: static_visitor + < + typename comparable_distance_result + < + boost::variant, + boost::variant, + Strategy + >::type + > + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + + template + typename comparable_distance_result + < + Geometry1, Geometry2, Strategy + >::type + operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const + { + return comparable_distance + < + Geometry1, + Geometry2 + >::template apply + < + Strategy + >(geometry1, geometry2, m_strategy); + } + }; + + template + static inline typename comparable_distance_result + < + boost::variant, + boost::variant, + Strategy + >::type + apply(boost::variant const& geometry1, + boost::variant const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(strategy), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + + +/*! +\brief \brief_calc2{comparable distance measurement} \brief_strategy +\ingroup distance +\details The free function comparable_distance does not necessarily calculate the distance, + but it calculates a distance measure such that two distances are comparable to each other. + For example: for the Cartesian coordinate system, Pythagoras is used but the square root + is not taken, which makes it faster and the results of two point pairs can still be + compared to each other. +\tparam Geometry1 first geometry type +\tparam Geometry2 second geometry type +\tparam Strategy \tparam_strategy{Distance} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{distance} +\return \return_calc{comparable distance} + +\qbk{distinguish,with strategy} + */ +template +inline typename comparable_distance_result::type +comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2, + Strategy const& strategy) +{ + concepts::check(); + concepts::check(); + + return resolve_variant::comparable_distance + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, strategy); +} + + + +/*! +\brief \brief_calc2{comparable distance measurement} +\ingroup distance +\details The free function comparable_distance does not necessarily calculate the distance, + but it calculates a distance measure such that two distances are comparable to each other. + For example: for the Cartesian coordinate system, Pythagoras is used but the square root + is not taken, which makes it faster and the results of two point pairs can still be + compared to each other. +\tparam Geometry1 first geometry type +\tparam Geometry2 second geometry type +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return \return_calc{comparable distance} + +\qbk{[include reference/algorithms/comparable_distance.qbk]} + */ +template +inline typename default_comparable_distance_result::type +comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + concepts::check(); + concepts::check(); + + return geometry::comparable_distance(geometry1, geometry2, default_strategy()); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp new file mode 100755 index 0000000000..ebf178feed --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp @@ -0,0 +1,80 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP + + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace conversion +{ + + +template +< + typename Source, + typename Destination, + std::size_t Dimension, + std::size_t DimensionCount +> +struct indexed_to_indexed +{ + static inline void apply(Source const& source, Destination& destination) + { + typedef typename coordinate_type::type coordinate_type; + + geometry::set(destination, + boost::numeric_cast( + geometry::get(source))); + geometry::set(destination, + boost::numeric_cast( + geometry::get(source))); + + indexed_to_indexed + < + Source, Destination, + Dimension + 1, DimensionCount + >::apply(source, destination); + } +}; + +template +< + typename Source, + typename Destination, + std::size_t DimensionCount +> +struct indexed_to_indexed +{ + static inline void apply(Source const& , Destination& ) + {} +}; + + +}} // namespace detail::conversion +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp new file mode 100755 index 0000000000..1c6ca8f22b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/convert_point_to_point.hpp @@ -0,0 +1,68 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP + +// Note: extracted from "convert.hpp" to avoid circular references convert/append + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace conversion +{ + + +template +struct point_to_point +{ + static inline void apply(Source const& source, Destination& destination) + { + typedef typename coordinate_type::type coordinate_type; + + set(destination, boost::numeric_cast(get(source))); + point_to_point::apply(source, destination); + } +}; + +template +struct point_to_point +{ + static inline void apply(Source const& , Destination& ) + {} +}; + + +template +inline void convert_point_to_point(Source const& source, Destination& destination) +{ + point_to_point::value>::apply(source, destination); +} + + + +}} // namespace detail::conversion +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/counting.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/counting.hpp new file mode 100755 index 0000000000..5089916f2b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/counting.hpp @@ -0,0 +1,107 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP + +#include + +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace counting +{ + + +template +struct other_count +{ + template + static inline std::size_t apply(Geometry const&) + { + return D; + } + + template + static inline std::size_t apply(Geometry const&, bool) + { + return D; + } +}; + + +template +struct polygon_count +{ + template + static inline std::size_t apply(Polygon const& poly) + { + std::size_t n = RangeCount::apply(exterior_ring(poly)); + + typename interior_return_type::type + rings = interior_rings(poly); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + n += RangeCount::apply(*it); + } + + return n; + } +}; + + +template +struct multi_count +{ + template + static inline std::size_t apply(MultiGeometry const& geometry) + { + std::size_t n = 0; + for (typename boost::range_iterator::type + it = boost::begin(geometry); + it != boost::end(geometry); + ++it) + { + n += SingleCount::apply(*it); + } + return n; + } +}; + + +}} // namespace detail::counting +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/course.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/course.hpp new file mode 100755 index 0000000000..d40652195e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/course.hpp @@ -0,0 +1,40 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +/// Calculate course (bearing) between two points. +/// +/// NOTE: left for convenience and temporary backward compatibility +template +inline ReturnType course(Point1 const& p1, Point2 const& p2) +{ + return azimuth(p1, p2); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/direction_code.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/direction_code.hpp new file mode 100755 index 0000000000..683d1456da --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/direction_code.hpp @@ -0,0 +1,79 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP + + +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +inline int sign_of_difference(Point1 const& point1, Point2 const& point2) +{ + return + math::equals(geometry::get(point1), geometry::get(point2)) + ? + 0 + : + (geometry::get(point1) > geometry::get(point2) ? 1 : -1); +} + + +// Gives sense of direction for point p, collinear w.r.t. segment (a,b) +// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a +// Returns 1 if p goes forward, so extends (a,b) +// Returns 0 if p is equal with b, or if (a,b) is degenerate +// Note that it does not do any collinearity test, that should be done before +template +inline int direction_code(Point1 const& segment_a, Point1 const& segment_b, + const Point2& p) +{ + // Suppose segment = (4 3,4 4) and p =(4 2) + // Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1 + + int const sign_a0 = sign_of_difference<0>(segment_b, segment_a); + int const sign_a1 = sign_of_difference<1>(segment_b, segment_a); + + if (sign_a0 == 0 && sign_a1 == 0) + { + return 0; + } + + int const sign_p0 = sign_of_difference<0>(segment_b, p); + int const sign_p1 = sign_of_difference<1>(segment_b, p); + + if (sign_p0 == 0 && sign_p1 == 0) + { + return 0; + } + + return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1; +} + + +} // namespace detail +#endif //DOXYGEN_NO_DETAIL + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp new file mode 100755 index 0000000000..94b048758f --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp @@ -0,0 +1,134 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +template +struct check_each_ring_for_within +{ + bool not_disjoint; + Geometry const& m_geometry; + + inline check_each_ring_for_within(Geometry const& g) + : not_disjoint(false) + , m_geometry(g) + {} + + template + inline void apply(Range const& range) + { + typename point_type::type pt; + not_disjoint = not_disjoint + || ( geometry::point_on_border(pt, range) + && geometry::covered_by(pt, m_geometry) ); + } +}; + + + +template +inline bool rings_containing(FirstGeometry const& geometry1, + SecondGeometry const& geometry2) +{ + check_each_ring_for_within checker(geometry1); + geometry::detail::for_each_range(geometry2, checker); + return checker.not_disjoint; +} + + + +template +struct general_areal +{ + static inline + bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + { + if ( ! disjoint_linear::apply(geometry1, geometry2) ) + { + return false; + } + + // If there is no intersection of segments, they might located + // inside each other + + // We check that using a point on the border (external boundary), + // and see if that is contained in the other geometry. And vice versa. + + if ( rings_containing(geometry1, geometry2) + || rings_containing(geometry2, geometry1) ) + { + return false; + } + + return true; + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::general_areal +{}; + + +template +struct disjoint + : detail::disjoint::general_areal +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp new file mode 100755 index 0000000000..14ad60852b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/box_box.hpp @@ -0,0 +1,163 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2016. +// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP + +#include + +#include +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + +template +< + typename Box1, typename Box2, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::value, + typename CSTag = typename tag_cast + < + typename cs_tag::type, + spherical_tag + >::type +> +struct box_box +{ + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + if (get(box1) < get(box2)) + { + return true; + } + if (get(box1) > get(box2)) + { + return true; + } + return box_box + < + Box1, Box2, + Dimension + 1, DimensionCount + >::apply(box1, box2); + } +}; + + +template +struct box_box +{ + static inline bool apply(Box1 const& , Box2 const& ) + { + return false; + } +}; + + +template +struct box_box +{ + static inline bool apply(Box1 const& box1, Box2 const& box2) + { + typedef typename geometry::select_most_precise + < + typename coordinate_type::type, + typename coordinate_type::type + >::type calc_t; + typedef typename coordinate_system::type::units units_t; + typedef math::detail::constants_on_spheroid constants; + + calc_t const b1_min = get(box1); + calc_t const b1_max = get(box1); + calc_t const b2_min = get(box2); + calc_t const b2_max = get(box2); + + // min <= max <=> diff >= 0 + calc_t const diff1 = b1_max - b1_min; + calc_t const diff2 = b2_max - b2_min; + + // check the intersection if neither box cover the whole globe + if (diff1 < constants::period() && diff2 < constants::period()) + { + // calculate positive longitude translation with b1_min as origin + calc_t const diff_min = math::longitude_distance_unsigned(b1_min, b2_min); + calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min + + if (b2_min_transl > b1_max // b2_min right of b1_max + && b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min + { + return true; + } + } + + return box_box + < + Box1, Box2, + 1, DimensionCount + >::apply(box1, box2); + } +}; + + +/*! + \brief Internal utility function to detect if boxes are disjoint + \note Is used from other algorithms, declared separately + to avoid circular references + */ +template +inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2) +{ + return box_box::apply(box1, box2); +} + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::box_box +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/implementation.hpp new file mode 100755 index 0000000000..8717a8a233 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/implementation.hpp @@ -0,0 +1,37 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/interface.hpp new file mode 100755 index 0000000000..097a02cb1c --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/interface.hpp @@ -0,0 +1,187 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP + +#include + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, + std::size_t DimensionCount, + typename Tag1, typename Tag2 +> +struct disjoint +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + return disjoint + < + Geometry2, Geometry1, + DimensionCount, + Tag2, Tag1 + >::apply(g2, g1); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant { + +template +struct disjoint +{ + static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + { + concepts::check_concepts_and_equal_dimensions + < + Geometry1 const, + Geometry2 const + >(); + + return dispatch::disjoint::apply(geometry1, geometry2); + } +}; + +template +struct disjoint, Geometry2> +{ + struct visitor: boost::static_visitor + { + Geometry2 const& m_geometry2; + + visitor(Geometry2 const& geometry2): m_geometry2(geometry2) {} + + template + bool operator()(Geometry1 const& geometry1) const + { + return disjoint::apply(geometry1, m_geometry2); + } + }; + + static inline bool + apply(boost::variant const& geometry1, + Geometry2 const& geometry2) + { + return boost::apply_visitor(visitor(geometry2), geometry1); + } +}; + +template +struct disjoint > +{ + struct visitor: boost::static_visitor + { + Geometry1 const& m_geometry1; + + visitor(Geometry1 const& geometry1): m_geometry1(geometry1) {} + + template + bool operator()(Geometry2 const& geometry2) const + { + return disjoint::apply(m_geometry1, geometry2); + } + }; + + static inline bool + apply(Geometry1 const& geometry1, + boost::variant const& geometry2) + { + return boost::apply_visitor(visitor(geometry1), geometry2); + } +}; + +template < + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct disjoint< + boost::variant, + boost::variant +> +{ + struct visitor: boost::static_visitor + { + template + bool operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return disjoint::apply(geometry1, geometry2); + } + }; + + static inline bool + apply(boost::variant const& geometry1, + boost::variant const& geometry2) + { + return boost::apply_visitor(visitor(), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + + +/*! +\brief \brief_check2{are disjoint} +\ingroup disjoint +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return \return_check2{are disjoint} + +\qbk{[include reference/algorithms/disjoint.qbk]} +*/ +template +inline bool disjoint(Geometry1 const& geometry1, + Geometry2 const& geometry2) +{ + return resolve_variant::disjoint::apply(geometry1, geometry2); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp new file mode 100755 index 0000000000..bece603738 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp @@ -0,0 +1,272 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + +template ::type, + typename Tag1OrMulti = typename tag_cast::type> +struct disjoint_no_intersections_policy +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + typedef typename point_type::type point1_type; + point1_type p; + geometry::point_on_border(p, g1); + return !geometry::covered_by(p, g2); + } +}; + +template +struct disjoint_no_intersections_policy +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + // TODO: use partition or rtree on g2 + typedef typename boost::range_iterator::type iterator; + for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it ) + { + typedef typename boost::range_value::type value_type; + if ( ! disjoint_no_intersections_policy + ::apply(*it, g2) ) + { + return false; + } + } + return true; + } +}; + + +template > +struct disjoint_linear_areal +{ + static inline bool apply(Geometry1 const& g1, Geometry2 const& g2) + { + // if there are intersections - return false + if ( !disjoint_linear::apply(g1, g2) ) + { + return false; + } + + return NoIntersectionsPolicy::apply(g1, g2); + } +}; + + + + +template +< + typename Segment, + typename Areal, + typename Tag = typename tag::type +> +struct disjoint_segment_areal + : not_implemented +{}; + + +template +class disjoint_segment_areal +{ +private: + template + static inline + bool check_interior_rings(InteriorRings const& interior_rings, + Segment const& segment) + { + typedef typename boost::range_value::type ring_type; + + typedef unary_disjoint_geometry_to_query_geometry + < + Segment, + disjoint_range_segment_or_box + < + ring_type, closure::value, Segment + > + > unary_predicate_type; + + return check_iterator_range + < + unary_predicate_type + >::apply(boost::begin(interior_rings), + boost::end(interior_rings), + unary_predicate_type(segment)); + } + + +public: + static inline bool apply(Segment const& segment, Polygon const& polygon) + { + typedef typename geometry::ring_type::type ring; + + if ( !disjoint_range_segment_or_box + < + ring, closure::value, Segment + >::apply(geometry::exterior_ring(polygon), segment) ) + { + return false; + } + + if ( !check_interior_rings(geometry::interior_rings(polygon), segment) ) + { + return false; + } + + typename point_type::type p; + detail::assign_point_from_index<0>(segment, p); + + return !geometry::covered_by(p, polygon); + } +}; + + +template +struct disjoint_segment_areal +{ + static inline + bool apply(Segment const& segment, MultiPolygon const& multipolygon) + { + return multirange_constant_size_geometry + < + MultiPolygon, Segment + >::apply(multipolygon, segment); + } +}; + + +template +struct disjoint_segment_areal +{ + static inline bool apply(Segment const& segment, Ring const& ring) + { + if ( !disjoint_range_segment_or_box + < + Ring, closure::value, Segment + >::apply(ring, segment) ) + { + return false; + } + + typename point_type::type p; + detail::assign_point_from_index<0>(segment, p); + + return !geometry::covered_by(p, ring); + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : public detail::disjoint::disjoint_linear_areal +{}; + + +template +struct disjoint +{ + static inline + bool apply(Areal const& areal, Linear const& linear) + { + return detail::disjoint::disjoint_linear_areal + < + Linear, Areal + >::apply(linear, areal); + } +}; + + +template +struct disjoint +{ + static inline bool apply(Areal const& g1, Segment const& g2) + { + return detail::disjoint::disjoint_segment_areal + < + Segment, Areal + >::apply(g2, g1); + } +}; + + +template +struct disjoint + : detail::disjoint::disjoint_segment_areal +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp new file mode 100755 index 0000000000..8fdaf4b3fc --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp @@ -0,0 +1,187 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + +template +struct disjoint_segment +{ + static inline bool apply(Segment1 const& segment1, Segment2 const& segment2) + { + typedef typename point_type::type point_type; + + // We don't need to rescale to detect disjointness + typedef no_rescale_policy rescale_policy_type; + rescale_policy_type robust_policy; + + typedef segment_intersection_points + < + point_type, + typename segment_ratio_type + < + point_type, + rescale_policy_type + >::type + > intersection_return_type; + + intersection_return_type is + = strategy::intersection::relate_cartesian_segments + < + policies::relate::segments_intersection_points + < + intersection_return_type + > + >::apply(segment1, segment2, robust_policy); + + return is.count == 0; + } +}; + + +struct assign_disjoint_policy +{ + // We want to include all points: + static bool const include_no_turn = true; + static bool const include_degenerate = true; + static bool const include_opposite = true; + + // We don't assign extra info: + template + < + typename Info, + typename Point1, + typename Point2, + typename IntersectionInfo + > + static inline void apply(Info& , Point1 const& , Point2 const&, + IntersectionInfo const&) + {} +}; + + +template +struct disjoint_linear +{ + static inline + bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + { + typedef typename geometry::point_type::type point_type; + typedef detail::no_rescale_policy rescale_policy_type; + typedef typename geometry::segment_ratio_type + < + point_type, rescale_policy_type + >::type segment_ratio_type; + typedef overlay::turn_info + < + point_type, + segment_ratio_type, + typename detail::get_turns::turn_operation_type + < + Geometry1, Geometry2, segment_ratio_type + >::type + > turn_info_type; + + std::deque turns; + + // Specify two policies: + // 1) Stop at any intersection + // 2) In assignment, include also degenerate points (which are normally skipped) + disjoint_interrupt_policy interrupt_policy; + dispatch::get_turns + < + typename geometry::tag::type, + typename geometry::tag::type, + Geometry1, + Geometry2, + overlay::do_reverse::value>::value, // should be false + overlay::do_reverse::value>::value, // should be false + detail::get_turns::get_turn_info_type + < + Geometry1, Geometry2, assign_disjoint_policy + > + >::apply(0, geometry1, 1, geometry2, + rescale_policy_type(), turns, interrupt_policy); + + return !interrupt_policy.has_intersections; + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::disjoint_linear +{}; + + +template +struct disjoint + : detail::disjoint::disjoint_segment +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp new file mode 100755 index 0000000000..914f1e7837 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp @@ -0,0 +1,168 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP + +#include +#include + +#include + +#include + +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +template +< + typename Range, + closure_selector Closure, + typename SegmentOrBox +> +struct disjoint_range_segment_or_box +{ + static inline + bool apply(Range const& range, SegmentOrBox const& segment_or_box) + { + typedef typename closeable_view::type view_type; + + typedef typename ::boost::range_value::type point_type; + typedef typename ::boost::range_iterator + < + view_type const + >::type const_iterator; + + typedef typename ::boost::range_size::type size_type; + + typedef typename geometry::model::referring_segment + < + point_type const + > range_segment; + + view_type view(range); + + const size_type count = ::boost::size(view); + + if ( count == 0 ) + { + return false; + } + else if ( count == 1 ) + { + return dispatch::disjoint + < + point_type, SegmentOrBox + >::apply(geometry::range::front(view), + segment_or_box); + } + else + { + const_iterator it0 = ::boost::begin(view); + const_iterator it1 = ::boost::begin(view) + 1; + const_iterator last = ::boost::end(view); + + for ( ; it1 != last ; ++it0, ++it1 ) + { + range_segment rng_segment(*it0, *it1); + if ( !dispatch::disjoint + < + range_segment, SegmentOrBox + >::apply(rng_segment, segment_or_box) ) + { + return false; + } + } + return true; + } + } +}; + + + + +template +< + typename Linear, + typename SegmentOrBox, + typename Tag = typename tag::type +> +struct disjoint_linear_segment_or_box + : not_implemented +{}; + + +template +struct disjoint_linear_segment_or_box + : disjoint_range_segment_or_box +{}; + + +template +struct disjoint_linear_segment_or_box + < + MultiLinestring, SegmentOrBox, multi_linestring_tag + > : multirange_constant_size_geometry +{}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::disjoint_linear_segment_or_box +{}; + + +template +struct disjoint + : detail::disjoint::disjoint_linear_segment_or_box +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp new file mode 100755 index 0000000000..b9fe2e2073 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp @@ -0,0 +1,286 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP + +#include +#include + +#include + +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +template +class multipoint_multipoint +{ +private: + template + class unary_disjoint_predicate + : detail::relate::less + { + private: + typedef detail::relate::less base_type; + + public: + unary_disjoint_predicate(Iterator first, Iterator last) + : base_type(), m_first(first), m_last(last) + {} + + template + inline bool apply(Point const& point) const + { + return !std::binary_search(m_first, + m_last, + point, + static_cast(*this)); + } + + private: + Iterator m_first, m_last; + }; + +public: + static inline bool apply(MultiPoint1 const& multipoint1, + MultiPoint2 const& multipoint2) + { + BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) ); + + typedef typename boost::range_value::type point1_type; + + std::vector points1(boost::begin(multipoint1), + boost::end(multipoint1)); + + std::sort(points1.begin(), points1.end(), detail::relate::less()); + + typedef unary_disjoint_predicate + < + typename std::vector::const_iterator + > predicate_type; + + return check_iterator_range + < + predicate_type + >::apply(boost::begin(multipoint2), + boost::end(multipoint2), + predicate_type(points1.begin(), points1.end())); + } +}; + + +template +class multipoint_linear +{ +private: + // structs for partition -- start + struct expand_box + { + template + static inline void apply(Box& total, Geometry const& geometry) + { + geometry::expand(total, geometry::return_envelope(geometry)); + } + + }; + + struct overlaps_box + { + template + static inline bool apply(Box const& box, Geometry const& geometry) + { + return ! dispatch::disjoint::apply(geometry, box); + } + }; + + class item_visitor_type + { + public: + item_visitor_type() : m_intersection_found(false) {} + + template + inline void apply(Item1 const& item1, Item2 const& item2) + { + if (! m_intersection_found + && ! dispatch::disjoint::apply(item1, item2)) + { + m_intersection_found = true; + } + } + + inline bool intersection_found() const { return m_intersection_found; } + + private: + bool m_intersection_found; + }; + // structs for partition -- end + + class segment_range + { + public: + typedef geometry::segment_iterator const_iterator; + typedef const_iterator iterator; + + segment_range(Linear const& linear) + : m_linear(linear) + {} + + const_iterator begin() const + { + return geometry::segments_begin(m_linear); + } + + const_iterator end() const + { + return geometry::segments_end(m_linear); + } + + private: + Linear const& m_linear; + }; + +public: + static inline bool apply(MultiPoint const& multipoint, Linear const& linear) + { + item_visitor_type visitor; + + geometry::partition + < + geometry::model::box::type>, + expand_box, + overlaps_box + >::apply(multipoint, segment_range(linear), visitor); + + return ! visitor.intersection_found(); + } + + static inline bool apply(Linear const& linear, MultiPoint const& multipoint) + { + return apply(multipoint, linear); + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + < + Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false + > : detail::disjoint::multirange_constant_size_geometry +{}; + + +template +struct disjoint + < + MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false + > : detail::disjoint::multirange_constant_size_geometry +{}; + + +template +struct disjoint + < + MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false + > : detail::disjoint::multirange_constant_size_geometry +{}; + + +template +< + typename MultiPoint1, + typename MultiPoint2, + std::size_t DimensionCount +> +struct disjoint + < + MultiPoint1, MultiPoint2, DimensionCount, + multi_point_tag, multi_point_tag, false + > +{ + static inline bool apply(MultiPoint1 const& multipoint1, + MultiPoint2 const& multipoint2) + { + if ( boost::size(multipoint2) < boost::size(multipoint1) ) + { + return detail::disjoint::multipoint_multipoint + < + MultiPoint2, MultiPoint1 + >::apply(multipoint2, multipoint1); + } + + return detail::disjoint::multipoint_multipoint + < + MultiPoint1, MultiPoint2 + >::apply(multipoint1, multipoint2); + } +}; + + +template +struct disjoint + < + Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false + > : detail::disjoint::multipoint_linear +{}; + + +template +struct disjoint + < + MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false + > : detail::disjoint::multipoint_linear +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp new file mode 100755 index 0000000000..205700641e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp @@ -0,0 +1,85 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +template +class unary_disjoint_geometry_to_query_geometry +{ +public: + unary_disjoint_geometry_to_query_geometry(Geometry const& geometry) + : m_geometry(geometry) + {} + + template + inline bool apply(QueryGeometry const& query_geometry) const + { + return BinaryPredicate::apply(query_geometry, m_geometry); + } + +private: + Geometry const& m_geometry; +}; + + +template +struct multirange_constant_size_geometry +{ + static inline bool apply(MultiRange const& multirange, + ConstantSizeGeometry const& constant_size_geometry) + { + typedef unary_disjoint_geometry_to_query_geometry + < + ConstantSizeGeometry, + dispatch::disjoint + < + typename boost::range_value::type, + ConstantSizeGeometry + > + > unary_predicate_type; + + return detail::check_iterator_range + < + unary_predicate_type + >::apply(boost::begin(multirange), boost::end(multirange), + unary_predicate_type(constant_size_geometry)); + } + + static inline bool apply(ConstantSizeGeometry const& constant_size_geometry, + MultiRange const& multirange) + { + return apply(multirange, constant_size_geometry); + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp new file mode 100755 index 0000000000..157de9f853 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_box.hpp @@ -0,0 +1,87 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland + +// This file was modified by Oracle on 2013-2016. +// Modifications copyright (c) 2013-2016, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP + +#include + +#include +#include +#include + +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +/*! + \brief Internal utility function to detect if point/box are disjoint + */ +template +inline bool disjoint_point_box(Point const& point, Box const& box) +{ + // ! covered_by(point, box) + return ! strategy::within::relate_point_box_loop + < + strategy::within::covered_by_range, + Point, Box, + 0, dimension::type::value + >::apply(point, box); +} + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint +{ + static inline bool apply(Point const& point, Box const& box) + { + // ! covered_by(point, box) + return ! strategy::within::relate_point_box_loop + < + strategy::within::covered_by_range, + Point, Box, + 0, DimensionCount + >::apply(point, box); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp new file mode 100755 index 0000000000..6eae1c96df --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp @@ -0,0 +1,88 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +struct reverse_covered_by +{ + template + static inline + bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) + { + return ! geometry::covered_by(geometry1, geometry2); + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::reverse_covered_by +{}; + + +template +struct disjoint + : detail::disjoint::reverse_covered_by +{}; + + +template +struct disjoint + : detail::disjoint::reverse_covered_by +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp new file mode 100755 index 0000000000..a62b8912f3 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp @@ -0,0 +1,235 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +template +struct point_point_generic +{ + template + static inline bool apply(Point1 const& p1, Point2 const& p2) + { + if (! geometry::math::equals(get(p1), get(p2))) + { + return true; + } + return + point_point_generic::apply(p1, p2); + } +}; + +template +struct point_point_generic +{ + template + static inline bool apply(Point1 const&, Point2 const&) + { + return false; + } +}; + + +class point_point_on_spheroid +{ +private: + template + struct are_same_points + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename helper_geometry::type helper_point_type1; + typedef typename helper_geometry::type helper_point_type2; + + helper_point_type1 point1_normalized + = return_normalized(point1); + helper_point_type2 point2_normalized + = return_normalized(point2); + + return point_point_generic + < + 0, dimension::value + >::apply(point1_normalized, point2_normalized); + } + }; + + template + struct are_same_points // points have different units + { + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + typedef typename geometry::select_most_precise + < + typename fp_coordinate_type::type, + typename fp_coordinate_type::type + >::type calculation_type; + + typename helper_geometry + < + Point1, calculation_type, radian + >::type helper_point1, helper_point2; + + Point1 point1_normalized = return_normalized(point1); + Point2 point2_normalized = return_normalized(point2); + + geometry::transform(point1_normalized, helper_point1); + geometry::transform(point2_normalized, helper_point2); + + return point_point_generic + < + 0, dimension::value + >::apply(helper_point1, helper_point2); + } + }; + +public: + template + static inline bool apply(Point1 const& point1, Point2 const& point2) + { + return are_same_points + < + Point1, + Point2, + boost::is_same + < + typename coordinate_system::type::units, + typename coordinate_system::type::units + >::value + >::apply(point1, point2); + } +}; + + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount, + typename CSTag1 = typename cs_tag::type, + typename CSTag2 = CSTag1 +> +struct point_point + : point_point +{}; + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point + < + Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag + > : point_point_on_spheroid +{}; + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point + < + Point1, Point2, Dimension, DimensionCount, geographic_tag + > : point_point_on_spheroid +{}; + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point + : point_point_generic +{}; + + +/*! + \brief Internal utility function to detect of points are disjoint + \note To avoid circular references + */ +template +inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2) +{ + return point_point + < + Point1, Point2, + 0, dimension::type::value + >::apply(point1, point2); +} + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::point_point +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp new file mode 100755 index 0000000000..d00d96059e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/disjoint/segment_box.hpp @@ -0,0 +1,298 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + + +template +struct compute_tmin_tmax_per_dim +{ + template + static inline void apply(SegmentPoint const& p0, + SegmentPoint const& p1, + Box const& box, + RelativeDistance& ti_min, + RelativeDistance& ti_max, + RelativeDistance& diff) + { + typedef typename coordinate_type::type box_coordinate_type; + typedef typename coordinate_type + < + SegmentPoint + >::type point_coordinate_type; + + RelativeDistance c_p0 = boost::numeric_cast + < + point_coordinate_type + >( geometry::get(p0) ); + + RelativeDistance c_p1 = boost::numeric_cast + < + point_coordinate_type + >( geometry::get(p1) ); + + RelativeDistance c_b_min = boost::numeric_cast + < + box_coordinate_type + >( geometry::get(box) ); + + RelativeDistance c_b_max = boost::numeric_cast + < + box_coordinate_type + >( geometry::get(box) ); + + if ( geometry::get(p1) >= geometry::get(p0) ) + { + diff = c_p1 - c_p0; + ti_min = c_b_min - c_p0; + ti_max = c_b_max - c_p0; + } + else + { + diff = c_p0 - c_p1; + ti_min = c_p0 - c_b_max; + ti_max = c_p0 - c_b_min; + } + } +}; + + +template +< + typename RelativeDistance, + typename SegmentPoint, + typename Box, + std::size_t I, + std::size_t Dimension +> +struct disjoint_segment_box_impl +{ + template + static inline bool apply(SegmentPoint const& p0, + SegmentPoint const& p1, + Box const& box, + RelativeDistancePair& t_min, + RelativeDistancePair& t_max) + { + RelativeDistance ti_min, ti_max, diff; + + compute_tmin_tmax_per_dim::apply(p0, p1, box, ti_min, ti_max, diff); + + if ( geometry::math::equals(diff, 0) ) + { + if ( (geometry::math::equals(t_min.second, 0) + && t_min.first > ti_max) + || + (geometry::math::equals(t_max.second, 0) + && t_max.first < ti_min) + || + (math::sign(ti_min) * math::sign(ti_max) > 0) ) + { + return true; + } + } + + RelativeDistance t_min_x_diff = t_min.first * diff; + RelativeDistance t_max_x_diff = t_max.first * diff; + + if ( t_min_x_diff > ti_max * t_min.second + || t_max_x_diff < ti_min * t_max.second ) + { + return true; + } + + if ( ti_min * t_min.second > t_min_x_diff ) + { + t_min.first = ti_min; + t_min.second = diff; + } + if ( ti_max * t_max.second < t_max_x_diff ) + { + t_max.first = ti_max; + t_max.second = diff; + } + + if ( t_min.first > t_min.second || t_max.first < 0 ) + { + return true; + } + + return disjoint_segment_box_impl + < + RelativeDistance, + SegmentPoint, + Box, + I + 1, + Dimension + >::apply(p0, p1, box, t_min, t_max); + } +}; + + +template +< + typename RelativeDistance, + typename SegmentPoint, + typename Box, + std::size_t Dimension +> +struct disjoint_segment_box_impl + < + RelativeDistance, SegmentPoint, Box, 0, Dimension + > +{ + static inline bool apply(SegmentPoint const& p0, + SegmentPoint const& p1, + Box const& box) + { + std::pair t_min, t_max; + RelativeDistance diff; + + compute_tmin_tmax_per_dim<0>::apply(p0, p1, box, + t_min.first, t_max.first, diff); + + if ( geometry::math::equals(diff, 0) ) + { + if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; } + if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; } + + if (math::sign(t_min.first) * math::sign(t_max.first) > 0) + { + return true; + } + } + + if ( t_min.first > diff || t_max.first < 0 ) + { + return true; + } + + t_min.second = t_max.second = diff; + + return disjoint_segment_box_impl + < + RelativeDistance, SegmentPoint, Box, 1, Dimension + >::apply(p0, p1, box, t_min, t_max); + } +}; + + +template +< + typename RelativeDistance, + typename SegmentPoint, + typename Box, + std::size_t Dimension +> +struct disjoint_segment_box_impl + < + RelativeDistance, SegmentPoint, Box, Dimension, Dimension + > +{ + template + static inline bool apply(SegmentPoint const&, SegmentPoint const&, + Box const&, + RelativeDistancePair&, RelativeDistancePair&) + { + return false; + } +}; + + +//========================================================================= + + +template +struct disjoint_segment_box +{ + static inline bool apply(Segment const& segment, Box const& box) + { + assert_dimension_equal(); + + typedef typename util::calculation_type::geometric::binary + < + Segment, Box, void + >::type relative_distance_type; + + typedef typename point_type::type segment_point_type; + segment_point_type p0, p1; + geometry::detail::assign_point_from_index<0>(segment, p0); + geometry::detail::assign_point_from_index<1>(segment, p1); + + return disjoint_segment_box_impl + < + relative_distance_type, segment_point_type, Box, + 0, dimension::value + >::apply(p0, p1, box); + } +}; + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct disjoint + : detail::disjoint::disjoint_segment_box +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/backward_compatibility.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/backward_compatibility.hpp new file mode 100755 index 0000000000..8fed0f0f57 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/backward_compatibility.hpp @@ -0,0 +1,333 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +struct point_to_segment +{ + static inline typename strategy::distance::services::return_type + < + Strategy, + Point, + typename point_type::type + >::type + apply(Point const& point, Segment const& segment, Strategy const& ) + { + typename detail::distance::default_ps_strategy + < + Point, + typename point_type::type, + Strategy + >::type segment_strategy; + + typename point_type::type p[2]; + geometry::detail::assign_point_from_index<0>(segment, p[0]); + geometry::detail::assign_point_from_index<1>(segment, p[1]); + return segment_strategy.apply(point, p[0], p[1]); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Point-segment version 1, with point-point strategy +template +struct distance +< + Point, Segment, Strategy, + point_tag, segment_tag, strategy_tag_distance_point_point, + false +> : detail::distance::point_to_segment +{}; + + +// Point-line version 1, where point-point strategy is specified +template +struct distance +< + Point, Linestring, Strategy, + point_tag, linestring_tag, strategy_tag_distance_point_point, + false +> +{ + + static inline typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type + apply(Point const& point, + Linestring const& linestring, + Strategy const&) + { + typedef typename detail::distance::default_ps_strategy + < + Point, + typename point_type::type, + Strategy + >::type ps_strategy_type; + + return detail::distance::point_to_range + < + Point, Linestring, closed, ps_strategy_type + >::apply(point, linestring, ps_strategy_type()); + } +}; + + +// Point-ring , where point-point strategy is specified +template +struct distance +< + Point, Ring, Strategy, + point_tag, ring_tag, strategy_tag_distance_point_point, + false +> +{ + typedef typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type return_type; + + static inline return_type apply(Point const& point, + Ring const& ring, + Strategy const&) + { + typedef typename detail::distance::default_ps_strategy + < + Point, + typename point_type::type, + Strategy + >::type ps_strategy_type; + + return detail::distance::point_to_ring + < + Point, Ring, + geometry::closure::value, + ps_strategy_type + >::apply(point, ring, ps_strategy_type()); + } +}; + + +// Point-polygon , where point-point strategy is specified +template +struct distance +< + Point, Polygon, Strategy, + point_tag, polygon_tag, strategy_tag_distance_point_point, + false +> +{ + typedef typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type return_type; + + static inline return_type apply(Point const& point, + Polygon const& polygon, + Strategy const&) + { + typedef typename detail::distance::default_ps_strategy + < + Point, + typename point_type::type, + Strategy + >::type ps_strategy_type; + + return detail::distance::point_to_polygon + < + Point, + Polygon, + geometry::closure::value, + ps_strategy_type + >::apply(point, polygon, ps_strategy_type()); + } +}; + + + + +template +< + typename Point, + typename MultiGeometry, + typename MultiGeometryTag, + typename Strategy +> +struct distance + < + Point, MultiGeometry, Strategy, + point_tag, MultiGeometryTag, + strategy_tag_distance_point_point, false + > +{ + typedef typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type return_type; + + static inline return_type apply(Point const& point, + MultiGeometry const& multigeometry, + Strategy const&) + { + typedef typename detail::distance::default_ps_strategy + < + Point, + typename point_type::type, + Strategy + >::type ps_strategy_type; + + return distance + < + Point, MultiGeometry, ps_strategy_type, + point_tag, MultiGeometryTag, + strategy_tag_distance_point_segment, false + >::apply(point, multigeometry, ps_strategy_type()); + } +}; + + +template +< + typename Geometry, + typename MultiPoint, + typename GeometryTag, + typename Strategy +> +struct distance + < + Geometry, MultiPoint, Strategy, + GeometryTag, multi_point_tag, + strategy_tag_distance_point_point, false + > +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(Geometry const& geometry, + MultiPoint const& multipoint, + Strategy const&) + { + typedef typename detail::distance::default_ps_strategy + < + typename point_type::type, + typename point_type::type, + Strategy + >::type ps_strategy_type; + + return distance + < + Geometry, MultiPoint, ps_strategy_type, + GeometryTag, multi_point_tag, + strategy_tag_distance_point_segment, false + >::apply(geometry, multipoint, ps_strategy_type()); + } +}; + + +template +< + typename MultiPoint, + typename MultiGeometry, + typename MultiGeometryTag, + typename Strategy +> +struct distance + < + MultiPoint, MultiGeometry, Strategy, + multi_point_tag, MultiGeometryTag, + strategy_tag_distance_point_point, false + > +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(MultiPoint const& multipoint, + MultiGeometry const& multigeometry, + Strategy const&) + { + typedef typename detail::distance::default_ps_strategy + < + typename point_type::type, + typename point_type::type, + Strategy + >::type ps_strategy_type; + + return distance + < + MultiPoint, MultiGeometry, ps_strategy_type, + multi_point_tag, MultiGeometryTag, + strategy_tag_distance_point_segment, false + >::apply(multipoint, multigeometry, ps_strategy_type()); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BACKWARD_COMPATIBILITY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/box_to_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/box_to_box.hpp new file mode 100755 index 0000000000..811c89080a --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/box_to_box.hpp @@ -0,0 +1,60 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP + +#include + +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct distance + < + Box1, Box2, Strategy, box_tag, box_tag, + strategy_tag_distance_box_box, false + > +{ + static inline typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type + apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy) + { + boost::ignore_unused(strategy); + return strategy.apply(box1, box2); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp new file mode 100755 index 0000000000..a222635389 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/default_strategies.hpp @@ -0,0 +1,137 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + + +// Helper metafunction for default strategy retrieval +template +< + typename Geometry1, + typename Geometry2 = Geometry1, + typename Tag1 = typename tag_cast + < + typename tag::type, pointlike_tag + >::type, + typename Tag2 = typename tag_cast + < + typename tag::type, pointlike_tag + >::type, + bool Reverse = geometry::reverse_dispatch::type::value +> +struct default_strategy + : strategy::distance::services::default_strategy + < + point_tag, segment_tag, + typename point_type::type, + typename point_type::type + > +{}; + +template +< + typename Geometry1, + typename Geometry2, + typename Tag1, + typename Tag2 +> +struct default_strategy + : default_strategy +{}; + + +template +struct default_strategy + < + Pointlike1, Pointlike2, + pointlike_tag, pointlike_tag, false + > : strategy::distance::services::default_strategy + < + point_tag, point_tag, + typename point_type::type, + typename point_type::type + > +{}; + + +template +struct default_strategy + : strategy::distance::services::default_strategy + < + point_tag, box_tag, + typename point_type::type, + typename point_type::type + > +{}; + + +template +struct default_strategy + : strategy::distance::services::default_strategy + < + box_tag, box_tag, + typename point_type::type, + typename point_type::type + > +{}; + + + +// Helper metafunction for default point-segment strategy retrieval +template +struct default_ps_strategy + : strategy::distance::services::default_strategy + < + point_tag, segment_tag, + typename point_type::type, + typename point_type::type, + typename cs_tag::type>::type, + typename cs_tag::type>::type, + Strategy + > +{}; + + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp new file mode 100755 index 0000000000..ff070c5a87 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp @@ -0,0 +1,464 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +// closure of segment or box point range +template +< + typename SegmentOrBox, + typename Tag = typename tag::type +> +struct segment_or_box_point_range_closure + : not_implemented +{}; + +template +struct segment_or_box_point_range_closure +{ + static const closure_selector value = closed; +}; + +template +struct segment_or_box_point_range_closure +{ + static const closure_selector value = open; +}; + + + +template +< + typename Geometry, + typename SegmentOrBox, + typename Strategy, + typename Tag = typename tag::type +> +class geometry_to_segment_or_box +{ +private: + typedef typename point_type::type segment_or_box_point; + + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef detail::closest_feature::point_to_point_range + < + typename point_type::type, + std::vector, + segment_or_box_point_range_closure::value, + comparable_strategy + > point_to_point_range; + + typedef detail::closest_feature::geometry_to_range geometry_to_range; + + typedef typename strategy::distance::services::return_type + < + comparable_strategy, + typename point_type::type, + segment_or_box_point + >::type comparable_return_type; + + + // assign the new minimum value for an iterator of the point range + // of a segment or a box + template + < + typename SegOrBox, + typename SegOrBoxTag = typename tag::type + > + struct assign_new_min_iterator + : not_implemented + {}; + + template + struct assign_new_min_iterator + { + template + static inline void apply(Iterator&, Iterator) + { + } + }; + + template + struct assign_new_min_iterator + { + template + static inline void apply(Iterator& it_min, Iterator it) + { + it_min = it; + } + }; + + + // assign the points of a segment or a box to a range + template + < + typename SegOrBox, + typename PointRange, + typename SegOrBoxTag = typename tag::type + > + struct assign_segment_or_box_points + {}; + + template + struct assign_segment_or_box_points + { + static inline void apply(Segment const& segment, PointRange& range) + { + detail::assign_point_from_index<0>(segment, range[0]); + detail::assign_point_from_index<1>(segment, range[1]); + } + }; + + template + struct assign_segment_or_box_points + { + static inline void apply(Box const& box, PointRange& range) + { + detail::assign_box_corners_oriented(box, range); + } + }; + + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + segment_or_box_point + >::type return_type; + + static inline return_type apply(Geometry const& geometry, + SegmentOrBox const& segment_or_box, + Strategy const& strategy, + bool check_intersection = true) + { + typedef geometry::point_iterator point_iterator_type; + typedef geometry::segment_iterator + < + Geometry const + > segment_iterator_type; + + typedef typename boost::range_const_iterator + < + std::vector + >::type seg_or_box_const_iterator; + + typedef assign_new_min_iterator assign_new_value; + + + if (check_intersection + && geometry::intersects(geometry, segment_or_box)) + { + return 0; + } + + comparable_strategy cstrategy = + strategy::distance::services::get_comparable + < + Strategy + >::apply(strategy); + + // get all points of the segment or the box + std::vector + seg_or_box_points(geometry::num_points(segment_or_box)); + + assign_segment_or_box_points + < + SegmentOrBox, + std::vector + >::apply(segment_or_box, seg_or_box_points); + + // consider all distances of the points in the geometry to the + // segment or box + comparable_return_type cd_min1(0); + point_iterator_type pit_min; + seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points); + seg_or_box_const_iterator it_min2 = it_min1; + ++it_min2; + bool first = true; + + for (point_iterator_type pit = points_begin(geometry); + pit != points_end(geometry); ++pit, first = false) + { + comparable_return_type cd; + std::pair + < + seg_or_box_const_iterator, seg_or_box_const_iterator + > it_pair + = point_to_point_range::apply(*pit, + boost::const_begin(seg_or_box_points), + boost::const_end(seg_or_box_points), + cstrategy, + cd); + + if (first || cd < cd_min1) + { + cd_min1 = cd; + pit_min = pit; + assign_new_value::apply(it_min1, it_pair.first); + assign_new_value::apply(it_min2, it_pair.second); + } + } + + // consider all distances of the points in the segment or box to the + // segments of the geometry + comparable_return_type cd_min2(0); + segment_iterator_type sit_min; + seg_or_box_const_iterator it_min; + + first = true; + for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points); + it != boost::const_end(seg_or_box_points); ++it, first = false) + { + comparable_return_type cd; + segment_iterator_type sit + = geometry_to_range::apply(*it, + segments_begin(geometry), + segments_end(geometry), + cstrategy, + cd); + + if (first || cd < cd_min2) + { + cd_min2 = cd; + it_min = it; + sit_min = sit; + } + } + + if (BOOST_GEOMETRY_CONDITION(is_comparable::value)) + { + return (std::min)(cd_min1, cd_min2); + } + + if (cd_min1 < cd_min2) + { + return strategy.apply(*pit_min, *it_min1, *it_min2); + } + else + { + return dispatch::distance + < + segment_or_box_point, + typename std::iterator_traits + < + segment_iterator_type + >::value_type, + Strategy + >::apply(*it_min, *sit_min, strategy); + } + } + + + static inline return_type + apply(SegmentOrBox const& segment_or_box, Geometry const& geometry, + Strategy const& strategy, bool check_intersection = true) + { + return apply(geometry, segment_or_box, strategy, check_intersection); + } +}; + + + +template +class geometry_to_segment_or_box + < + MultiPoint, SegmentOrBox, Strategy, multi_point_tag + > +{ +private: + typedef detail::closest_feature::geometry_to_range base_type; + + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + typedef detail::closest_feature::geometry_to_range geometry_to_range; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(MultiPoint const& multipoint, + SegmentOrBox const& segment_or_box, + Strategy const& strategy) + { + namespace sds = strategy::distance::services; + + typename sds::return_type + < + typename sds::comparable_type::type, + typename point_type::type, + typename point_type::type + >::type cd_min; + + iterator_type it_min + = geometry_to_range::apply(segment_or_box, + boost::begin(multipoint), + boost::end(multipoint), + sds::get_comparable + < + Strategy + >::apply(strategy), + cd_min); + + return + is_comparable::value + ? + cd_min + : + dispatch::distance + < + typename point_type::type, + SegmentOrBox, + Strategy + >::apply(*it_min, segment_or_box, strategy); + } +}; + + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct distance + < + Linear, Segment, Strategy, linear_tag, segment_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::geometry_to_segment_or_box +{}; + + +template +struct distance + < + Areal, Segment, Strategy, areal_tag, segment_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::geometry_to_segment_or_box +{}; + + +template +struct distance + < + Segment, Areal, Strategy, segment_tag, areal_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::geometry_to_segment_or_box +{}; + + +template +struct distance + < + Linear, Box, Strategy, linear_tag, box_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::geometry_to_segment_or_box + < + Linear, Box, Strategy + > +{}; + + +template +struct distance + < + Areal, Box, Strategy, areal_tag, box_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::geometry_to_segment_or_box +{}; + + +template +struct distance + < + MultiPoint, Segment, Strategy, + multi_point_tag, segment_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::geometry_to_segment_or_box + < + MultiPoint, Segment, Strategy + > +{}; + + +template +struct distance + < + MultiPoint, Box, Strategy, + multi_point_tag, box_tag, + strategy_tag_distance_point_box, false + > : detail::distance::geometry_to_segment_or_box + < + MultiPoint, Box, Strategy + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/implementation.hpp new file mode 100755 index 0000000000..9249c0921d --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/implementation.hpp @@ -0,0 +1,35 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP + +// the implementation details +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/interface.hpp new file mode 100755 index 0000000000..02ae971e82 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/interface.hpp @@ -0,0 +1,403 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2014 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, typename Strategy, + typename Tag1, typename Tag2, typename StrategyTag +> +struct distance +< + Geometry1, Geometry2, Strategy, + Tag1, Tag2, StrategyTag, + true +> + : distance +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply( + Geometry1 const& g1, + Geometry2 const& g2, + Strategy const& strategy) + { + return distance + < + Geometry2, Geometry1, Strategy, + Tag2, Tag1, StrategyTag, + false + >::apply(g2, g1, strategy); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_strategy +{ + +struct distance +{ + template + static inline typename distance_result::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return dispatch::distance + < + Geometry1, Geometry2, Strategy + >::apply(geometry1, geometry2, strategy); + } + + template + static inline + typename distance_result::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + default_strategy) + { + typedef typename detail::distance::default_strategy + < + Geometry1, Geometry2 + >::type strategy_type; + + return dispatch::distance + < + Geometry1, Geometry2, strategy_type + >::apply(geometry1, geometry2, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant +{ + + +template +struct distance +{ + template + static inline typename distance_result::type + apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return + resolve_strategy::distance::apply(geometry1, geometry2, strategy); + } +}; + + +template +struct distance, Geometry2> +{ + template + struct visitor: static_visitor + < + typename distance_result + < + variant, + Geometry2, + Strategy + >::type + > + { + Geometry2 const& m_geometry2; + Strategy const& m_strategy; + + visitor(Geometry2 const& geometry2, + Strategy const& strategy) + : m_geometry2(geometry2), + m_strategy(strategy) + {} + + template + typename distance_result::type + operator()(Geometry1 const& geometry1) const + { + return distance + < + Geometry1, + Geometry2 + >::template apply + < + Strategy + >(geometry1, m_geometry2, m_strategy); + } + }; + + template + static inline typename distance_result + < + variant, + Geometry2, + Strategy + >::type + apply(variant const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(geometry2, strategy), geometry1); + } +}; + + +template +struct distance > +{ + template + struct visitor: static_visitor + < + typename distance_result + < + Geometry1, + variant, + Strategy + >::type + > + { + Geometry1 const& m_geometry1; + Strategy const& m_strategy; + + visitor(Geometry1 const& geometry1, + Strategy const& strategy) + : m_geometry1(geometry1), + m_strategy(strategy) + {} + + template + typename distance_result::type + operator()(Geometry2 const& geometry2) const + { + return distance + < + Geometry1, + Geometry2 + >::template apply + < + Strategy + >(m_geometry1, geometry2, m_strategy); + } + }; + + template + static inline typename distance_result + < + Geometry1, + variant, + Strategy + >::type + apply( + Geometry1 const& geometry1, + const variant& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(geometry1, strategy), geometry2); + } +}; + + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct distance + < + boost::variant, + boost::variant + > +{ + template + struct visitor: static_visitor + < + typename distance_result + < + boost::variant, + boost::variant, + Strategy + >::type + > + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy) + : m_strategy(strategy) + {} + + template + typename distance_result::type + operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const + { + return distance + < + Geometry1, + Geometry2 + >::template apply + < + Strategy + >(geometry1, geometry2, m_strategy); + } + }; + + template + static inline typename distance_result + < + boost::variant, + boost::variant, + Strategy + >::type + apply(boost::variant const& geometry1, + boost::variant const& geometry2, + Strategy const& strategy) + { + return boost::apply_visitor(visitor(strategy), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc2{distance} \brief_strategy +\ingroup distance +\details +\details \details_calc{area}. \brief_strategy. \details_strategy_reasons + +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Strategy \tparam_strategy{Distance} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param strategy \param_strategy{distance} +\return \return_calc{distance} +\note The strategy can be a point-point strategy. In case of distance point-line/point-polygon + it may also be a point-segment strategy. + +\qbk{distinguish,with strategy} + +\qbk{ +[heading Available Strategies] +\* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)] +\* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)] +\* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)] +\* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)] +\* more (currently extensions): Vincenty\, Andoyer (geographic) +} + */ + +/* +Note, in case of a Compilation Error: +if you get: + - "Failed to specialize function template ..." + - "error: no matching function for call to ..." +for distance, it is probably so that there is no specialization +for return_type<...> for your strategy. +*/ +template +inline typename distance_result::type +distance(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) +{ + concepts::check(); + concepts::check(); + + detail::throw_on_empty_input(geometry1); + detail::throw_on_empty_input(geometry2); + + return resolve_variant::distance + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, strategy); +} + + +/*! +\brief \brief_calc2{distance} +\ingroup distance +\details The default strategy is used, corresponding to the coordinate system of the geometries +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return \return_calc{distance} + +\qbk{[include reference/algorithms/distance.qbk]} + */ +template +inline typename default_distance_result::type +distance(Geometry1 const& geometry1, + Geometry2 const& geometry2) +{ + concepts::check(); + concepts::check(); + + return geometry::distance(geometry1, geometry2, default_strategy()); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/is_comparable.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/is_comparable.hpp new file mode 100755 index 0000000000..db1c49d570 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/is_comparable.hpp @@ -0,0 +1,45 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP +#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +// metafunction to determine is a strategy is comparable or not +template +struct is_comparable + : boost::is_same + < + Strategy, + typename strategy::distance::services::comparable_type + < + Strategy + >::type + > +{}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/iterator_selector.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/iterator_selector.hpp new file mode 100755 index 0000000000..400dca04a8 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/iterator_selector.hpp @@ -0,0 +1,70 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP +#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +// class to choose between point_iterator and segment_iterator +template ::type> +struct iterator_selector +{ + typedef geometry::segment_iterator iterator_type; + + static inline iterator_type begin(Geometry& geometry) + { + return segments_begin(geometry); + } + + static inline iterator_type end(Geometry& geometry) + { + return segments_end(geometry); + } +}; + +template +struct iterator_selector +{ + typedef geometry::point_iterator iterator_type; + + static inline iterator_type begin(MultiPoint& multipoint) + { + return points_begin(multipoint); + } + + static inline iterator_type end(MultiPoint& multipoint) + { + return points_end(multipoint); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp new file mode 100755 index 0000000000..d30b4fc5d1 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp @@ -0,0 +1,147 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP + +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +struct linear_to_areal +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(Linear const& linear, + Areal const& areal, + Strategy const& strategy) + { + if ( geometry::intersects(linear, areal) ) + { + return 0; + } + + return linear_to_linear + < + Linear, Areal, Strategy + >::apply(linear, areal, strategy, false); + } + + + static inline return_type apply(Areal const& areal, + Linear const& linear, + Strategy const& strategy) + { + return apply(linear, areal, strategy); + } +}; + + +template +struct areal_to_areal +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(Areal1 const& areal1, + Areal2 const& areal2, + Strategy const& strategy) + { + if ( geometry::intersects(areal1, areal2) ) + { + return 0; + } + + return linear_to_linear + < + Areal1, Areal2, Strategy + >::apply(areal1, areal2, strategy, false); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct distance + < + Linear, Areal, Strategy, + linear_tag, areal_tag, + strategy_tag_distance_point_segment, false + > + : detail::distance::linear_to_areal + < + Linear, Areal, Strategy + > +{}; + + +template +struct distance + < + Areal, Linear, Strategy, + areal_tag, linear_tag, + strategy_tag_distance_point_segment, false + > + : detail::distance::linear_to_areal + < + Linear, Areal, Strategy + > +{}; + + +template +struct distance + < + Areal1, Areal2, Strategy, + areal_tag, areal_tag, + strategy_tag_distance_point_segment, false + > + : detail::distance::areal_to_areal + < + Areal1, Areal2, Strategy + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp new file mode 100755 index 0000000000..1cb44b3708 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp @@ -0,0 +1,123 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP + +#include + +#include + +#include +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +struct linear_to_linear +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(Linear1 const& linear1, + Linear2 const& linear2, + Strategy const& strategy, + bool = false) + { + if (geometry::num_points(linear1) == 1) + { + return dispatch::distance + < + typename point_type::type, + Linear2, + Strategy + >::apply(*points_begin(linear1), linear2, strategy); + } + + if (geometry::num_points(linear2) == 1) + { + return dispatch::distance + < + typename point_type::type, + Linear1, + Strategy + >::apply(*points_begin(linear2), linear1, strategy); + } + + if (geometry::num_segments(linear2) < geometry::num_segments(linear1)) + { + return point_or_segment_range_to_geometry_rtree + < + geometry::segment_iterator, + Linear1, + Strategy + >::apply(geometry::segments_begin(linear2), + geometry::segments_end(linear2), + linear1, + strategy); + + } + + return point_or_segment_range_to_geometry_rtree + < + geometry::segment_iterator, + Linear2, + Strategy + >::apply(geometry::segments_begin(linear1), + geometry::segments_end(linear1), + linear2, + strategy); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +struct distance + < + Linear1, Linear2, Strategy, + linear_tag, linear_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::linear_to_linear + < + Linear1, Linear2, Strategy + > +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp new file mode 100755 index 0000000000..0c443bdecc --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp @@ -0,0 +1,239 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP + +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +struct multipoint_to_multipoint +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(MultiPoint1 const& multipoint1, + MultiPoint2 const& multipoint2, + Strategy const& strategy) + { + if (boost::size(multipoint2) < boost::size(multipoint1)) + + { + return point_or_segment_range_to_geometry_rtree + < + typename boost::range_iterator::type, + MultiPoint1, + Strategy + >::apply(boost::begin(multipoint2), + boost::end(multipoint2), + multipoint1, + strategy); + } + + return point_or_segment_range_to_geometry_rtree + < + typename boost::range_iterator::type, + MultiPoint2, + Strategy + >::apply(boost::begin(multipoint1), + boost::end(multipoint1), + multipoint2, + strategy); + } +}; + + +template +struct multipoint_to_linear +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(MultiPoint const& multipoint, + Linear const& linear, + Strategy const& strategy) + { + return detail::distance::point_or_segment_range_to_geometry_rtree + < + typename boost::range_iterator::type, + Linear, + Strategy + >::apply(boost::begin(multipoint), + boost::end(multipoint), + linear, + strategy); + } + + static inline return_type apply(Linear const& linear, + MultiPoint const& multipoint, + Strategy const& strategy) + { + return apply(multipoint, linear, strategy); + } +}; + + +template +class multipoint_to_areal +{ +private: + struct not_covered_by_areal + { + not_covered_by_areal(Areal const& areal) + : m_areal(areal) + {} + + template + inline bool apply(Point const& point) const + { + return !geometry::covered_by(point, m_areal); + } + + Areal const& m_areal; + }; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(MultiPoint const& multipoint, + Areal const& areal, + Strategy const& strategy) + { + not_covered_by_areal predicate(areal); + + if (check_iterator_range + < + not_covered_by_areal, false + >::apply(boost::begin(multipoint), + boost::end(multipoint), + predicate)) + { + return detail::distance::point_or_segment_range_to_geometry_rtree + < + typename boost::range_iterator::type, + Areal, + Strategy + >::apply(boost::begin(multipoint), + boost::end(multipoint), + areal, + strategy); + } + return 0; + } + + static inline return_type apply(Areal const& areal, + MultiPoint const& multipoint, + Strategy const& strategy) + { + return apply(multipoint, areal, strategy); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct distance + < + MultiPoint1, MultiPoint2, Strategy, + multi_point_tag, multi_point_tag, + strategy_tag_distance_point_point, false + > : detail::distance::multipoint_to_multipoint + < + MultiPoint1, MultiPoint2, Strategy + > +{}; + +template +struct distance + < + MultiPoint, Linear, Strategy, multi_point_tag, linear_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::multipoint_to_linear +{}; + + +template +struct distance + < + Linear, MultiPoint, Strategy, linear_tag, multi_point_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::multipoint_to_linear +{}; + + +template +struct distance + < + MultiPoint, Areal, Strategy, multi_point_tag, areal_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::multipoint_to_areal +{}; + + +template +struct distance + < + Areal, MultiPoint, Strategy, areal_tag, multi_point_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::multipoint_to_areal +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp new file mode 100755 index 0000000000..63d4c50bb8 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp @@ -0,0 +1,518 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +struct point_to_point +{ + static inline + typename strategy::distance::services::return_type::type + apply(P1 const& p1, P2 const& p2, Strategy const& strategy) + { + boost::ignore_unused(strategy); + return strategy.apply(p1, p2); + } +}; + + +template +< + typename Point, + typename Range, + closure_selector Closure, + typename Strategy +> +class point_to_range +{ +private: + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef detail::closest_feature::point_to_point_range + < + Point, Range, Closure, comparable_strategy + > point_to_point_range; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + Point, + typename boost::range_value::type + >::type return_type; + + static inline return_type apply(Point const& point, Range const& range, + Strategy const& strategy) + { + return_type const zero = return_type(0); + + if (boost::size(range) == 0) + { + return zero; + } + + namespace sds = strategy::distance::services; + + typename sds::return_type + < + comparable_strategy, + Point, + typename point_type::type + >::type cd_min; + + std::pair + < + typename boost::range_iterator::type, + typename boost::range_iterator::type + > it_pair + = point_to_point_range::apply(point, + boost::begin(range), + boost::end(range), + sds::get_comparable + < + Strategy + >::apply(strategy), + cd_min); + + return + is_comparable::value + ? + cd_min + : + strategy.apply(point, *it_pair.first, *it_pair.second); + } +}; + + +template +< + typename Point, + typename Ring, + closure_selector Closure, + typename Strategy +> +struct point_to_ring +{ + typedef typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type return_type; + + static inline return_type apply(Point const& point, + Ring const& ring, + Strategy const& strategy) + { + if (geometry::within(point, ring)) + { + return return_type(0); + } + + return point_to_range + < + Point, Ring, closure::value, Strategy + >::apply(point, ring, strategy); + } +}; + + +template +< + typename Point, + typename Polygon, + closure_selector Closure, + typename Strategy +> +class point_to_polygon +{ +public: + typedef typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type return_type; + +private: + typedef point_to_range + < + Point, typename ring_type::type, Closure, Strategy + > per_ring; + + struct distance_to_interior_rings + { + template + static inline return_type apply(Point const& point, + InteriorRingIterator first, + InteriorRingIterator last, + Strategy const& strategy) + { + for (InteriorRingIterator it = first; it != last; ++it) + { + if (geometry::within(point, *it)) + { + // the point is inside a polygon hole, so its distance + // to the polygon its distance to the polygon's + // hole boundary + return per_ring::apply(point, *it, strategy); + } + } + return 0; + } + + template + static inline return_type apply(Point const& point, + InteriorRings const& interior_rings, + Strategy const& strategy) + { + return apply(point, + boost::begin(interior_rings), + boost::end(interior_rings), + strategy); + } + }; + + +public: + static inline return_type apply(Point const& point, + Polygon const& polygon, + Strategy const& strategy) + { + if (!geometry::covered_by(point, exterior_ring(polygon))) + { + // the point is outside the exterior ring, so its distance + // to the polygon is its distance to the polygon's exterior ring + return per_ring::apply(point, exterior_ring(polygon), strategy); + } + + // Check interior rings + return distance_to_interior_rings::apply(point, + interior_rings(polygon), + strategy); + } +}; + + +template +< + typename Point, + typename MultiGeometry, + typename Strategy, + bool CheckCoveredBy = boost::is_same + < + typename tag::type, multi_polygon_tag + >::value +> +class point_to_multigeometry +{ +private: + typedef detail::closest_feature::geometry_to_range geometry_to_range; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + Point, + typename point_type::type + >::type return_type; + + static inline return_type apply(Point const& point, + MultiGeometry const& multigeometry, + Strategy const& strategy) + { + typedef iterator_selector selector_type; + + namespace sds = strategy::distance::services; + + typename sds::return_type + < + typename sds::comparable_type::type, + Point, + typename point_type::type + >::type cd; + + typename selector_type::iterator_type it_min + = geometry_to_range::apply(point, + selector_type::begin(multigeometry), + selector_type::end(multigeometry), + sds::get_comparable + < + Strategy + >::apply(strategy), + cd); + + return + is_comparable::value + ? + cd + : + dispatch::distance + < + Point, + typename std::iterator_traits + < + typename selector_type::iterator_type + >::value_type, + Strategy + >::apply(point, *it_min, strategy); + } +}; + + +// this is called only for multipolygons, hence the change in the +// template parameter name MultiGeometry to MultiPolygon +template +struct point_to_multigeometry +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + Point, + typename point_type::type + >::type return_type; + + static inline return_type apply(Point const& point, + MultiPolygon const& multipolygon, + Strategy const& strategy) + { + if (geometry::covered_by(point, multipolygon)) + { + return 0; + } + + return point_to_multigeometry + < + Point, MultiPolygon, Strategy, false + >::apply(point, multipolygon, strategy); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Point-point +template +struct distance + < + P1, P2, Strategy, point_tag, point_tag, + strategy_tag_distance_point_point, false + > : detail::distance::point_to_point +{}; + + +// Point-line version 2, where point-segment strategy is specified +template +struct distance + < + Point, Linestring, Strategy, point_tag, linestring_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::point_to_range +{}; + + +// Point-ring , where point-segment strategy is specified +template +struct distance + < + Point, Ring, Strategy, point_tag, ring_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::point_to_ring + < + Point, Ring, closure::value, Strategy + > +{}; + + +// Point-polygon , where point-segment strategy is specified +template +struct distance + < + Point, Polygon, Strategy, point_tag, polygon_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::point_to_polygon + < + Point, Polygon, closure::value, Strategy + > +{}; + + +// Point-segment version 2, with point-segment strategy +template +struct distance + < + Point, Segment, Strategy, point_tag, segment_tag, + strategy_tag_distance_point_segment, false + > +{ + static inline typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type apply(Point const& point, + Segment const& segment, + Strategy const& strategy) + { + typename point_type::type p[2]; + geometry::detail::assign_point_from_index<0>(segment, p[0]); + geometry::detail::assign_point_from_index<1>(segment, p[1]); + + boost::ignore_unused(strategy); + return strategy.apply(point, p[0], p[1]); + } +}; + + +template +struct distance + < + Point, Box, Strategy, point_tag, box_tag, + strategy_tag_distance_point_box, false + > +{ + static inline typename strategy::distance::services::return_type + < + Strategy, Point, typename point_type::type + >::type + apply(Point const& point, Box const& box, Strategy const& strategy) + { + boost::ignore_unused(strategy); + return strategy.apply(point, box); + } +}; + + +template +struct distance + < + Point, MultiPoint, Strategy, point_tag, multi_point_tag, + strategy_tag_distance_point_point, false + > : detail::distance::point_to_multigeometry + < + Point, MultiPoint, Strategy + > +{}; + + +template +struct distance + < + Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::point_to_multigeometry + < + Point, MultiLinestring, Strategy + > +{}; + + +template +struct distance + < + Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag, + strategy_tag_distance_point_segment, false + > : detail::distance::point_to_multigeometry + < + Point, MultiPolygon, Strategy + > +{}; + + +template +struct distance + < + Point, Linear, Strategy, point_tag, linear_tag, + strategy_tag_distance_point_segment, false + > : distance + < + Point, Linear, Strategy, + point_tag, typename tag::type, + strategy_tag_distance_point_segment, false + > +{}; + + +template +struct distance + < + Point, Areal, Strategy, point_tag, areal_tag, + strategy_tag_distance_point_segment, false + > : distance + < + Point, Areal, Strategy, + point_tag, typename tag::type, + strategy_tag_distance_point_segment, false + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp new file mode 100755 index 0000000000..0d3c2d622e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp @@ -0,0 +1,130 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP + +#include +#include + +#include +#include + +#include + +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +< + typename PointOrSegmentIterator, + typename Geometry, + typename Strategy +> +class point_or_segment_range_to_geometry_rtree +{ +private: + typedef typename std::iterator_traits + < + PointOrSegmentIterator + >::value_type point_or_segment_type; + + typedef iterator_selector selector_type; + + typedef detail::closest_feature::range_to_range_rtree range_to_range; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type apply(PointOrSegmentIterator first, + PointOrSegmentIterator last, + Geometry const& geometry, + Strategy const& strategy) + { + namespace sds = strategy::distance::services; + + BOOST_GEOMETRY_ASSERT( first != last ); + + if ( geometry::has_one_element(first, last) ) + { + return dispatch::distance + < + point_or_segment_type, Geometry, Strategy + >::apply(*first, geometry, strategy); + } + + typename sds::return_type + < + typename sds::comparable_type::type, + typename point_type::type, + typename point_type::type + >::type cd_min; + + std::pair + < + point_or_segment_type, + typename selector_type::iterator_type + > closest_features + = range_to_range::apply(first, + last, + selector_type::begin(geometry), + selector_type::end(geometry), + sds::get_comparable + < + Strategy + >::apply(strategy), + cd_min); + + return + is_comparable::value + ? + cd_min + : + dispatch::distance + < + point_or_segment_type, + typename std::iterator_traits + < + typename selector_type::iterator_type + >::value_type, + Strategy + >::apply(closest_features.first, + *closest_features.second, + strategy); + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp new file mode 100755 index 0000000000..8ee3ee1cbb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -0,0 +1,892 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + +template +< + typename Segment, + typename Box, + typename Strategy, + bool UsePointBoxStrategy = false +> +class segment_to_box_2D_generic +{ +private: + typedef typename point_type::type segment_point; + typedef typename point_type::type box_point; + + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef detail::closest_feature::point_to_point_range + < + segment_point, + std::vector, + open, + comparable_strategy + > point_to_point_range; + + typedef typename strategy::distance::services::return_type + < + comparable_strategy, segment_point, box_point + >::type comparable_return_type; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, segment_point, box_point + >::type return_type; + + static inline return_type apply(Segment const& segment, + Box const& box, + Strategy const& strategy, + bool check_intersection = true) + { + if (check_intersection && geometry::intersects(segment, box)) + { + return 0; + } + + comparable_strategy cstrategy = + strategy::distance::services::get_comparable + < + Strategy + >::apply(strategy); + + // get segment points + segment_point p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + + // get box points + std::vector box_points(4); + detail::assign_box_corners_oriented(box, box_points); + + comparable_return_type cd[6]; + for (unsigned int i = 0; i < 4; ++i) + { + cd[i] = cstrategy.apply(box_points[i], p[0], p[1]); + } + + std::pair + < + typename std::vector::const_iterator, + typename std::vector::const_iterator + > bit_min[2]; + + bit_min[0] = point_to_point_range::apply(p[0], + box_points.begin(), + box_points.end(), + cstrategy, + cd[4]); + bit_min[1] = point_to_point_range::apply(p[1], + box_points.begin(), + box_points.end(), + cstrategy, + cd[5]); + + unsigned int imin = 0; + for (unsigned int i = 1; i < 6; ++i) + { + if (cd[i] < cd[imin]) + { + imin = i; + } + } + + if (BOOST_GEOMETRY_CONDITION(is_comparable::value)) + { + return cd[imin]; + } + + if (imin < 4) + { + return strategy.apply(box_points[imin], p[0], p[1]); + } + else + { + unsigned int bimin = imin - 4; + return strategy.apply(p[bimin], + *bit_min[bimin].first, + *bit_min[bimin].second); + } + } +}; + + +template +< + typename Segment, + typename Box, + typename Strategy +> +class segment_to_box_2D_generic +{ +private: + typedef typename point_type::type segment_point; + typedef typename point_type::type box_point; + + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef typename strategy::distance::services::return_type + < + comparable_strategy, segment_point, box_point + >::type comparable_return_type; + + typedef typename detail::distance::default_strategy + < + segment_point, Box + >::type point_box_strategy; + + typedef typename strategy::distance::services::comparable_type + < + point_box_strategy + >::type point_box_comparable_strategy; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, segment_point, box_point + >::type return_type; + + static inline return_type apply(Segment const& segment, + Box const& box, + Strategy const& strategy, + bool check_intersection = true) + { + if (check_intersection && geometry::intersects(segment, box)) + { + return 0; + } + + comparable_strategy cstrategy = + strategy::distance::services::get_comparable + < + Strategy + >::apply(strategy); + boost::ignore_unused(cstrategy); + + // get segment points + segment_point p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + + // get box points + std::vector box_points(4); + detail::assign_box_corners_oriented(box, box_points); + + comparable_return_type cd[6]; + for (unsigned int i = 0; i < 4; ++i) + { + cd[i] = cstrategy.apply(box_points[i], p[0], p[1]); + } + + point_box_comparable_strategy pb_cstrategy; + boost::ignore_unused(pb_cstrategy); + cd[4] = pb_cstrategy.apply(p[0], box); + cd[5] = pb_cstrategy.apply(p[1], box); + + unsigned int imin = 0; + for (unsigned int i = 1; i < 6; ++i) + { + if (cd[i] < cd[imin]) + { + imin = i; + } + } + + if (is_comparable::value) + { + return cd[imin]; + } + + if (imin < 4) + { + strategy.apply(box_points[imin], p[0], p[1]); + } + else + { + return point_box_strategy().apply(p[imin - 4], box); + } + } +}; + + + + +template +< + typename ReturnType, + typename SegmentPoint, + typename BoxPoint, + typename PPStrategy, + typename PSStrategy +> +class segment_to_box_2D +{ +private: + template + struct cast_to_result + { + template + static inline Result apply(T const& t) + { + return boost::numeric_cast(t); + } + }; + + + template + struct compare_less_equal + { + typedef compare_less_equal other; + + template + inline bool operator()(T1 const& t1, T2 const& t2) const + { + return std::less_equal()(cast_to_result::apply(t1), + cast_to_result::apply(t2)); + } + }; + + template + struct compare_less_equal + { + typedef compare_less_equal other; + + template + inline bool operator()(T1 const& t1, T2 const& t2) const + { + return std::greater_equal()(cast_to_result::apply(t1), + cast_to_result::apply(t2)); + } + }; + + + template + struct other_compare + { + typedef typename LessEqual::other type; + }; + + + // it is assumed here that p0 lies to the right of the box (so the + // entire segment lies to the right of the box) + template + struct right_of_box + { + static inline ReturnType apply(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& bottom_right, + BoxPoint const& top_right, + PPStrategy const& pp_strategy, + PSStrategy const& ps_strategy) + { + boost::ignore_unused(pp_strategy, ps_strategy); + + // the implementation below is written for non-negative slope + // segments + // + // for negative slope segments swap the roles of bottom_right + // and top_right and use greater_equal instead of less_equal. + + typedef cast_to_result cast; + + LessEqual less_equal; + + if (less_equal(geometry::get<1>(top_right), geometry::get<1>(p0))) + { + // closest box point is the top-right corner + return cast::apply(pp_strategy.apply(p0, top_right)); + } + else if (less_equal(geometry::get<1>(bottom_right), + geometry::get<1>(p0))) + { + // distance is realized between p0 and right-most + // segment of box + ReturnType diff = cast::apply(geometry::get<0>(p0)) + - cast::apply(geometry::get<0>(bottom_right)); + return strategy::distance::services::result_from_distance + < + PSStrategy, BoxPoint, SegmentPoint + >::apply(ps_strategy, math::abs(diff)); + } + else + { + // distance is realized between the bottom-right + // corner of the box and the segment + return cast::apply(ps_strategy.apply(bottom_right, p0, p1)); + } + } + }; + + + // it is assumed here that p0 lies above the box (so the + // entire segment lies above the box) + template + struct above_of_box + { + static inline ReturnType apply(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + PSStrategy const& ps_strategy) + { + boost::ignore_unused(ps_strategy); + + // the segment lies above the box + + typedef cast_to_result cast; + + LessEqual less_equal; + + // p0 is above the upper segment of the box + // (and inside its band) + if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p0))) + { + ReturnType diff = cast::apply(geometry::get<1>(p0)) + - cast::apply(geometry::get<1>(top_left)); + return strategy::distance::services::result_from_distance + < + PSStrategy, SegmentPoint, BoxPoint + >::apply(ps_strategy, math::abs(diff)); + } + + // p0 is to the left of the box, but p1 is above the box + // in this case the distance is realized between the + // top-left corner of the box and the segment + return cast::apply(ps_strategy.apply(top_left, p0, p1)); + } + }; + + + template + struct check_right_left_of_box + { + static inline bool apply(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right, + PPStrategy const& pp_strategy, + PSStrategy const& ps_strategy, + ReturnType& result) + { + // p0 lies to the right of the box + if (geometry::get<0>(p0) >= geometry::get<0>(top_right)) + { + result = right_of_box + < + LessEqual + >::apply(p0, p1, bottom_right, top_right, + pp_strategy, ps_strategy); + return true; + } + + // p1 lies to the left of the box + if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left)) + { + result = right_of_box + < + typename other_compare::type + >::apply(p1, p0, top_left, bottom_left, + pp_strategy, ps_strategy); + return true; + } + + return false; + } + }; + + + template + struct check_above_below_of_box + { + static inline bool apply(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right, + PSStrategy const& ps_strategy, + ReturnType& result) + { + // the segment lies below the box + if (geometry::get<1>(p1) < geometry::get<1>(bottom_left)) + { + result = above_of_box + < + typename other_compare::type + >::apply(p1, p0, bottom_right, ps_strategy); + return true; + } + + // the segment lies above the box + if (geometry::get<1>(p0) > geometry::get<1>(top_right)) + { + result = above_of_box + < + LessEqual + >::apply(p0, p1, top_left, ps_strategy); + return true; + } + return false; + } + }; + + struct check_generic_position + { + static inline bool apply(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& bottom_left0, + BoxPoint const& top_right0, + BoxPoint const& bottom_left1, + BoxPoint const& top_right1, + BoxPoint const& corner1, + BoxPoint const& corner2, + PSStrategy const& ps_strategy, + ReturnType& result) + { + typedef cast_to_result cast; + + ReturnType diff0 = cast::apply(geometry::get<0>(p1)) + - cast::apply(geometry::get<0>(p0)); + ReturnType t_min0 = cast::apply(geometry::get<0>(bottom_left0)) + - cast::apply(geometry::get<0>(p0)); + ReturnType t_max0 = cast::apply(geometry::get<0>(top_right0)) + - cast::apply(geometry::get<0>(p0)); + + ReturnType diff1 = cast::apply(geometry::get<1>(p1)) + - cast::apply(geometry::get<1>(p0)); + ReturnType t_min1 = cast::apply(geometry::get<1>(bottom_left1)) + - cast::apply(geometry::get<1>(p0)); + ReturnType t_max1 = cast::apply(geometry::get<1>(top_right1)) + - cast::apply(geometry::get<1>(p0)); + + if (diff1 < 0) + { + diff1 = -diff1; + t_min1 = -t_min1; + t_max1 = -t_max1; + } + + // t_min0 > t_max1 + if (t_min0 * diff1 > t_max1 * diff0) + { + result = cast::apply(ps_strategy.apply(corner1, p0, p1)); + return true; + } + + // t_max0 < t_min1 + if (t_max0 * diff1 < t_min1 * diff0) + { + result = cast::apply(ps_strategy.apply(corner2, p0, p1)); + return true; + } + return false; + } + }; + + static inline ReturnType + non_negative_slope_segment(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right, + PPStrategy const& pp_strategy, + PSStrategy const& ps_strategy) + { + typedef compare_less_equal less_equal; + + // assert that the segment has non-negative slope + BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1)) + && geometry::get<1>(p0) < geometry::get<1>(p1)) + || + ( geometry::get<0>(p0) < geometry::get<0>(p1) + && geometry::get<1>(p0) <= geometry::get<1>(p1) ) + || geometry::has_nan_coordinate(p0) + || geometry::has_nan_coordinate(p1)); + + ReturnType result(0); + + if (check_right_left_of_box + < + less_equal + >::apply(p0, p1, + top_left, top_right, bottom_left, bottom_right, + pp_strategy, ps_strategy, result)) + { + return result; + } + + if (check_above_below_of_box + < + less_equal + >::apply(p0, p1, + top_left, top_right, bottom_left, bottom_right, + ps_strategy, result)) + { + return result; + } + + if (check_generic_position::apply(p0, p1, + bottom_left, top_right, + bottom_left, top_right, + top_left, bottom_right, + ps_strategy, result)) + { + return result; + } + + // in all other cases the box and segment intersect, so return 0 + return result; + } + + + static inline ReturnType + negative_slope_segment(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right, + PPStrategy const& pp_strategy, + PSStrategy const& ps_strategy) + { + typedef compare_less_equal greater_equal; + + // assert that the segment has negative slope + BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1) + && geometry::get<1>(p0) > geometry::get<1>(p1) ) + || geometry::has_nan_coordinate(p0) + || geometry::has_nan_coordinate(p1) ); + + ReturnType result(0); + + if (check_right_left_of_box + < + greater_equal + >::apply(p0, p1, + bottom_left, bottom_right, top_left, top_right, + pp_strategy, ps_strategy, result)) + { + return result; + } + + if (check_above_below_of_box + < + greater_equal + >::apply(p1, p0, + top_right, top_left, bottom_right, bottom_left, + ps_strategy, result)) + { + return result; + } + + if (check_generic_position::apply(p0, p1, + bottom_left, top_right, + top_right, bottom_left, + bottom_left, top_right, + ps_strategy, result)) + { + return result; + } + + // in all other cases the box and segment intersect, so return 0 + return result; + } + +public: + static inline ReturnType apply(SegmentPoint const& p0, + SegmentPoint const& p1, + BoxPoint const& top_left, + BoxPoint const& top_right, + BoxPoint const& bottom_left, + BoxPoint const& bottom_right, + PPStrategy const& pp_strategy, + PSStrategy const& ps_strategy) + { + BOOST_GEOMETRY_ASSERT( geometry::less()(p0, p1) + || geometry::has_nan_coordinate(p0) + || geometry::has_nan_coordinate(p1) ); + + if (geometry::get<0>(p0) < geometry::get<0>(p1) + && geometry::get<1>(p0) > geometry::get<1>(p1)) + { + return negative_slope_segment(p0, p1, + top_left, top_right, + bottom_left, bottom_right, + pp_strategy, ps_strategy); + } + + return non_negative_slope_segment(p0, p1, + top_left, top_right, + bottom_left, bottom_right, + pp_strategy, ps_strategy); + } +}; + + +//========================================================================= + + +template +< + typename Segment, + typename Box, + typename std::size_t Dimension, + typename PPStrategy, + typename PSStrategy +> +class segment_to_box + : not_implemented +{}; + + +template +< + typename Segment, + typename Box, + typename PPStrategy, + typename PSStrategy +> +class segment_to_box +{ +private: + typedef typename point_type::type segment_point; + typedef typename point_type::type box_point; + + typedef typename strategy::distance::services::comparable_type + < + PPStrategy + >::type pp_comparable_strategy; + + typedef typename strategy::distance::services::comparable_type + < + PSStrategy + >::type ps_comparable_strategy; + + typedef typename strategy::distance::services::return_type + < + ps_comparable_strategy, segment_point, box_point + >::type comparable_return_type; +public: + typedef typename strategy::distance::services::return_type + < + PSStrategy, segment_point, box_point + >::type return_type; + + static inline return_type apply(Segment const& segment, + Box const& box, + PPStrategy const& pp_strategy, + PSStrategy const& ps_strategy) + { + segment_point p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + + if (geometry::equals(p[0], p[1])) + { + typedef typename boost::mpl::if_ + < + boost::is_same + < + ps_comparable_strategy, + PSStrategy + >, + typename strategy::distance::services::comparable_type + < + typename detail::distance::default_strategy + < + segment_point, Box + >::type + >::type, + typename detail::distance::default_strategy + < + segment_point, Box + >::type + >::type point_box_strategy_type; + + return dispatch::distance + < + segment_point, + Box, + point_box_strategy_type + >::apply(p[0], box, point_box_strategy_type()); + } + + box_point top_left, top_right, bottom_left, bottom_right; + detail::assign_box_corners(box, bottom_left, bottom_right, + top_left, top_right); + + if (geometry::less()(p[0], p[1])) + { + return segment_to_box_2D + < + return_type, + segment_point, + box_point, + PPStrategy, + PSStrategy + >::apply(p[0], p[1], + top_left, top_right, bottom_left, bottom_right, + pp_strategy, + ps_strategy); + } + else + { + return segment_to_box_2D + < + return_type, + segment_point, + box_point, + PPStrategy, + PSStrategy + >::apply(p[1], p[0], + top_left, top_right, bottom_left, bottom_right, + pp_strategy, + ps_strategy); + } + } +}; + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct distance + < + Segment, Box, Strategy, segment_tag, box_tag, + strategy_tag_distance_point_segment, false + > +{ + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + + static inline return_type apply(Segment const& segment, + Box const& box, + Strategy const& strategy) + { + assert_dimension_equal(); + + typedef typename boost::mpl::if_ + < + boost::is_same + < + typename strategy::distance::services::comparable_type + < + Strategy + >::type, + Strategy + >, + typename strategy::distance::services::comparable_type + < + typename detail::distance::default_strategy + < + typename point_type::type, + typename point_type::type + >::type + >::type, + typename detail::distance::default_strategy + < + typename point_type::type, + typename point_type::type + >::type + >::type pp_strategy_type; + + + return detail::distance::segment_to_box + < + Segment, + Box, + dimension::value, + pp_strategy_type, + Strategy + >::apply(segment, box, pp_strategy_type(), strategy); + } +}; + + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp new file mode 100755 index 0000000000..fb83c6e2c0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp @@ -0,0 +1,152 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP + +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace distance +{ + + + +// compute segment-segment distance +template +class segment_to_segment +{ +private: + typedef typename strategy::distance::services::comparable_type + < + Strategy + >::type comparable_strategy; + + typedef typename strategy::distance::services::return_type + < + comparable_strategy, + typename point_type::type, + typename point_type::type + >::type comparable_return_type; + +public: + typedef typename strategy::distance::services::return_type + < + Strategy, + typename point_type::type, + typename point_type::type + >::type return_type; + + static inline return_type + apply(Segment1 const& segment1, Segment2 const& segment2, + Strategy const& strategy) + { + if (geometry::intersects(segment1, segment2)) + { + return 0; + } + + typename point_type::type p[2]; + detail::assign_point_from_index<0>(segment1, p[0]); + detail::assign_point_from_index<1>(segment1, p[1]); + + typename point_type::type q[2]; + detail::assign_point_from_index<0>(segment2, q[0]); + detail::assign_point_from_index<1>(segment2, q[1]); + + comparable_strategy cstrategy = + strategy::distance::services::get_comparable + < + Strategy + >::apply(strategy); + + comparable_return_type d[4]; + d[0] = cstrategy.apply(q[0], p[0], p[1]); + d[1] = cstrategy.apply(q[1], p[0], p[1]); + d[2] = cstrategy.apply(p[0], q[0], q[1]); + d[3] = cstrategy.apply(p[1], q[0], q[1]); + + std::size_t imin = std::distance(boost::addressof(d[0]), + std::min_element(d, d + 4)); + + if (BOOST_GEOMETRY_CONDITION(is_comparable::value)) + { + return d[imin]; + } + + switch (imin) + { + case 0: + return strategy.apply(q[0], p[0], p[1]); + case 1: + return strategy.apply(q[1], p[0], p[1]); + case 2: + return strategy.apply(p[0], q[0], q[1]); + default: + return strategy.apply(p[1], q[0], q[1]); + } + } +}; + + + + +}} // namespace detail::distance +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + + +// segment-segment +template +struct distance + < + Segment1, Segment2, Strategy, segment_tag, segment_tag, + strategy_tag_distance_point_segment, false + > + : detail::distance::segment_to_segment +{}; + + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/box.hpp new file mode 100755 index 0000000000..03dee40604 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/box.hpp @@ -0,0 +1,167 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +< + std::size_t Index, + std::size_t Dimension, + std::size_t DimensionCount +> +struct envelope_indexed_box +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + detail::indexed_point_view box_in_corner(box_in); + detail::indexed_point_view mbr_corner(mbr); + + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + +template +< + std::size_t Index, + std::size_t DimensionCount +> +struct envelope_indexed_box_on_spheroid +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + // transform() does not work with boxes of dimension higher + // than 2; to account for such boxes we transform the min/max + // points of the boxes using the indexed_point_view + detail::indexed_point_view box_in_corner(box_in); + detail::indexed_point_view mbr_corner(mbr); + + // first transform the units + transform_units(box_in_corner, mbr_corner); + + // now transform the remaining coordinates + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + 2, + DimensionCount + >::apply(box_in_corner, mbr_corner); + } +}; + + +struct envelope_box +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + envelope_indexed_box + < + min_corner, 0, dimension::value + >::apply(box_in, mbr); + + envelope_indexed_box + < + max_corner, 0, dimension::value + >::apply(box_in, mbr); + } +}; + + +struct envelope_box_on_spheroid +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& mbr) + { + BoxIn box_in_normalized = detail::return_normalized(box_in); + + envelope_indexed_box_on_spheroid + < + min_corner, dimension::value + >::apply(box_in_normalized, mbr); + + envelope_indexed_box_on_spheroid + < + max_corner, dimension::value + >::apply(box_in_normalized, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct envelope + : detail::envelope::envelope_box +{}; + + +template +struct envelope + : detail::envelope::envelope_box_on_spheroid +{}; + + +template +struct envelope + : detail::envelope::envelope_box_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/implementation.hpp new file mode 100755 index 0000000000..e380146b12 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/implementation.hpp @@ -0,0 +1,106 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +struct envelope_polygon +{ + template + static inline void apply(Polygon const& polygon, Box& mbr) + { + typename ring_return_type::type ext_ring + = exterior_ring(polygon); + + if (geometry::is_empty(ext_ring)) + { + // if the exterior ring is empty, consider the interior rings + envelope_multi_range + < + envelope_range + >::apply(interior_rings(polygon), mbr); + } + else + { + // otherwise, consider only the exterior ring + envelope_range::apply(ext_ring, mbr); + } + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct envelope + : detail::envelope::envelope_range +{}; + + +template +struct envelope + : detail::envelope::envelope_polygon +{}; + + +template +struct envelope + : detail::envelope::envelope_multi_range + < + detail::envelope::envelope_polygon + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/initialize.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/initialize.hpp new file mode 100755 index 0000000000..871ad64aa0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/initialize.hpp @@ -0,0 +1,86 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP + +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + +template +struct initialize_loop +{ + template + static inline void apply(Box& box, + CoordinateType min_value, + CoordinateType max_value) + { + geometry::set(box, min_value); + geometry::set(box, max_value); + + initialize_loop + < + Dimension + 1, DimensionCount + >::apply(box, min_value, max_value); + } +}; + +template +struct initialize_loop +{ + template + static inline void apply(Box&, CoordinateType, CoordinateType) + { + } +}; + + +template +< + typename Box, + std::size_t Dimension = 0, + std::size_t DimensionCount = dimension::value +> +struct initialize +{ + typedef typename coordinate_type::type coordinate_type; + + static inline void apply(Box& box, + coordinate_type min_value + = boost::numeric::bounds::highest(), + coordinate_type max_value + = boost::numeric::bounds::lowest()) + { + initialize_loop + < + Dimension, DimensionCount + >::apply(box, min_value, max_value); + } +}; + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/interface.hpp new file mode 100755 index 0000000000..f7df181382 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/interface.hpp @@ -0,0 +1,126 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace resolve_variant +{ + +template +struct envelope +{ + template + static inline void apply(Geometry const& geometry, Box& box) + { + concepts::check(); + concepts::check(); + + dispatch::envelope::apply(geometry, box); + } +}; + +template +struct envelope > +{ + template + struct visitor: boost::static_visitor + { + Box& m_box; + + visitor(Box& box): m_box(box) {} + + template + void operator()(Geometry const& geometry) const + { + envelope::apply(geometry, m_box); + } + }; + + template + static inline void + apply(boost::variant const& geometry, + Box& box) + { + boost::apply_visitor(visitor(box), geometry); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc{envelope} +\ingroup envelope +\details \details_calc{envelope,\det_envelope}. +\tparam Geometry \tparam_geometry +\tparam Box \tparam_box +\param geometry \param_geometry +\param mbr \param_box \param_set{envelope} + +\qbk{[include reference/algorithms/envelope.qbk]} +\qbk{ +[heading Example] +[envelope] [envelope_output] +} +*/ +template +inline void envelope(Geometry const& geometry, Box& mbr) +{ + resolve_variant::envelope::apply(geometry, mbr); +} + + +/*! +\brief \brief_calc{envelope} +\ingroup envelope +\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope} +\tparam Box \tparam_box +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\return \return_calc{envelope} + +\qbk{[include reference/algorithms/envelope.qbk]} +\qbk{ +[heading Example] +[return_envelope] [return_envelope_output] +} +*/ +template +inline Box return_envelope(Geometry const& geometry) +{ + Box mbr; + resolve_variant::envelope::apply(geometry, mbr); + return mbr; +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp new file mode 100755 index 0000000000..e72268c049 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp @@ -0,0 +1,78 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +namespace detail { namespace envelope +{ + + +struct intersects_antimeridian +{ + template + static inline bool apply(CoordinateType const& lon1, + CoordinateType const& lat1, + CoordinateType const& lon2, + CoordinateType const& lat2) + { + typedef math::detail::constants_on_spheroid + < + CoordinateType, Units + > constants; + + return + math::equals(math::abs(lat1), constants::max_latitude()) + || + math::equals(math::abs(lat2), constants::max_latitude()) + || + math::larger(math::abs(lon1 - lon2), constants::half_period()); + } + + template + static inline bool apply(Segment const& segment) + { + return apply(detail::indexed_point_view(segment), + detail::indexed_point_view(segment)); + } + + template + static inline bool apply(Point const& p1, Point const& p2) + { + Point p1_normalized = detail::return_normalized(p1); + Point p2_normalized = detail::return_normalized(p2); + + return apply + < + typename coordinate_system::type::units + >(geometry::get<0>(p1_normalized), + geometry::get<1>(p1_normalized), + geometry::get<0>(p2_normalized), + geometry::get<1>(p2_normalized)); + } +}; + + +}} // namespace detail::envelope + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/linear.hpp new file mode 100755 index 0000000000..ef993f83cb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/linear.hpp @@ -0,0 +1,96 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP + +#include +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +struct envelope_linestring_on_spheroid +{ + template + static inline void apply(Linestring const& linestring, Box& mbr) + { + envelope_range::apply(geometry::segments_begin(linestring), + geometry::segments_end(linestring), + mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct envelope + : detail::envelope::envelope_range +{}; + +template +struct envelope + : detail::envelope::envelope_linestring_on_spheroid +{}; + + +template +struct envelope + < + MultiLinestring, multi_linestring_tag, CS_Tag + > : detail::envelope::envelope_multi_range + < + detail::envelope::envelope_range + > +{}; + +template +struct envelope + < + MultiLinestring, multi_linestring_tag, spherical_equatorial_tag + > : detail::envelope::envelope_multi_range_on_spheroid + < + detail::envelope::envelope_linestring_on_spheroid + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp new file mode 100755 index 0000000000..8f41b7413e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/multipoint.hpp @@ -0,0 +1,378 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +class envelope_multipoint_on_spheroid +{ +private: + template + struct coordinate_less + { + template + inline bool operator()(Point const& point1, Point const& point2) const + { + return math::smaller(geometry::get(point1), + geometry::get(point2)); + } + }; + + template + static inline void analyze_point_coordinates(MultiPoint const& multipoint, + bool& has_south_pole, + bool& has_north_pole, + OutputIterator oit) + { + typedef typename boost::range_value::type point_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + // analyze point coordinates: + // (1) normalize point coordinates + // (2) check if any point is the north or the south pole + // (3) put all non-pole points in a container + // + // notice that at this point in the algorithm, we have at + // least two points on the spheroid + has_south_pole = false; + has_north_pole = false; + + for (iterator_type it = boost::begin(multipoint); + it != boost::end(multipoint); + ++it) + { + point_type point = detail::return_normalized(*it); + + if (math::equals(geometry::get<1>(point), + Constants::min_latitude())) + { + has_south_pole = true; + } + else if (math::equals(geometry::get<1>(point), + Constants::max_latitude())) + { + has_north_pole = true; + } + else + { + *oit++ = point; + } + } + } + + template + static inline Value maximum_gap(SortedRange const& sorted_range, + Value& max_gap_left, + Value& max_gap_right) + { + typedef typename boost::range_iterator + < + SortedRange const + >::type iterator_type; + + iterator_type it1 = boost::begin(sorted_range), it2 = it1; + ++it2; + max_gap_left = geometry::get<0>(*it1); + max_gap_right = geometry::get<0>(*it2); + + Value max_gap = max_gap_right - max_gap_left; + for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2) + { + Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1); + if (math::larger(gap, max_gap)) + { + max_gap_left = geometry::get<0>(*it1); + max_gap_right = geometry::get<0>(*it2); + max_gap = gap; + } + } + + return max_gap; + } + + template + < + typename Constants, + typename PointRange, + typename LongitudeLess, + typename CoordinateType + > + static inline void get_min_max_longitudes(PointRange& range, + LongitudeLess const& lon_less, + CoordinateType& lon_min, + CoordinateType& lon_max) + { + typedef typename boost::range_iterator + < + PointRange const + >::type iterator_type; + + // compute min and max longitude values + std::pair min_max_longitudes + = boost::minmax_element(boost::begin(range), + boost::end(range), + lon_less); + + lon_min = geometry::get<0>(*min_max_longitudes.first); + lon_max = geometry::get<0>(*min_max_longitudes.second); + + // if the longitude span is "large" compute the true maximum gap + if (math::larger(lon_max - lon_min, Constants::half_period())) + { + std::sort(boost::begin(range), boost::end(range), lon_less); + + CoordinateType max_gap_left = 0, max_gap_right = 0; + CoordinateType max_gap + = maximum_gap(range, max_gap_left, max_gap_right); + + CoordinateType complement_gap + = Constants::period() + lon_min - lon_max; + + if (math::larger(max_gap, complement_gap)) + { + lon_min = max_gap_right; + lon_max = max_gap_left + Constants::period(); + } + } + } + + template + < + typename Constants, + typename Iterator, + typename LatitudeLess, + typename CoordinateType + > + static inline void get_min_max_latitudes(Iterator const first, + Iterator const last, + LatitudeLess const& lat_less, + bool has_south_pole, + bool has_north_pole, + CoordinateType& lat_min, + CoordinateType& lat_max) + { + if (has_south_pole && has_north_pole) + { + lat_min = Constants::min_latitude(); + lat_max = Constants::max_latitude(); + } + else if (has_south_pole) + { + lat_min = Constants::min_latitude(); + lat_max + = geometry::get<1>(*std::max_element(first, last, lat_less)); + } + else if (has_north_pole) + { + lat_min + = geometry::get<1>(*std::min_element(first, last, lat_less)); + lat_max = Constants::max_latitude(); + } + else + { + std::pair min_max_latitudes + = boost::minmax_element(first, last, lat_less); + + lat_min = geometry::get<1>(*min_max_latitudes.first); + lat_max = geometry::get<1>(*min_max_latitudes.second); + } + } + +public: + template + static inline void apply(MultiPoint const& multipoint, Box& mbr) + { + typedef typename point_type::type point_type; + typedef typename coordinate_type::type coordinate_type; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator_type; + + typedef math::detail::constants_on_spheroid + < + coordinate_type, + typename coordinate_system::type::units + > constants; + + if (boost::empty(multipoint)) + { + initialize::value>::apply(mbr); + return; + } + + initialize::apply(mbr); + + if (boost::size(multipoint) == 1) + { + return dispatch::envelope + < + typename boost::range_value::type + >::apply(range::front(multipoint), mbr); + } + + // analyze the points and put the non-pole ones in the + // points vector + std::vector points; + bool has_north_pole = false, has_south_pole = false; + + analyze_point_coordinates(multipoint, + has_south_pole, has_north_pole, + std::back_inserter(points)); + + coordinate_type lon_min, lat_min, lon_max, lat_max; + if (points.size() == 1) + { + // we have one non-pole point and at least one pole point + lon_min = geometry::get<0>(range::front(points)); + lon_max = geometry::get<0>(range::front(points)); + lat_min = has_south_pole + ? constants::min_latitude() + : constants::max_latitude(); + lat_max = has_north_pole + ? constants::max_latitude() + : constants::min_latitude(); + } + else if (points.empty()) + { + // all points are pole points + BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole); + lon_min = coordinate_type(0); + lon_max = coordinate_type(0); + lat_min = has_south_pole + ? constants::min_latitude() + : constants::max_latitude(); + lat_max = (has_north_pole) + ? constants::max_latitude() + : constants::min_latitude(); + } + else + { + get_min_max_longitudes(points, + coordinate_less<0>(), + lon_min, + lon_max); + + get_min_max_latitudes(points.begin(), + points.end(), + coordinate_less<1>(), + has_south_pole, + has_north_pole, + lat_min, + lat_max); + } + + typedef typename helper_geometry + < + Box, + coordinate_type, + typename coordinate_system::type::units + >::type helper_box_type; + + helper_box_type helper_mbr; + + geometry::set(helper_mbr, lon_min); + geometry::set(helper_mbr, lat_min); + geometry::set(helper_mbr, lon_max); + geometry::set(helper_mbr, lat_max); + + // now transform to output MBR (per index) + envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); + envelope_indexed_box_on_spheroid::apply(helper_mbr, mbr); + + // compute envelope for higher coordinates + iterator_type it = boost::begin(multipoint); + envelope_one_point<2, dimension::value>::apply(*it, mbr); + + for (++it; it != boost::end(multipoint); ++it) + { + detail::expand::point_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + 2, dimension::value + >::apply(mbr, *it); + } + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct envelope + : detail::envelope::envelope_range +{}; + +template +struct envelope + : detail::envelope::envelope_multipoint_on_spheroid +{}; + +template +struct envelope + : detail::envelope::envelope_multipoint_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/point.hpp new file mode 100755 index 0000000000..38f4c40b9b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/point.hpp @@ -0,0 +1,127 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +struct envelope_one_point +{ + template + static inline void apply(Point const& point, Box& mbr) + { + detail::indexed_point_view box_corner(mbr); + detail::conversion::point_to_point + < + Point, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(point, box_corner); + } + + template + static inline void apply(Point const& point, Box& mbr) + { + apply(point, mbr); + apply(point, mbr); + } +}; + + +struct envelope_point_on_spheroid +{ + template + static inline void apply(Point const& point, Box& mbr) + { + Point normalized_point = detail::return_normalized(point); + + typename point_type::type box_point; + + // transform units of input point to units of a box point + transform_units(normalized_point, box_point); + + geometry::set(mbr, geometry::get<0>(box_point)); + geometry::set(mbr, geometry::get<1>(box_point)); + + geometry::set(mbr, geometry::get<0>(box_point)); + geometry::set(mbr, geometry::get<1>(box_point)); + + envelope_one_point + < + 2, dimension::value + >::apply(normalized_point, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct envelope + : detail::envelope::envelope_one_point<0, dimension::value> +{}; + + +template +struct envelope + : detail::envelope::envelope_point_on_spheroid +{}; + + +template +struct envelope + : detail::envelope::envelope_point_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/range.hpp new file mode 100755 index 0000000000..8568b00137 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/range.hpp @@ -0,0 +1,179 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP + +#include +#include + +#include + +#include + +#include + +#include + +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +// implementation for simple ranges +struct envelope_range +{ + template + static inline void apply(Iterator first, Iterator last, Box& mbr) + { + typedef typename std::iterator_traits::value_type value_type; + + // initialize MBR + initialize::value>::apply(mbr); + + Iterator it = first; + if (it != last) + { + // initialize box with first element in range + dispatch::envelope::apply(*it, mbr); + + // consider now the remaining elements in the range (if any) + for (++it; it != last; ++it) + { + dispatch::expand::apply(mbr, *it); + } + } + } + + template + static inline void apply(Range const& range, Box& mbr) + { + return apply(boost::begin(range), boost::end(range), mbr); + } +}; + + +// implementation for multi-ranges +template +struct envelope_multi_range +{ + template + static inline void apply(MultiRange const& multirange, Box& mbr) + { + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator_type; + + bool initialized = false; + for (iterator_type it = boost::begin(multirange); + it != boost::end(multirange); + ++it) + { + if (! geometry::is_empty(*it)) + { + if (initialized) + { + Box helper_mbr; + EnvelopePolicy::apply(*it, helper_mbr); + + dispatch::expand::apply(mbr, helper_mbr); + } + else + { + // compute the initial envelope + EnvelopePolicy::apply(*it, mbr); + initialized = true; + } + } + } + + if (! initialized) + { + // if not already initialized, initialize MBR + initialize::value>::apply(mbr); + } + } +}; + + +// implementation for multi-range on a spheroid (longitude is periodic) +template +struct envelope_multi_range_on_spheroid +{ + template + static inline void apply(MultiRange const& multirange, Box& mbr) + { + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator_type; + + // due to the periodicity of longitudes we need to compute the boxes + // of all the single geometries and keep them in a container + std::vector boxes; + for (iterator_type it = boost::begin(multirange); + it != boost::end(multirange); + ++it) + { + if (! geometry::is_empty(*it)) + { + Box helper_box; + EnvelopePolicy::apply(*it, helper_box); + boxes.push_back(helper_box); + } + } + + // now we need to compute the envelope of the range of boxes + // (cannot be done in an incremental fashion as in the + // Cartesian coordinate system) + // if all single geometries are empty no boxes have been found + // and the MBR is simply initialized + if (! boxes.empty()) + { + envelope_range_of_boxes::apply(boxes, mbr); + } + else + { + initialize::value>::apply(mbr); + } + + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp new file mode 100755 index 0000000000..bc00a32302 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp @@ -0,0 +1,326 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +class longitude_interval +{ + typedef T const& reference_type; + +public: + typedef T value_type; + typedef T difference_type; + + longitude_interval(T const& left, T const& right) + { + m_end[0] = left; + m_end[1] = right; + } + + template + reference_type get() const + { + return m_end[Index]; + } + + difference_type length() const + { + return get<1>() - get<0>(); + } + +private: + T m_end[2]; +}; + + +template +struct envelope_range_of_longitudes +{ + template + struct longitude_less + { + template + inline bool operator()(Interval const& i1, Interval const& i2) const + { + return math::smaller(i1.template get(), + i2.template get()); + } + }; + + template + static inline void apply(RangeOfLongitudeIntervals const& range, + Longitude& lon_min, Longitude& lon_max) + { + typedef typename math::detail::constants_on_spheroid + < + Longitude, Units + > constants; + + Longitude const zero = 0; + Longitude const period = constants::period(); + + lon_min = lon_max = zero; + + // the range of longitude intervals can be empty if all input boxes + // degenerate to the north or south pole (or combination of the two) + // in this case the initialization values for lon_min and + // lon_max are valid choices + if (! boost::empty(range)) + { + lon_min = std::min_element(boost::begin(range), + boost::end(range), + longitude_less<0>())->template get<0>(); + lon_max = std::max_element(boost::begin(range), + boost::end(range), + longitude_less<1>())->template get<1>(); + + if (math::larger(lon_max - lon_min, constants::half_period())) + { + Longitude max_gap_left, max_gap_right; + Longitude max_gap = geometry::maximum_gap(range, + max_gap_left, + max_gap_right); + + BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max)); + BOOST_GEOMETRY_ASSERT + (! math::larger(lon_max, constants::max_longitude())); + BOOST_GEOMETRY_ASSERT + (! math::smaller(lon_min, constants::min_longitude())); + + BOOST_GEOMETRY_ASSERT + (! math::larger(max_gap_left, max_gap_right)); + BOOST_GEOMETRY_ASSERT + (! math::larger(max_gap_right, constants::max_longitude())); + BOOST_GEOMETRY_ASSERT + (! math::smaller(max_gap_left, constants::min_longitude())); + + if (math::larger(max_gap, zero)) + { + Longitude wrapped_gap = period + lon_min - lon_max; + if (math::larger(max_gap, wrapped_gap)) + { + lon_min = max_gap_right; + lon_max = max_gap_left + period; + } + } + } + } + } +}; + + +template +struct envelope_range_of_boxes_by_expansion +{ + template + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + { + typedef typename boost::range_value::type box_type; + + typedef typename boost::range_iterator + < + RangeOfBoxes const + >::type iterator_type; + + // first initialize MBR + detail::indexed_point_view mbr_min(mbr); + detail::indexed_point_view mbr_max(mbr); + + detail::indexed_point_view + first_box_min(range::front(range_of_boxes)); + + detail::indexed_point_view + first_box_max(range::front(range_of_boxes)); + + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(first_box_min, mbr_min); + + detail::conversion::point_to_point + < + detail::indexed_point_view, + detail::indexed_point_view, + Dimension, + DimensionCount + >::apply(first_box_max, mbr_max); + + // now expand using the remaining boxes + iterator_type it = boost::begin(range_of_boxes); + for (++it; it != boost::end(range_of_boxes); ++it) + { + detail::expand::indexed_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + min_corner, + Dimension, + DimensionCount + >::apply(mbr, *it); + + detail::expand::indexed_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + max_corner, + Dimension, + DimensionCount + >::apply(mbr, *it); + } + } + +}; + + +struct envelope_range_of_boxes +{ + template + struct latitude_less + { + template + inline bool operator()(Box const& box1, Box const& box2) const + { + return math::smaller(geometry::get(box1), + geometry::get(box2)); + } + }; + + template + static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr) + { + // boxes in the range are assumed to be normalized already + + typedef typename boost::range_value::type box_type; + typedef typename coordinate_type::type coordinate_type; + typedef typename coordinate_system::type::units units_type; + typedef typename boost::range_iterator + < + RangeOfBoxes const + >::type iterator_type; + + typedef math::detail::constants_on_spheroid + < + coordinate_type, units_type + > constants; + + typedef longitude_interval interval_type; + typedef std::vector interval_range_type; + + BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes)); + + iterator_type it_min = std::min_element(boost::begin(range_of_boxes), + boost::end(range_of_boxes), + latitude_less()); + iterator_type it_max = std::max_element(boost::begin(range_of_boxes), + boost::end(range_of_boxes), + latitude_less()); + + coordinate_type const min_longitude = constants::min_longitude(); + coordinate_type const max_longitude = constants::max_longitude(); + coordinate_type const period = constants::period(); + + interval_range_type intervals; + for (iterator_type it = boost::begin(range_of_boxes); + it != boost::end(range_of_boxes); + ++it) + { + coordinate_type lat_min = geometry::get(*it); + coordinate_type lat_max = geometry::get(*it); + if (math::equals(lat_min, constants::max_latitude()) + || math::equals(lat_max, constants::min_latitude())) + { + // if the box degenerates to the south or north pole + // just ignore it + continue; + } + + coordinate_type lon_left = geometry::get(*it); + coordinate_type lon_right = geometry::get(*it); + + if (math::larger(lon_right, max_longitude)) + { + intervals.push_back(interval_type(lon_left, max_longitude)); + intervals.push_back + (interval_type(min_longitude, lon_right - period)); + } + else + { + intervals.push_back(interval_type(lon_left, lon_right)); + } + } + + coordinate_type lon_min = 0; + coordinate_type lon_max = 0; + envelope_range_of_longitudes + < + units_type + >::apply(intervals, lon_min, lon_max); + + // do not convert units; conversion will be performed at a + // higher level + + // assign now the min/max longitude/latitude values + detail::indexed_point_view mbr_min(mbr); + detail::indexed_point_view mbr_max(mbr); + + geometry::set<0>(mbr_min, lon_min); + geometry::set<1>(mbr_min, geometry::get(*it_min)); + geometry::set<0>(mbr_max, lon_max); + geometry::set<1>(mbr_max, geometry::get(*it_max)); + + // what remains to be done is to compute the envelope range + // for the remaining dimensions (if any) + envelope_range_of_boxes_by_expansion + < + 2, dimension::value + >::apply(range_of_boxes, mbr); + } +}; + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/segment.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/segment.hpp new file mode 100755 index 0000000000..8e1e388b11 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/segment.hpp @@ -0,0 +1,408 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015, 2016. +// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +struct envelope_one_segment +{ + template + static inline void apply(Point const& p1, Point const& p2, Box& mbr) + { + envelope_one_point::apply(p1, mbr); + detail::expand::point_loop + < + strategy::compare::default_strategy, + strategy::compare::default_strategy, + Dimension, + DimensionCount + >::apply(mbr, p2); + } +}; + + +// Computes the MBR of a segment given by (lon1, lat1) and (lon2, +// lat2), and with azimuths a1 and a2 at the two endpoints of the +// segment. +// It is assumed that the spherical coordinates of the segment are +// normalized and in radians. +// The longitudes and latitudes of the endpoints are overridden by +// those of the box. +class compute_mbr_of_segment +{ +private: + // computes the azimuths of the segment with endpoints (lon1, lat1) + // and (lon2, lat2) + // radians + template + static inline void azimuths(CalculationType const& lon1, + CalculationType const& lat1, + CalculationType const& lon2, + CalculationType const& lat2, + CalculationType& a1, + CalculationType& a2) + { + BOOST_GEOMETRY_ASSERT(lon1 <= lon2); + + CalculationType dlon = lon2 - lon1; + CalculationType sin_dlon = sin(dlon); + CalculationType cos_dlon = cos(dlon); + CalculationType cos_lat1 = cos(lat1); + CalculationType cos_lat2 = cos(lat2); + CalculationType sin_lat1 = sin(lat1); + CalculationType sin_lat2 = sin(lat2); + + a1 = atan2(sin_dlon * cos_lat2, + cos_lat1 * sin_lat2 - sin_lat1 * cos_lat2 * cos_dlon); + + a2 = atan2(-sin_dlon * cos_lat1, + cos_lat2 * sin_lat1 - sin_lat2 * cos_lat1 * cos_dlon); + a2 += math::pi(); + } + + // degrees or radians + template + static inline void swap(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + std::swap(lon1, lon2); + std::swap(lat1, lat2); + } + + // radians + template + static inline bool contains_pi_half(CalculationType const& a1, + CalculationType const& a2) + { + // azimuths a1 and a2 are assumed to be in radians + BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2)); + + static CalculationType const pi_half = math::half_pi(); + + return (a1 < a2) + ? (a1 < pi_half && pi_half < a2) + : (a1 > pi_half && pi_half > a2); + } + + // radians or degrees + template + static inline bool crosses_antimeridian(CoordinateType const& lon1, + CoordinateType const& lon2) + { + typedef math::detail::constants_on_spheroid + < + CoordinateType, Units + > constants; + + return math::abs(lon1 - lon2) > constants::half_period(); // > pi + } + + // radians + template + static inline CalculationType max_latitude(CalculationType const& azimuth, + CalculationType const& latitude) + { + // azimuth and latitude are assumed to be in radians + return acos( math::abs(cos(latitude) * sin(azimuth)) ); + } + + // degrees or radians + template + static inline void compute_box_corners(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + // coordinates are assumed to be in radians + BOOST_GEOMETRY_ASSERT(lon1 <= lon2); + + CalculationType lon1_rad = math::as_radian(lon1); + CalculationType lat1_rad = math::as_radian(lat1); + CalculationType lon2_rad = math::as_radian(lon2); + CalculationType lat2_rad = math::as_radian(lat2); + + CalculationType a1 = 0, a2 = 0; + azimuths(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2); + + if (lat1 > lat2) + { + std::swap(lat1, lat2); + std::swap(lat1_rad, lat2_rad); + } + + if (math::equals(a1, a2)) + { + // the segment must lie on the equator or is very short + return; + } + + if (contains_pi_half(a1, a2)) + { + CalculationType const mid_lat = lat1 + lat2; + if (mid_lat < 0) + { + // update using min latitude + CalculationType const lat_min_rad = -max_latitude(a1, lat1_rad); + CalculationType const lat_min = math::from_radian(lat_min_rad); + + if (lat1 > lat_min) + { + lat1 = lat_min; + } + } + else if (mid_lat > 0) + { + // update using max latitude + CalculationType const lat_max_rad = max_latitude(a1, lat1_rad); + CalculationType const lat_max = math::from_radian(lat_max_rad); + + if (lat2 < lat_max) + { + lat2 = lat_max; + } + } + } + } + + template + static inline void apply(CalculationType& lon1, + CalculationType& lat1, + CalculationType& lon2, + CalculationType& lat2) + { + typedef math::detail::constants_on_spheroid + < + CalculationType, Units + > constants; + + bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude()); + bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude()); + + if (is_pole1 && is_pole2) + { + // both points are poles; nothing more to do: + // longitudes are already normalized to 0 + // but just in case + lon1 = 0; + lon2 = 0; + } + else if (is_pole1 && !is_pole2) + { + // first point is a pole, second point is not: + // make the longitude of the first point the same as that + // of the second point + lon1 = lon2; + } + else if (!is_pole1 && is_pole2) + { + // second point is a pole, first point is not: + // make the longitude of the second point the same as that + // of the first point + lon2 = lon1; + } + + if (lon1 == lon2) + { + // segment lies on a meridian + if (lat1 > lat2) + { + std::swap(lat1, lat2); + } + return; + } + + BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2); + + if (lon1 > lon2) + { + swap(lon1, lat1, lon2, lat2); + } + + if (crosses_antimeridian(lon1, lon2)) + { + lon1 += constants::period(); + swap(lon1, lat1, lon2, lat2); + } + + compute_box_corners(lon1, lat1, lon2, lat2); + } + +public: + template + static inline void apply(CalculationType lon1, + CalculationType lat1, + CalculationType lon2, + CalculationType lat2, + Box& mbr) + { + typedef typename coordinate_type::type box_coordinate_type; + + typedef typename helper_geometry + < + Box, box_coordinate_type, Units + >::type helper_box_type; + + helper_box_type radian_mbr; + + apply(lon1, lat1, lon2, lat2); + + geometry::set + < + min_corner, 0 + >(radian_mbr, boost::numeric_cast(lon1)); + + geometry::set + < + min_corner, 1 + >(radian_mbr, boost::numeric_cast(lat1)); + + geometry::set + < + max_corner, 0 + >(radian_mbr, boost::numeric_cast(lon2)); + + geometry::set + < + max_corner, 1 + >(radian_mbr, boost::numeric_cast(lat2)); + + transform_units(radian_mbr, mbr); + } +}; + + +template +struct envelope_segment_on_sphere +{ + template + static inline void apply(Point const& p1, Point const& p2, Box& mbr) + { + // first compute the envelope range for the first two coordinates + Point p1_normalized = detail::return_normalized(p1); + Point p2_normalized = detail::return_normalized(p2); + + typedef typename coordinate_system::type::units units_type; + + compute_mbr_of_segment::template apply( + geometry::get<0>(p1_normalized), + geometry::get<1>(p1_normalized), + geometry::get<0>(p2_normalized), + geometry::get<1>(p2_normalized), + mbr); + + // now compute the envelope range for coordinates of + // dimension 2 and higher + envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr); + } + + template + static inline void apply(Segment const& segment, Box& mbr) + { + typename point_type::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + apply(p[0], p[1], mbr); + } +}; + + + +template +struct envelope_segment + : envelope_one_segment<0, DimensionCount> +{}; + + +template +struct envelope_segment + : envelope_segment_on_sphere +{}; + + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct envelope +{ + template + static inline void apply(Segment const& segment, Box& mbr) + { + typename point_type::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + detail::envelope::envelope_segment + < + dimension::value, CS_Tag + >::apply(p[0], p[1], mbr); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp new file mode 100755 index 0000000000..3314826c13 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/envelope/transform_units.hpp @@ -0,0 +1,103 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace envelope +{ + + +template +< + typename GeometryIn, + typename GeometryOut, + typename TagIn = typename tag::type, + typename TagOut = typename tag::type +> +struct transform_units_impl + : not_implemented +{}; + +template +struct transform_units_impl +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + detail::two_dimensional_view view_in(point_in); + detail::two_dimensional_view view_out(point_out); + + geometry::transform(view_in, view_out); + } +}; + +template +struct transform_units_impl +{ + template + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + typedef detail::indexed_point_view view_in_type; + typedef detail::indexed_point_view view_out_type; + + view_in_type view_in(box_in); + view_out_type view_out(box_out); + + transform_units_impl + < + view_in_type, view_out_type + >::apply(view_in, view_out); + } + + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + apply(box_in, box_out); + apply(box_in, box_out); + } +}; + + +// Short utility to transform the units of the first two coordinates of +// geometry_in to the units of geometry_out +template +inline void transform_units(GeometryIn const& geometry_in, + GeometryOut& geometry_out) +{ + transform_units_impl + < + GeometryIn, GeometryOut + >::apply(geometry_in, geometry_out); +} + + +}} // namespace detail::envelope +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost:geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_TRANSFORM_UNITS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp new file mode 100755 index 0000000000..0e70bccca6 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp @@ -0,0 +1,538 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP + + +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +// Since these vectors (though ray would be a better name) are used in the +// implementation of equals() for Areal geometries the internal representation +// should be consistent with the default side strategy for CS because currently +// it's used in other relops. + +template < + typename T, + typename Geometry, + typename CSTag = typename cs_tag::type +> +struct collected_vector +{ + typedef T type; + + inline collected_vector() + {} + + inline collected_vector(T const& px, T const& py, + T const& pdx, T const& pdy) + : x(px) + , y(py) + , dx(pdx) + , dy(pdy) + //, dx_0(dx) + //, dy_0(dy) + {} + + template + inline collected_vector(Point const& p1, Point const& p2) + : x(get<0>(p1)) + , y(get<1>(p1)) + , dx(get<0>(p2) - x) + , dy(get<1>(p2) - y) + //, dx_0(dx) + //, dy_0(dy) + {} + + bool normalize() + { + T magnitude = math::sqrt( + boost::numeric_cast(dx * dx + dy * dy)); + + // NOTE: shouldn't here math::equals() be called? + if (magnitude > 0) + { + dx /= magnitude; + dy /= magnitude; + return true; + } + + return false; + } + + // For sorting + inline bool operator<(collected_vector const& other) const + { + if (math::equals(x, other.x)) + { + if (math::equals(y, other.y)) + { + if (math::equals(dx, other.dx)) + { + return dy < other.dy; + } + return dx < other.dx; + } + return y < other.y; + } + return x < other.x; + } + + inline bool next_is_collinear(collected_vector const& other) const + { + return same_direction(other); + } + + // For std::equals + inline bool operator==(collected_vector const& other) const + { + return math::equals(x, other.x) + && math::equals(y, other.y) + && same_direction(other); + } + +private: + inline bool same_direction(collected_vector const& other) const + { + // For high precision arithmetic, we have to be + // more relaxed then using == + // Because 2/sqrt( (0,0)<->(2,2) ) == 1/sqrt( (0,0)<->(1,1) ) + // is not always true (at least, it is not for ttmath) + return math::equals_with_epsilon(dx, other.dx) + && math::equals_with_epsilon(dy, other.dy); + } + + T x, y; + T dx, dy; + //T dx_0, dy_0; +}; + +template +struct collected_vector +{ + typedef T type; + + typedef typename coordinate_system::type cs_type; + typedef model::point point_type; + typedef model::point vector_type; + + collected_vector() + {} + + template + collected_vector(Point const& p1, Point const& p2) + : origin(get<0>(p1), get<1>(p1)) + { + origin = detail::return_normalized(origin); + + using namespace geometry::formula; + prev = sph_to_cart3d(p1); + next = sph_to_cart3d(p2); + direction = cross_product(prev, next); + } + + bool normalize() + { + T magnitude_sqr = dot_product(direction, direction); + + // NOTE: shouldn't here math::equals() be called? + if (magnitude_sqr > 0) + { + divide_value(direction, math::sqrt(magnitude_sqr)); + return true; + } + + return false; + } + + bool operator<(collected_vector const& other) const + { + if (math::equals(get<0>(origin), get<0>(other.origin))) + { + if (math::equals(get<1>(origin), get<1>(other.origin))) + { + if (math::equals(get<0>(direction), get<0>(other.direction))) + { + if (math::equals(get<1>(direction), get<1>(other.direction))) + { + return get<2>(direction) < get<2>(other.direction); + } + return get<1>(direction) < get<1>(other.direction); + } + return get<0>(direction) < get<0>(other.direction); + } + return get<1>(origin) < get<1>(other.origin); + } + return get<0>(origin) < get<0>(other.origin); + } + + // For consistency with side and intersection strategies used by relops + // IMPORTANT: this method should be called for previous vector + // and next vector should be passed as parameter + bool next_is_collinear(collected_vector const& other) const + { + return formula::sph_side_value(direction, other.next) == 0; + } + + // For std::equals + bool operator==(collected_vector const& other) const + { + return math::equals(get<0>(origin), get<0>(other.origin)) + && math::equals(get<1>(origin), get<1>(other.origin)) + && is_collinear(other); + } + +private: + // For consistency with side and intersection strategies used by relops + bool is_collinear(collected_vector const& other) const + { + return formula::sph_side_value(direction, other.prev) == 0 + && formula::sph_side_value(direction, other.next) == 0; + } + + /*bool same_direction(collected_vector const& other) const + { + return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction)) + && math::equals_with_epsilon(get<1>(direction), get<1>(other.direction)) + && math::equals_with_epsilon(get<2>(direction), get<2>(other.direction)); + }*/ + + point_type origin; // used for sorting and equality check + vector_type direction; // used for sorting, only in operator< + vector_type prev; // used for collinearity check, only in operator== + vector_type next; // used for collinearity check +}; + +template +struct collected_vector + : public collected_vector +{ + typedef collected_vector base_type; + + collected_vector() {} + + template + collected_vector(Point const& p1, Point const& p2) + : base_type(to_equatorial(p1), to_equatorial(p2)) + {} + +private: + template + Point polar_to_equatorial(Point const& p) + { + typedef typename coordinate_type::type coord_type; + + typedef math::detail::constants_on_spheroid + < + coord_type, + typename coordinate_system::type::units + > constants; + + coord_type const pi_2 = constants::half_period() / 2; + + Point res = p; + set<1>(res, pi_2 - get<1>(p)); + return res; + } +}; + +// This is consistent with the currently used default geographic side +// and intersection strategies. Spherical strategies are used by default. +// When default strategies are changed in the future this specialization +// should be changed too. +template +struct collected_vector + : public collected_vector +{ + typedef collected_vector base_type; + + collected_vector() {} + + template + collected_vector(Point const& p1, Point const& p2) + : base_type(p1, p2) + {} +}; + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace collect_vectors +{ + + +template +struct range_collect_vectors +{ + typedef typename boost::range_value::type item_type; + typedef typename item_type::type calculation_type; + + static inline void apply(Collection& collection, Range const& range) + { + if (boost::size(range) < 2) + { + return; + } + + typedef typename boost::range_size::type collection_size_t; + collection_size_t c_old_size = boost::size(collection); + + typedef typename boost::range_iterator::type iterator; + + bool is_first = true; + iterator it = boost::begin(range); + + for (iterator prev = it++; + it != boost::end(range); + prev = it++) + { + typename boost::range_value::type v(*prev, *it); + + // Normalize the vector -> this results in points+direction + // and is comparible between geometries + // Avoid non-duplicate points (AND division by zero) + if (v.normalize()) + { + // Avoid non-direction changing points + if (is_first || ! collection.back().next_is_collinear(v)) + { + collection.push_back(v); + } + is_first = false; + } + } + + // If first one has same direction as last one, remove first one + collection_size_t collected_count = boost::size(collection) - c_old_size; + if ( collected_count > 1 ) + { + typedef typename boost::range_iterator::type c_iterator; + c_iterator first = range::pos(collection, c_old_size); + + if (collection.back().next_is_collinear(*first) ) + { + //collection.erase(first); + // O(1) instead of O(N) + *first = collection.back(); + collection.pop_back(); + } + } + } +}; + + +// Default version (cartesian) +template ::type> +struct box_collect_vectors +{ + // Calculate on coordinate type, but if it is integer, + // then use double + typedef typename boost::range_value::type item_type; + typedef typename item_type::type calculation_type; + + static inline void apply(Collection& collection, Box const& box) + { + typename point_type::type lower_left, lower_right, + upper_left, upper_right; + geometry::detail::assign_box_corners(box, lower_left, lower_right, + upper_left, upper_right); + + typedef typename boost::range_value::type item; + + collection.push_back(item(get<0>(lower_left), get<1>(lower_left), 0, 1)); + collection.push_back(item(get<0>(upper_left), get<1>(upper_left), 1, 0)); + collection.push_back(item(get<0>(upper_right), get<1>(upper_right), 0, -1)); + collection.push_back(item(get<0>(lower_right), get<1>(lower_right), -1, 0)); + } +}; + +// NOTE: This is not fully correct because Box in spherical and geographic +// cordinate systems cannot be seen as Polygon +template +struct box_collect_vectors +{ + static inline void apply(Collection& collection, Box const& box) + { + typename point_type::type lower_left, lower_right, + upper_left, upper_right; + geometry::detail::assign_box_corners(box, lower_left, lower_right, + upper_left, upper_right); + + typedef typename boost::range_value::type item; + + collection.push_back(item(lower_left, upper_left)); + collection.push_back(item(upper_left, upper_right)); + collection.push_back(item(upper_right, lower_right)); + collection.push_back(item(lower_right, lower_left)); + } +}; + +template +struct box_collect_vectors + : box_collect_vectors +{}; + +template +struct box_collect_vectors + : box_collect_vectors +{}; + + +template +struct polygon_collect_vectors +{ + static inline void apply(Collection& collection, Polygon const& polygon) + { + typedef typename geometry::ring_type::type ring_type; + + typedef range_collect_vectors per_range; + per_range::apply(collection, exterior_ring(polygon)); + + typename interior_return_type::type + rings = interior_rings(polygon); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + per_range::apply(collection, *it); + } + } +}; + + +template +struct multi_collect_vectors +{ + static inline void apply(Collection& collection, MultiGeometry const& multi) + { + for (typename boost::range_iterator::type + it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + SinglePolicy::apply(collection, *it); + } + } +}; + + +}} // namespace detail::collect_vectors +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Tag, + typename Collection, + typename Geometry +> +struct collect_vectors +{ + static inline void apply(Collection&, Geometry const&) + {} +}; + + +template +struct collect_vectors + : detail::collect_vectors::box_collect_vectors +{}; + + + +template +struct collect_vectors + : detail::collect_vectors::range_collect_vectors +{}; + + +template +struct collect_vectors + : detail::collect_vectors::range_collect_vectors +{}; + + +template +struct collect_vectors + : detail::collect_vectors::polygon_collect_vectors +{}; + + +template +struct collect_vectors + : detail::collect_vectors::multi_collect_vectors + < + MultiPolygon, + Collection, + detail::collect_vectors::polygon_collect_vectors + < + typename boost::range_value::type, + Collection + > + > +{}; + + + +} // namespace dispatch +#endif + + +/*! + \ingroup collect_vectors + \tparam Collection Collection type, should be e.g. std::vector<> + \tparam Geometry geometry type + \param collection the collection of vectors + \param geometry the geometry to make collect_vectors +*/ +template +inline void collect_vectors(Collection& collection, Geometry const& geometry) +{ + concepts::check(); + + dispatch::collect_vectors + < + typename tag::type, + Collection, + Geometry + >::apply(collection, geometry); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/equals/point_point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/equals/point_point.hpp new file mode 100755 index 0000000000..33e1d718e9 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/equals/point_point.hpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland + +// This file was modified by Oracle on 2013-2014. +// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace equals +{ + +/*! + \brief Internal utility function to detect of points are disjoint + \note To avoid circular references + */ +template +inline bool equals_point_point(Point1 const& point1, Point2 const& point2) +{ + return ! detail::disjoint::disjoint_point_point(point1, point2); +} + + +}} // namespace detail::equals +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/box.hpp new file mode 100755 index 0000000000..1bd5b88b70 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/box.hpp @@ -0,0 +1,126 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +struct box_on_spheroid +{ + template + static inline void apply(BoxOut& box_out, BoxIn const& box_in) + { + // normalize both boxes and convert box-in to be of type of box-out + BoxOut mbrs[2]; + detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]); + detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]); + + // compute the envelope of the two boxes + detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Box + box -> new box containing two input boxes +template +< + typename BoxOut, typename BoxIn, + typename StrategyLess, typename StrategyGreater, + typename CSTagOut, typename CSTag +> +struct expand + < + BoxOut, BoxIn, + StrategyLess, StrategyGreater, + box_tag, box_tag, + CSTagOut, CSTag + > : detail::expand::expand_indexed + < + 0, dimension::value, StrategyLess, StrategyGreater + > +{ + BOOST_MPL_ASSERT_MSG((boost::is_same::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types())); +}; + +template +< + typename BoxOut, typename BoxIn, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, BoxIn, + StrategyLess, StrategyGreater, + box_tag, box_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::box_on_spheroid +{}; + +template +< + typename BoxOut, typename BoxIn, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, BoxIn, + StrategyLess, StrategyGreater, + box_tag, box_tag, + geographic_tag, geographic_tag + > : detail::expand::box_on_spheroid +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/implementation.hpp new file mode 100755 index 0000000000..8bbc75fddf --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/implementation.hpp @@ -0,0 +1,27 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP + +#include +#include +#include + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/indexed.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/indexed.hpp new file mode 100755 index 0000000000..8d607c8afc --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/indexed.hpp @@ -0,0 +1,144 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Index, + std::size_t Dimension, std::size_t DimensionCount +> +struct indexed_loop +{ + template + static inline void apply(Box& box, Geometry const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Box, Dimension + >::type less_type; + + typedef typename strategy::compare::detail::select_strategy + < + StrategyGreater, -1, Box, Dimension + >::type greater_type; + + typedef typename select_coordinate_type + < + Box, + Geometry + >::type coordinate_type; + + less_type less; + greater_type greater; + + coordinate_type const coord = get(source); + + if (less(coord, get(box))) + { + set(box, coord); + } + + if (greater(coord, get(box))) + { + set(box, coord); + } + + indexed_loop + < + StrategyLess, StrategyGreater, + Index, Dimension + 1, DimensionCount + >::apply(box, source); + } +}; + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Index, std::size_t DimensionCount +> +struct indexed_loop + < + StrategyLess, StrategyGreater, + Index, DimensionCount, DimensionCount + > +{ + template + static inline void apply(Box&, Geometry const&) {} +}; + + + +// Changes a box such that the other box is also contained by the box +template +< + std::size_t Dimension, std::size_t DimensionCount, + typename StrategyLess, typename StrategyGreater +> +struct expand_indexed +{ + template + static inline void apply(Box& box, Geometry const& geometry) + { + indexed_loop + < + StrategyLess, StrategyGreater, + 0, Dimension, DimensionCount + >::apply(box, geometry); + + indexed_loop + < + StrategyLess, StrategyGreater, + 1, Dimension, DimensionCount + >::apply(box, geometry); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/interface.hpp new file mode 100755 index 0000000000..5663f63688 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/interface.hpp @@ -0,0 +1,128 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +namespace resolve_variant +{ + +template +struct expand +{ + template + static inline void apply(Box& box, Geometry const& geometry) + { + concepts::check(); + concepts::check(); + concepts::check_concepts_and_equal_dimensions(); + + dispatch::expand::apply(box, geometry); + } +}; + +template +struct expand > +{ + template + struct visitor: boost::static_visitor + { + Box& m_box; + + visitor(Box& box) : m_box(box) {} + + template + void operator()(Geometry const& geometry) const + { + return expand::apply(m_box, geometry); + } + }; + + template + static inline void + apply(Box& box, + boost::variant const& geometry) + { + return boost::apply_visitor(visitor(box), geometry); + } +}; + +} // namespace resolve_variant + + +/*** +*! +\brief Expands a box using the extend (envelope) of another geometry (box, point) +\ingroup expand +\tparam Box type of the box +\tparam Geometry of second geometry, to be expanded with the box +\param box box to expand another geometry with, might be changed +\param geometry other geometry +\param strategy_less +\param strategy_greater +\note Strategy is currently ignored + * +template +< + typename Box, typename Geometry, + typename StrategyLess, typename StrategyGreater +> +inline void expand(Box& box, Geometry const& geometry, + StrategyLess const& strategy_less, + StrategyGreater const& strategy_greater) +{ + concepts::check_concepts_and_equal_dimensions(); + + dispatch::expand::apply(box, geometry); +} +***/ + + +/*! +\brief Expands a box using the bounding box (envelope) of another geometry (box, point) +\ingroup expand +\tparam Box type of the box +\tparam Geometry \tparam_geometry +\param box box to be expanded using another geometry, mutable +\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box + +\qbk{[include reference/algorithms/expand.qbk]} + */ +template +inline void expand(Box& box, Geometry const& geometry) +{ + resolve_variant::expand::apply(box, geometry); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/point.hpp new file mode 100755 index 0000000000..d37fa53378 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/point.hpp @@ -0,0 +1,303 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +template +< + typename StrategyLess, typename StrategyGreater, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_loop +{ + template + static inline void apply(Box& box, Point const& source) + { + typedef typename strategy::compare::detail::select_strategy + < + StrategyLess, 1, Point, Dimension + >::type less_type; + + typedef typename strategy::compare::detail::select_strategy + < + StrategyGreater, -1, Point, Dimension + >::type greater_type; + + typedef typename select_coordinate_type + < + Point, Box + >::type coordinate_type; + + less_type less; + greater_type greater; + + coordinate_type const coord = get(source); + + if (less(coord, get(box))) + { + set(box, coord); + } + + if (greater(coord, get(box))) + { + set(box, coord); + } + + point_loop + < + StrategyLess, StrategyGreater, Dimension + 1, DimensionCount + >::apply(box, source); + } +}; + + +template +< + typename StrategyLess, typename StrategyGreater, std::size_t DimensionCount +> +struct point_loop + < + StrategyLess, StrategyGreater, DimensionCount, DimensionCount + > +{ + template + static inline void apply(Box&, Point const&) {} +}; + + +// implementation for the spherical equatorial and geographic coordinate systems +template +< + typename StrategyLess, + typename StrategyGreater, + std::size_t DimensionCount +> +struct point_loop_on_spheroid +{ + template + static inline void apply(Box& box, Point const& point) + { + typedef typename point_type::type box_point_type; + typedef typename coordinate_type::type box_coordinate_type; + + typedef math::detail::constants_on_spheroid + < + box_coordinate_type, + typename coordinate_system::type::units + > constants; + + // normalize input point and input box + Point p_normalized = detail::return_normalized(point); + detail::normalize(box, box); + + // transform input point to be of the same type as the box point + box_point_type box_point; + detail::envelope::transform_units(p_normalized, box_point); + + box_coordinate_type p_lon = geometry::get<0>(box_point); + box_coordinate_type p_lat = geometry::get<1>(box_point); + + typename coordinate_type::type + b_lon_min = geometry::get(box), + b_lat_min = geometry::get(box), + b_lon_max = geometry::get(box), + b_lat_max = geometry::get(box); + + if (math::equals(math::abs(p_lat), constants::max_latitude())) + { + // the point of expansion is the either the north or the + // south pole; the only important coordinate here is the + // pole's latitude, as the longitude can be anything; + // we, thus, take into account the point's latitude only and return + geometry::set(box, (std::min)(p_lat, b_lat_min)); + geometry::set(box, (std::max)(p_lat, b_lat_max)); + return; + } + + if (math::equals(b_lat_min, b_lat_max) + && math::equals(math::abs(b_lat_min), constants::max_latitude())) + { + // the box degenerates to either the north or the south pole; + // the only important coordinate here is the pole's latitude, + // as the longitude can be anything; + // we thus take into account the box's latitude only and return + geometry::set(box, p_lon); + geometry::set(box, (std::min)(p_lat, b_lat_min)); + geometry::set(box, p_lon); + geometry::set(box, (std::max)(p_lat, b_lat_max)); + return; + } + + // update latitudes + b_lat_min = (std::min)(b_lat_min, p_lat); + b_lat_max = (std::max)(b_lat_max, p_lat); + + // update longitudes + if (math::smaller(p_lon, b_lon_min)) + { + box_coordinate_type p_lon_shifted = p_lon + constants::period(); + + if (math::larger(p_lon_shifted, b_lon_max)) + { + // here we could check using: ! math::larger(.., ..) + if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max)) + { + b_lon_min = p_lon; + } + else + { + b_lon_max = p_lon_shifted; + } + } + } + else if (math::larger(p_lon, b_lon_max)) + { + // in this case, and since p_lon is normalized in the range + // (-180, 180], we must have that b_lon_max <= 180 + if (b_lon_min < 0 + && math::larger(p_lon - b_lon_max, + constants::period() - p_lon + b_lon_min)) + { + b_lon_min = p_lon; + b_lon_max += constants::period(); + } + else + { + b_lon_max = p_lon; + } + } + + geometry::set(box, b_lon_min); + geometry::set(box, b_lat_min); + geometry::set(box, b_lon_max); + geometry::set(box, b_lat_max); + + point_loop + < + StrategyLess, StrategyGreater, 2, DimensionCount + >::apply(box, point); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Box + point -> new box containing also point +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater, + typename CSTagOut, typename CSTag +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + CSTagOut, CSTag + > : detail::expand::point_loop + < + StrategyLess, StrategyGreater, 0, dimension::value + > +{ + BOOST_MPL_ASSERT_MSG((boost::is_same::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types())); +}; + +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::point_loop_on_spheroid + < + StrategyLess, StrategyGreater, dimension::value + > +{}; + +template +< + typename BoxOut, typename Point, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + BoxOut, Point, + StrategyLess, StrategyGreater, + box_tag, point_tag, + geographic_tag, geographic_tag + > : detail::expand::point_loop_on_spheroid + < + StrategyLess, StrategyGreater, dimension::value + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/segment.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/segment.hpp new file mode 100755 index 0000000000..b4d4d4a2bb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand/segment.hpp @@ -0,0 +1,115 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + + +struct segment_on_sphere +{ + template + static inline void apply(Box& box, Segment const& segment) + { + Box mbrs[2]; + + // compute the envelope of the segment + detail::envelope::envelope_segment_on_sphere + < + dimension::value + >::apply(segment, mbrs[0]); + + // normalize the box + detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1]); + + // compute the envelope of the two boxes + detail::envelope::envelope_range_of_boxes::apply(mbrs, box); + } +}; + + +}} // namespace detail::expand +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Box, typename Segment, + typename StrategyLess, typename StrategyGreater, + typename CSTagOut, typename CSTag +> +struct expand + < + Box, Segment, + StrategyLess, StrategyGreater, + box_tag, segment_tag, + CSTagOut, CSTag + > : detail::expand::expand_indexed + < + 0, dimension::value, StrategyLess, StrategyGreater + > +{ + BOOST_MPL_ASSERT_MSG((boost::is_same::value), + COORDINATE_SYSTEMS_MUST_BE_THE_SAME, + (types())); +}; + +template +< + typename Box, typename Segment, + typename StrategyLess, typename StrategyGreater +> +struct expand + < + Box, Segment, + StrategyLess, StrategyGreater, + box_tag, segment_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::expand::segment_on_sphere +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand_by_epsilon.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand_by_epsilon.hpp new file mode 100755 index 0000000000..f01d46f07d --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/expand_by_epsilon.hpp @@ -0,0 +1,113 @@ +// Boost.Geometry + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace expand +{ + +template +< + typename Point, + template class PlusOrMinus, + std::size_t I = 0, + std::size_t D = dimension::value, + bool Enable = boost::is_floating_point + < + typename coordinate_type::type + >::value +> +struct corner_by_epsilon +{ + static inline void apply(Point & point) + { + typedef typename coordinate_type::type coord_type; + coord_type const coord = get(point); + coord_type const eps = math::scaled_epsilon(coord); + + set(point, PlusOrMinus()(coord, eps)); + + corner_by_epsilon::apply(point); + } +}; + +template +< + typename Point, + template class PlusOrMinus, + std::size_t I, + std::size_t D +> +struct corner_by_epsilon +{ + static inline void apply(Point const&) {} +}; + +template +< + typename Point, + template class PlusOrMinus, + std::size_t D, + bool Enable +> +struct corner_by_epsilon +{ + static inline void apply(Point const&) {} +}; + +template +< + typename Point, + template class PlusOrMinus, + std::size_t D +> +struct corner_by_epsilon +{ + static inline void apply(Point const&) {} +}; + +} // namespace expand + +template +inline void expand_by_epsilon(Box & box) +{ + typedef detail::indexed_point_view min_type; + min_type min_point(box); + expand::corner_by_epsilon::apply(min_point); + + typedef detail::indexed_point_view max_type; + max_type max_point(box); + expand::corner_by_epsilon::apply(max_point); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/extreme_points.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/extreme_points.hpp new file mode 100755 index 0000000000..abf6940054 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/extreme_points.hpp @@ -0,0 +1,520 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2013 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2013 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP + + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace extreme_points +{ + +template +struct compare +{ + template + inline bool operator()(Point const& lhs, Point const& rhs) + { + return geometry::get(lhs) < geometry::get(rhs); + } +}; + + +template +inline void move_along_vector(PointType& point, PointType const& extreme, CoordinateType const& base_value) +{ + // Moves a point along the vector (point, extreme) in the direction of the extreme point + // This adapts the possibly uneven legs of the triangle (or trapezium-like shape) + // _____extreme _____ + // / \ / \ . + // /base \ => / \ point . + // \ point . + // + // For so-called intruders, it can be used to adapt both legs to the level of "base" + // For the base, it can be used to adapt both legs to the level of the max-value of the intruders + // If there are 2 or more extreme values, use the one close to 'point' to have a correct vector + + CoordinateType const value = geometry::get(point); + //if (geometry::math::equals(value, base_value)) + if (value >= base_value) + { + return; + } + + PointType vector = point; + subtract_point(vector, extreme); + + CoordinateType const diff = geometry::get(vector); + + // diff should never be zero + // because of the way our triangle/trapezium is build. + // We just return if it would be the case. + if (geometry::math::equals(diff, 0)) + { + return; + } + + CoordinateType const base_diff = base_value - geometry::get(extreme); + + multiply_value(vector, base_diff); + divide_value(vector, diff); + + // The real move: + point = extreme; + add_point(point, vector); +} + + +template +inline void move_along_vector(Range& range, CoordinateType const& base_value) +{ + if (range.size() >= 3) + { + move_along_vector(range.front(), *(range.begin() + 1), base_value); + move_along_vector(range.back(), *(range.rbegin() + 1), base_value); + } +} + + +template +struct extreme_points_on_ring +{ + + typedef typename geometry::coordinate_type::type coordinate_type; + typedef typename boost::range_iterator::type range_iterator; + typedef typename geometry::point_type::type point_type; + + typedef typename geometry::strategy::side::services::default_strategy + < + typename geometry::cs_tag::type + >::type side_strategy; + + + template + static inline bool extend(CirclingIterator& it, + std::size_t n, + coordinate_type max_coordinate_value, + Points& points, int direction) + { + std::size_t safe_index = 0; + do + { + it += direction; + + points.push_back(*it); + + if (safe_index++ >= n) + { + // E.g.: ring is completely horizontal or vertical (= invalid, but we don't want to have an infinite loop) + return false; + } + } while (geometry::math::equals(geometry::get(*it), max_coordinate_value)); + + return true; + } + + // Overload without adding to poinst + template + static inline bool extend(CirclingIterator& it, + std::size_t n, + coordinate_type max_coordinate_value, + int direction) + { + std::size_t safe_index = 0; + do + { + it += direction; + + if (safe_index++ >= n) + { + // E.g.: ring is completely horizontal or vertical (= invalid, but we don't want to have an infinite loop) + return false; + } + } while (geometry::math::equals(geometry::get(*it), max_coordinate_value)); + + return true; + } + + template + static inline bool extent_both_sides(Ring const& ring, + point_type extreme, + CirclingIterator& left, + CirclingIterator& right) + { + std::size_t const n = boost::size(ring); + coordinate_type const max_coordinate_value = geometry::get(extreme); + + if (! extend(left, n, max_coordinate_value, -1)) + { + return false; + } + if (! extend(right, n, max_coordinate_value, +1)) + { + return false; + } + + return true; + } + + template + static inline bool collect(Ring const& ring, + point_type extreme, + Collection& points, + CirclingIterator& left, + CirclingIterator& right) + { + std::size_t const n = boost::size(ring); + coordinate_type const max_coordinate_value = geometry::get(extreme); + + // Collects first left, which is reversed (if more than one point) then adds the top itself, then right + if (! extend(left, n, max_coordinate_value, points, -1)) + { + return false; + } + std::reverse(points.begin(), points.end()); + points.push_back(extreme); + if (! extend(right, n, max_coordinate_value, points, +1)) + { + return false; + } + + return true; + } + + template + static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right, + Extremes const& extremes, + Intruders& intruders) + { + if (boost::size(extremes) < 3) + { + return; + } + coordinate_type const min_value = geometry::get(*std::min_element(boost::begin(extremes), boost::end(extremes), compare())); + + // Also select left/right (if Dimension=1) + coordinate_type const other_min = geometry::get<1 - Dimension>(*std::min_element(boost::begin(extremes), boost::end(extremes), compare<1 - Dimension>())); + coordinate_type const other_max = geometry::get<1 - Dimension>(*std::max_element(boost::begin(extremes), boost::end(extremes), compare<1 - Dimension>())); + + std::size_t defensive_check_index = 0; // in case we skip over left/right check, collect modifies right too + std::size_t const n = boost::size(ring); + while (left != right && defensive_check_index < n) + { + coordinate_type const coordinate = geometry::get(*right); + coordinate_type const other_coordinate = geometry::get<1 - Dimension>(*right); + if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max) + { + int const factor = geometry::point_order::value == geometry::clockwise ? 1 : -1; + int const first_side = side_strategy::apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor; + int const last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor; + + // If not lying left from any of the extemes side + if (first_side != 1 && last_side != 1) + { + //std::cout << "first " << first_side << " last " << last_side << std::endl; + + // we start at this intrusion until it is handled, and don't affect our initial left iterator + CirclingIterator left_intrusion_it = right; + typename boost::range_value::type intruder; + collect(ring, *right, intruder, left_intrusion_it, right); + + // Also moves these to base-level, makes sorting possible which can be done in case of self-tangencies + // (we might postpone this action, it is often not necessary. However it is not time-consuming) + move_along_vector(intruder, min_value); + intruders.push_back(intruder); + --right; + } + } + ++right; + defensive_check_index++; + } + } + + template + static inline void get_intruders(Ring const& ring, + Extremes const& extremes, + Intruders& intruders) + { + std::size_t const n = boost::size(ring); + if (n >= 3) + { + geometry::ever_circling_range_iterator left(ring); + geometry::ever_circling_range_iterator right(ring); + ++right; + + get_intruders(ring, left, right, extremes, intruders); + } + } + + template + static inline bool right_turn(Ring const& ring, Iterator it) + { + typename std::iterator_traits::difference_type const index + = std::distance(boost::begin(ring), it); + geometry::ever_circling_range_iterator left(ring); + geometry::ever_circling_range_iterator right(ring); + left += index; + right += index; + + if (! extent_both_sides(ring, *it, left, right)) + { + return false; + } + + int const factor = geometry::point_order::value == geometry::clockwise ? 1 : -1; + int const first_side = side_strategy::apply(*(right - 1), *right, *left) * factor; + int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor; + +//std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl; + + // Turn should not be left (actually, it should be right because extent removes horizontal/collinear cases) + return first_side != 1 && last_side != 1; + } + + + // Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring + template + static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders) + { + std::size_t const n = boost::size(ring); + if (n < 3) + { + return false; + } + + // Get all maxima, usually one. In case of self-tangencies, or self-crossings, + // the max might be is not valid. A valid max should make a right turn + range_iterator max_it = boost::begin(ring); + compare smaller; + for (range_iterator it = max_it + 1; it != boost::end(ring); ++it) + { + if (smaller(*max_it, *it) && right_turn(ring, it)) + { + max_it = it; + } + } + + if (max_it == boost::end(ring)) + { + return false; + } + + typename std::iterator_traits::difference_type const + index = std::distance(boost::begin(ring), max_it); +//std::cout << "Extreme point lies at " << index << " having " << geometry::wkt(*max_it) << std::endl; + + geometry::ever_circling_range_iterator left(ring); + geometry::ever_circling_range_iterator right(ring); + left += index; + right += index; + + // Collect all points (often 3) in a temporary vector + std::vector points; + points.reserve(3); + if (! collect(ring, *max_it, points, left, right)) + { + return false; + } + +//std::cout << "Built vector of " << points.size() << std::endl; + + coordinate_type const front_value = geometry::get(points.front()); + coordinate_type const back_value = geometry::get(points.back()); + coordinate_type const base_value = (std::max)(front_value, back_value); + if (front_value < back_value) + { + move_along_vector(points.front(), *(points.begin() + 1), base_value); + } + else + { + move_along_vector(points.back(), *(points.rbegin() + 1), base_value); + } + + std::copy(points.begin(), points.end(), std::back_inserter(extremes)); + + get_intruders(ring, left, right, extremes, intruders); + + return true; + } +}; + + + + + +}} // namespace detail::extreme_points +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry, + std::size_t Dimension, + typename GeometryTag = typename tag::type +> +struct extreme_points +{}; + + +template +struct extreme_points + : detail::extreme_points::extreme_points_on_ring +{}; + + +template +struct extreme_points +{ + template + static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders) + { + typedef typename geometry::ring_type::type ring_type; + typedef detail::extreme_points::extreme_points_on_ring + < + ring_type, Dimension + > ring_implementation; + + if (! ring_implementation::apply(geometry::exterior_ring(polygon), extremes, intruders)) + { + return false; + } + + // For a polygon, its interior rings can contain intruders + typename interior_return_type::type + rings = interior_rings(polygon); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + ring_implementation::get_intruders(*it, extremes, intruders); + } + + return true; + } +}; + +template +struct extreme_points +{ + template + static inline bool apply(Box const& box, Extremes& extremes, Intruders& ) + { + extremes.resize(4); + geometry::detail::assign_box_corners_oriented(box, extremes); + // ll,ul,ur,lr, contains too exactly the right info + return true; + } +}; + +template +struct extreme_points +{ + template + static inline bool apply(Box const& box, Extremes& extremes, Intruders& ) + { + extremes.resize(4); + geometry::detail::assign_box_corners_oriented(box, extremes); + // ll,ul,ur,lr, rotate one to start with UL and end with LL + std::rotate(extremes.begin(), extremes.begin() + 1, extremes.end()); + return true; + } +}; + +template +struct extreme_points +{ + template + static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders) + { + // Get one for the very first polygon, that is (for the moment) enough. + // It is not guaranteed the "extreme" then, but for the current purpose + // (point_on_surface) it can just be this point. + if (boost::size(multi) >= 1) + { + return extreme_points + < + typename boost::range_value::type, + Dimension, + polygon_tag + >::apply(*boost::begin(multi), extremes, intruders); + } + + return false; + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! +\brief Returns extreme points (for Edge=1 in dimension 1, so the top, + for Edge=0 in dimension 0, the right side) +\note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that. + */ +template +inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders) +{ + concepts::check(); + + // Extremes is not required to follow a geometry concept (but it should support an output iterator), + // but its elements should fulfil the point-concept + concepts::check::type>(); + + // Intruders should contain collections which value type is point-concept + // Extremes might be anything (supporting an output iterator), but its elements should fulfil the point-concept + concepts::check + < + typename boost::range_value + < + typename boost::range_value::type + >::type + const + >(); + + return dispatch::extreme_points::apply(geometry, extremes, intruders); +} + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/flattening.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/flattening.hpp new file mode 100755 index 0000000000..56995f004a --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/flattening.hpp @@ -0,0 +1,69 @@ +// Boost.Geometry + +// Copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP + +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch +{ + +template ::type> +struct flattening + : not_implemented +{}; + +template +struct flattening +{ + static inline ResultType apply(Geometry const& /*geometry*/) + { + return ResultType(0); + } +}; + +template +struct flattening +{ + static inline ResultType apply(Geometry const& geometry) + { + return ResultType(get_radius<0>(geometry) - get_radius<2>(geometry)) + / ResultType(get_radius<0>(geometry)); + } +}; + +} // namespace detail_dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +ResultType flattening(Geometry const& geometry) +{ + return detail_dispatch::flattening::apply(geometry); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FLATTENING_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/for_each_range.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/for_each_range.hpp new file mode 100755 index 0000000000..da3516a988 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/for_each_range.hpp @@ -0,0 +1,201 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace for_each +{ + + +template +struct fe_range_range +{ + static inline void apply(Range & range, Actor & actor) + { + actor.apply(range); + } +}; + + +template +struct fe_range_polygon +{ + static inline void apply(Polygon & polygon, Actor & actor) + { + actor.apply(exterior_ring(polygon)); + + // TODO: If some flag says true, also do the inner rings. + // for convex hull, it's not necessary + } +}; + +template +struct fe_range_box +{ + static inline void apply(Box & box, Actor & actor) + { + actor.apply(box_view::type>(box)); + } +}; + +template +struct fe_range_multi +{ + static inline void apply(Multi & multi, Actor & actor) + { + for ( typename boost::range_iterator::type + it = boost::begin(multi); it != boost::end(multi); ++it) + { + SinglePolicy::apply(*it, actor); + } + } +}; + +}} // namespace detail::for_each +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Geometry, + typename Actor, + typename Tag = typename tag::type +> +struct for_each_range +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types) + ); +}; + + +template +struct for_each_range + : detail::for_each::fe_range_range +{}; + + +template +struct for_each_range + : detail::for_each::fe_range_range +{}; + + +template +struct for_each_range + : detail::for_each::fe_range_polygon +{}; + + +template +struct for_each_range + : detail::for_each::fe_range_box +{}; + + +template +struct for_each_range + : detail::for_each::fe_range_range +{}; + + +template +struct for_each_range + : detail::for_each::fe_range_multi + < + Geometry, + Actor, + detail::for_each::fe_range_range + < + typename add_const_if_c + < + boost::is_const::value, + typename boost::range_value::type + >::type, + Actor + > + > +{}; + + +template +struct for_each_range + : detail::for_each::fe_range_multi + < + Geometry, + Actor, + detail::for_each::fe_range_polygon + < + typename add_const_if_c + < + boost::is_const::value, + typename boost::range_value::type + >::type, + Actor + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +namespace detail +{ + +template +inline void for_each_range(Geometry const& geometry, Actor & actor) +{ + dispatch::for_each_range + < + Geometry const, + Actor + >::apply(geometry, actor); +} + + +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/get_left_turns.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/get_left_turns.hpp new file mode 100755 index 0000000000..efbdf57a66 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/get_left_turns.hpp @@ -0,0 +1,318 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +// TODO: move this to /util/ +template +inline std::pair ordered_pair(T const& first, T const& second) +{ + return first < second ? std::make_pair(first, second) : std::make_pair(second, first); +} + +namespace left_turns +{ + + + +template +inline int get_quadrant(Vector const& vector) +{ + // Return quadrant as layouted in the code below: + // 3 | 0 + // ----- + // 2 | 1 + return geometry::get<1>(vector) >= 0 + ? (geometry::get<0>(vector) < 0 ? 3 : 0) + : (geometry::get<0>(vector) < 0 ? 2 : 1) + ; +} + +template +inline int squared_length(Vector const& vector) +{ + return geometry::get<0>(vector) * geometry::get<0>(vector) + + geometry::get<1>(vector) * geometry::get<1>(vector) + ; +} + + +template +struct angle_less +{ + typedef Point vector_type; + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy_type; + + angle_less(Point const& origin) + : m_origin(origin) + {} + + template + inline bool operator()(Angle const& p, Angle const& q) const + { + // Vector origin -> p and origin -> q + vector_type pv = p.point; + vector_type qv = q.point; + geometry::subtract_point(pv, m_origin); + geometry::subtract_point(qv, m_origin); + + int const quadrant_p = get_quadrant(pv); + int const quadrant_q = get_quadrant(qv); + if (quadrant_p != quadrant_q) + { + return quadrant_p < quadrant_q; + } + // Same quadrant, check if p is located left of q + int const side = side_strategy_type::apply(m_origin, q.point, + p.point); + if (side != 0) + { + return side == 1; + } + // Collinear, check if one is incoming, incoming angles come first + if (p.incoming != q.incoming) + { + return int(p.incoming) < int(q.incoming); + } + // Same quadrant/side/direction, return longest first + // TODO: maybe not necessary, decide this + int const length_p = squared_length(pv); + int const length_q = squared_length(qv); + if (length_p != length_q) + { + return squared_length(pv) > squared_length(qv); + } + // They are still the same. Just compare on seg_id + return p.seg_id < q.seg_id; + } + +private: + Point m_origin; +}; + +template +struct angle_equal_to +{ + typedef Point vector_type; + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy_type; + + inline angle_equal_to(Point const& origin) + : m_origin(origin) + {} + + template + inline bool operator()(Angle const& p, Angle const& q) const + { + // Vector origin -> p and origin -> q + vector_type pv = p.point; + vector_type qv = q.point; + geometry::subtract_point(pv, m_origin); + geometry::subtract_point(qv, m_origin); + + if (get_quadrant(pv) != get_quadrant(qv)) + { + return false; + } + // Same quadrant, check if p/q are collinear + int const side = side_strategy_type::apply(m_origin, q.point, + p.point); + return side == 0; + } + +private: + Point m_origin; +}; + +template +inline void get_left_turns(AngleCollection const& sorted_angles, + Turns& turns) +{ + std::set good_incoming; + std::set good_outgoing; + + for (typename boost::range_iterator::type it = + sorted_angles.begin(); it != sorted_angles.end(); ++it) + { + if (!it->blocked) + { + if (it->incoming) + { + good_incoming.insert(it->turn_index); + } + else + { + good_outgoing.insert(it->turn_index); + } + } + } + + if (good_incoming.empty() || good_outgoing.empty()) + { + return; + } + + for (typename boost::range_iterator::type it = + sorted_angles.begin(); it != sorted_angles.end(); ++it) + { + if (good_incoming.count(it->turn_index) == 0 + || good_outgoing.count(it->turn_index) == 0) + { + turns[it->turn_index].remove_on_multi = true; + } + } +} + + +//! Returns the number of clusters +template +inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin) +{ + // Assign same cluster_index for all turns in same direction + BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u); + + angle_equal_to comparator(origin); + typename boost::range_iterator::type it = sorted.begin(); + + std::size_t cluster_index = 0; + it->cluster_index = cluster_index; + typename boost::range_iterator::type previous = it++; + for (; it != sorted.end(); ++it) + { + if (!comparator(*previous, *it)) + { + cluster_index++; + previous = it; + } + it->cluster_index = cluster_index; + } + return cluster_index + 1; +} + +template +inline void block_turns(AngleCollection& sorted, std::size_t cluster_size) +{ + BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0); + + std::vector > directions; + for (std::size_t i = 0; i < cluster_size; i++) + { + directions.push_back(std::make_pair(false, false)); + } + + for (typename boost::range_iterator::type it = sorted.begin(); + it != sorted.end(); ++it) + { + if (it->incoming) + { + directions[it->cluster_index].first = true; + } + else + { + directions[it->cluster_index].second = true; + } + } + + for (typename boost::range_iterator::type it = sorted.begin(); + it != sorted.end(); ++it) + { + signed_size_type cluster_index = static_cast(it->cluster_index); + signed_size_type previous_index = cluster_index - 1; + if (previous_index < 0) + { + previous_index = cluster_size - 1; + } + signed_size_type next_index = cluster_index + 1; + if (next_index >= static_cast(cluster_size)) + { + next_index = 0; + } + + if (directions[cluster_index].first + && directions[cluster_index].second) + { + it->blocked = true; + } + else if (!directions[cluster_index].first + && directions[cluster_index].second + && directions[previous_index].second) + { + // Only outgoing, previous was also outgoing: block this one + it->blocked = true; + } + else if (directions[cluster_index].first + && !directions[cluster_index].second + && !directions[previous_index].first + && directions[previous_index].second) + { + // Only incoming, previous was only outgoing: block this one + it->blocked = true; + } + else if (directions[cluster_index].first + && !directions[cluster_index].second + && directions[next_index].first + && !directions[next_index].second) + { + // Only incoming, next also incoming, block this one + it->blocked = true; + } + } +} + +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) +template +inline bool has_rounding_issues(AngleCollection const& angles, Point const& origin) +{ + for (typename boost::range_iterator::type it = + angles.begin(); it != angles.end(); ++it) + { + // Vector origin -> p and origin -> q + typedef Point vector_type; + vector_type v = it->point; + geometry::subtract_point(v, origin); + return geometry::math::abs(geometry::get<0>(v)) <= 1 + || geometry::math::abs(geometry::get<1>(v)) <= 1 + ; + } + return false; +} +#endif + + +} // namespace left_turns + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/get_max_size.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/get_max_size.hpp new file mode 100755 index 0000000000..37921457c9 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/get_max_size.hpp @@ -0,0 +1,64 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Bruno Lalande, Paris, France. +// Copyright (c) 2014 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP + + +#include + +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct get_max_size_box +{ + static inline typename coordinate_type::type apply(Box const& box) + { + typename coordinate_type::type s + = geometry::math::abs(geometry::get<1, Dimension>(box) - geometry::get<0, Dimension>(box)); + + return (std::max)(s, get_max_size_box::apply(box)); + } +}; + +template +struct get_max_size_box +{ + static inline typename coordinate_type::type apply(Box const& box) + { + return geometry::math::abs(geometry::get<1, 0>(box) - geometry::get<0, 0>(box)); + } +}; + +// This might be implemented later on for other geometries too. +// Not dispatched yet. +template +inline typename coordinate_type::type get_max_size(Box const& box) +{ + return get_max_size_box::value - 1>::apply(box); +} + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/has_self_intersections.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/has_self_intersections.hpp new file mode 100755 index 0000000000..289b607740 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/has_self_intersections.hpp @@ -0,0 +1,151 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS +# include +# include +#endif + + +namespace boost { namespace geometry +{ + + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + +/*! +\brief Overlay Invalid Input Exception +\ingroup overlay +\details The overlay_invalid_input_exception is thrown at invalid input + */ +class overlay_invalid_input_exception : public geometry::exception +{ +public: + + inline overlay_invalid_input_exception() {} + + virtual char const* what() const throw() + { + return "Boost.Geometry Overlay invalid input exception"; + } +}; + +#endif + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +inline bool has_self_intersections(Geometry const& geometry, + RobustPolicy const& robust_policy, + bool throw_on_self_intersection = true) +{ + typedef typename point_type::type point_type; + typedef turn_info + < + point_type, + typename segment_ratio_type::type + > turn_info; + std::deque turns; + detail::disjoint::disjoint_interrupt_policy policy; + + geometry::self_turns(geometry, robust_policy, turns, policy); + +#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS + bool first = true; +#endif + for(typename std::deque::const_iterator it = boost::begin(turns); + it != boost::end(turns); ++it) + { + turn_info const& info = *it; + bool const both_union_turn = + info.operations[0].operation == detail::overlay::operation_union + && info.operations[1].operation == detail::overlay::operation_union; + bool const both_intersection_turn = + info.operations[0].operation == detail::overlay::operation_intersection + && info.operations[1].operation == detail::overlay::operation_intersection; + + bool const valid = (both_union_turn || both_intersection_turn) + && (info.method == detail::overlay::method_touch + || info.method == detail::overlay::method_touch_interior); + + if (! valid) + { +#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS + if (first) + { + std::cout << "turn points: " << std::endl; + first = false; + } + std::cout << method_char(info.method); + for (int i = 0; i < 2; i++) + { + std::cout << " " << operation_char(info.operations[i].operation); + std::cout << " " << info.operations[i].seg_id; + } + std::cout << " " << geometry::dsv(info.point) << std::endl; +#endif + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + if (throw_on_self_intersection) + { + throw overlay_invalid_input_exception(); + } +#endif + return true; + } + + } + return false; +} + +// For backward compatibility +template +inline bool has_self_intersections(Geometry const& geometry, + bool throw_on_self_intersection = true) +{ + typedef typename geometry::point_type::type point_type; + typedef typename geometry::rescale_policy_type::type + rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry); + + return has_self_intersections(geometry, robust_policy, + throw_on_self_intersection); +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP + diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/interior_iterator.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/interior_iterator.hpp new file mode 100755 index 0000000000..b31b44720b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/interior_iterator.hpp @@ -0,0 +1,71 @@ +// Boost.Geometry + +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP + +#include +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +/*! +\brief Structure defining the type of interior rings iterator +\note If the Geometry is const, const iterator is defined. +\tparam Geometry \tparam_geometry + */ +template +struct interior_iterator +{ + typedef typename boost::range_iterator + < + typename geometry::interior_type::type + >::type type; +}; + +template +struct copy_const +{ + typedef T type; +}; + +template +struct copy_const +{ + typedef T const type; +}; + +template +struct interior_ring_iterator +{ + typedef typename boost::range_iterator + < + typename copy_const + < + typename geometry::interior_type::type, + typename boost::range_value + < + typename geometry::interior_type::type + >::type + >::type + >::type type; +}; + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/box_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/box_box.hpp new file mode 100755 index 0000000000..30c5767dcb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/box_box.hpp @@ -0,0 +1,54 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Box1, typename Box2, bool Reverse +> +struct intersection + < + Box1, Box2, + box_tag, box_tag, + Reverse + > : public detail::intersection::intersection_box_box + < + 0, geometry::dimension::value + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/implementation.hpp new file mode 100755 index 0000000000..b70e3ce411 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/implementation.hpp @@ -0,0 +1,22 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP + + +#include +#include + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/interface.hpp new file mode 100755 index 0000000000..b75bc827e6 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -0,0 +1,307 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP + + +// TODO: those headers probably may be removed +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// By default, all is forwarded to the intersection_insert-dispatcher +template +< + typename Geometry1, typename Geometry2, + typename Tag1 = typename geometry::tag::type, + typename Tag2 = typename geometry::tag::type, + bool Reverse = reverse_dispatch::type::value +> +struct intersection +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + GeometryOut& geometry_out, + Strategy const& strategy) + { + typedef typename boost::range_value::type OneOut; + + intersection_insert + < + Geometry1, Geometry2, OneOut, + overlay_intersection + >::apply(geometry1, geometry2, robust_policy, range::back_inserter(geometry_out), strategy); + + return true; + } + +}; + + +// If reversal is needed, perform it +template +< + typename Geometry1, typename Geometry2, + typename Tag1, typename Tag2 +> +struct intersection +< + Geometry1, Geometry2, + Tag1, Tag2, + true +> + : intersection +{ + template + static inline bool apply( + Geometry1 const& g1, + Geometry2 const& g2, + RobustPolicy const& robust_policy, + GeometryOut& out, + Strategy const& strategy) + { + return intersection< + Geometry2, Geometry1, + Tag2, Tag1, + false + >::apply(g2, g1, robust_policy, out, strategy); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +namespace resolve_variant +{ + +template +struct intersection +{ + template + static inline bool + apply( + const Geometry1& geometry1, + const Geometry2& geometry2, + GeometryOut& geometry_out) + { + concepts::check(); + concepts::check(); + + typedef typename geometry::rescale_overlay_policy_type + < + Geometry1, + Geometry2 + >::type rescale_policy_type; + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, + geometry2); + + typedef intersection_strategies + < + typename cs_tag::type, + Geometry1, + Geometry2, + typename geometry::point_type::type, + rescale_policy_type + > strategy; + + return dispatch::intersection + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, robust_policy, geometry_out, strategy()); + } +}; + + +template +struct intersection, Geometry2> +{ + template + struct visitor: static_visitor + { + Geometry2 const& m_geometry2; + GeometryOut& m_geometry_out; + + visitor(Geometry2 const& geometry2, + GeometryOut& geometry_out) + : m_geometry2(geometry2) + , m_geometry_out(geometry_out) + {} + + template + result_type operator()(Geometry1 const& geometry1) const + { + return intersection + < + Geometry1, + Geometry2 + >::template apply + < + GeometryOut + > + (geometry1, m_geometry2, m_geometry_out); + } + }; + + template + static inline bool + apply(variant const& geometry1, + Geometry2 const& geometry2, + GeometryOut& geometry_out) + { + return boost::apply_visitor(visitor(geometry2, geometry_out), geometry1); + } +}; + + +template +struct intersection > +{ + template + struct visitor: static_visitor + { + Geometry1 const& m_geometry1; + GeometryOut& m_geometry_out; + + visitor(Geometry1 const& geometry1, + GeometryOut& geometry_out) + : m_geometry1(geometry1) + , m_geometry_out(geometry_out) + {} + + template + result_type operator()(Geometry2 const& geometry2) const + { + return intersection + < + Geometry1, + Geometry2 + >::template apply + < + GeometryOut + > + (m_geometry1, geometry2, m_geometry_out); + } + }; + + template + static inline bool + apply(Geometry1 const& geometry1, + const variant& geometry2, + GeometryOut& geometry_out) + { + return boost::apply_visitor(visitor(geometry1, geometry_out), geometry2); + } +}; + + +template +struct intersection, variant > +{ + template + struct visitor: static_visitor + { + GeometryOut& m_geometry_out; + + visitor(GeometryOut& geometry_out) + : m_geometry_out(geometry_out) + {} + + template + result_type operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return intersection + < + Geometry1, + Geometry2 + >::template apply + < + GeometryOut + > + (geometry1, geometry2, m_geometry_out); + } + }; + + template + static inline bool + apply(const variant& geometry1, + const variant& geometry2, + GeometryOut& geometry_out) + { + return boost::apply_visitor(visitor(geometry_out), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + + +/*! +\brief \brief_calc2{intersection} +\ingroup intersection +\details \details_calc2{intersection, spatial set theoretic intersection}. +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which + the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box) +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param geometry_out The output geometry, either a multi_point, multi_polygon, + multi_linestring, or a box (for intersection of two boxes) + +\qbk{[include reference/algorithms/intersection.qbk]} +*/ +template +< + typename Geometry1, + typename Geometry2, + typename GeometryOut +> +inline bool intersection(Geometry1 const& geometry1, + Geometry2 const& geometry2, + GeometryOut& geometry_out) +{ + return resolve_variant::intersection + < + Geometry1, + Geometry2 + >::template apply + < + GeometryOut + > + (geometry1, geometry2, geometry_out); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/multi.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/multi.hpp new file mode 100755 index 0000000000..180aa01625 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/intersection/multi.hpp @@ -0,0 +1,421 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP + +#include +#include +#include +#include +#include +#include + +// TODO: those headers probably may be removed +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace intersection +{ + + +template +struct intersection_multi_linestring_multi_linestring_point +{ + template + < + typename MultiLinestring1, typename MultiLinestring2, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(MultiLinestring1 const& ml1, + MultiLinestring2 const& ml2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + // Note, this loop is quadratic w.r.t. number of linestrings per input. + // Future Enhancement: first do the sections of each, then intersect. + for (typename boost::range_iterator + < + MultiLinestring1 const + >::type it1 = boost::begin(ml1); + it1 != boost::end(ml1); + ++it1) + { + for (typename boost::range_iterator + < + MultiLinestring2 const + >::type it2 = boost::begin(ml2); + it2 != boost::end(ml2); + ++it2) + { + out = intersection_linestring_linestring_point + ::apply(*it1, *it2, robust_policy, out, strategy); + } + } + + return out; + } +}; + + +template +struct intersection_linestring_multi_linestring_point +{ + template + < + typename Linestring, typename MultiLinestring, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Linestring const& linestring, + MultiLinestring const& ml, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + for (typename boost::range_iterator + < + MultiLinestring const + >::type it = boost::begin(ml); + it != boost::end(ml); + ++it) + { + out = intersection_linestring_linestring_point + ::apply(linestring, *it, robust_policy, out, strategy); + } + + return out; + } +}; + + +// This loop is quite similar to the loop above, but beacuse the iterator +// is second (above) or first (below) argument, it is not trivial to merge them. +template +< + bool ReverseAreal, + typename LineStringOut, + overlay_type OverlayType +> +struct intersection_of_multi_linestring_with_areal +{ + template + < + typename MultiLinestring, typename Areal, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + for (typename boost::range_iterator + < + MultiLinestring const + >::type it = boost::begin(ml); + it != boost::end(ml); + ++it) + { + out = intersection_of_linestring_with_areal + < + ReverseAreal, LineStringOut, OverlayType + >::apply(*it, areal, robust_policy, out, strategy); + } + + return out; + + } +}; + +// This one calls the one above with reversed arguments +template +< + bool ReverseAreal, + typename LineStringOut, + overlay_type OverlayType +> +struct intersection_of_areal_with_multi_linestring +{ + template + < + typename Areal, typename MultiLinestring, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + return intersection_of_multi_linestring_with_areal + < + ReverseAreal, LineStringOut, OverlayType + >::apply(ml, areal, robust_policy, out, strategy); + } +}; + + + +template +struct clip_multi_linestring +{ + template + < + typename MultiLinestring, typename Box, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(MultiLinestring const& multi_linestring, + Box const& box, + RobustPolicy const& robust_policy, + OutputIterator out, Strategy const& ) + { + typedef typename point_type::type point_type; + strategy::intersection::liang_barsky lb_strategy; + for (typename boost::range_iterator::type it + = boost::begin(multi_linestring); + it != boost::end(multi_linestring); ++it) + { + out = detail::intersection::clip_range_with_box + (box, *it, robust_policy, out, lb_strategy); + } + return out; + } +}; + + +}} // namespace detail::intersection +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Linear +template +< + typename MultiLinestring1, typename MultiLinestring2, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + MultiLinestring1, MultiLinestring2, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + multi_linestring_tag, multi_linestring_tag, point_tag, + false, false, false + > : detail::intersection::intersection_multi_linestring_multi_linestring_point + < + GeometryOut + > +{}; + + +template +< + typename Linestring, typename MultiLinestring, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Linestring, MultiLinestring, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + linestring_tag, multi_linestring_tag, point_tag, + false, false, false + > : detail::intersection::intersection_linestring_multi_linestring_point + < + GeometryOut + > +{}; + + +template +< + typename MultiLinestring, typename Box, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + MultiLinestring, Box, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + multi_linestring_tag, box_tag, linestring_tag, + false, true, false + > : detail::intersection::clip_multi_linestring + < + GeometryOut + > +{}; + + +template +< + typename Linestring, typename MultiPolygon, + typename GeometryOut, + overlay_type OverlayType, + bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut +> +struct intersection_insert + < + Linestring, MultiPolygon, + GeometryOut, + OverlayType, + ReverseLinestring, ReverseMultiPolygon, ReverseOut, + linestring_tag, multi_polygon_tag, linestring_tag, + false, true, false + > : detail::intersection::intersection_of_linestring_with_areal + < + ReverseMultiPolygon, + GeometryOut, + OverlayType + > +{}; + + +// Derives from areal/mls because runtime arguments are in that order. +// areal/mls reverses it itself to mls/areal +template +< + typename Polygon, typename MultiLinestring, + typename GeometryOut, + overlay_type OverlayType, + bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut +> +struct intersection_insert + < + Polygon, MultiLinestring, + GeometryOut, + OverlayType, + ReversePolygon, ReverseMultiLinestring, ReverseOut, + polygon_tag, multi_linestring_tag, linestring_tag, + true, false, false + > : detail::intersection::intersection_of_areal_with_multi_linestring + < + ReversePolygon, + GeometryOut, + OverlayType + > +{}; + + +template +< + typename MultiLinestring, typename Ring, + typename GeometryOut, + overlay_type OverlayType, + bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut +> +struct intersection_insert + < + MultiLinestring, Ring, + GeometryOut, + OverlayType, + ReverseMultiLinestring, ReverseRing, ReverseOut, + multi_linestring_tag, ring_tag, linestring_tag, + false, true, false + > : detail::intersection::intersection_of_multi_linestring_with_areal + < + ReverseRing, + GeometryOut, + OverlayType + > +{}; + +template +< + typename MultiLinestring, typename Polygon, + typename GeometryOut, + overlay_type OverlayType, + bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut +> +struct intersection_insert + < + MultiLinestring, Polygon, + GeometryOut, + OverlayType, + ReverseMultiLinestring, ReverseRing, ReverseOut, + multi_linestring_tag, polygon_tag, linestring_tag, + false, true, false + > : detail::intersection::intersection_of_multi_linestring_with_areal + < + ReverseRing, + GeometryOut, + OverlayType + > +{}; + + + +template +< + typename MultiLinestring, typename MultiPolygon, + typename GeometryOut, + overlay_type OverlayType, + bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut +> +struct intersection_insert + < + MultiLinestring, MultiPolygon, + GeometryOut, + OverlayType, + ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut, + multi_linestring_tag, multi_polygon_tag, linestring_tag, + false, true, false + > : detail::intersection::intersection_of_multi_linestring_with_areal + < + ReverseMultiPolygon, + GeometryOut, + OverlayType + > +{}; + + +} // namespace dispatch +#endif + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP + diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/always_simple.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/always_simple.hpp new file mode 100755 index 0000000000..95b5b78926 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/always_simple.hpp @@ -0,0 +1,83 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP + +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +template +struct always_simple +{ + static inline bool apply(Geometry const&) + { + return true; + } +}; + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A point is always simple +template +struct is_simple + : detail::is_simple::always_simple +{}; + + +// A valid segment is always simple. +// A segment is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// Reference: OGC 06-103r4 (6.1.6.1) +template +struct is_simple + : detail::is_simple::always_simple +{}; + + +// A valid box is always simple +// A box is a Polygon, and it satisfies the conditions for Polygon validity. +// +// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1) +template +struct is_simple + : detail::is_simple::always_simple +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/areal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/areal.hpp new file mode 100755 index 0000000000..17b403dd0b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/areal.hpp @@ -0,0 +1,143 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +template +struct is_simple_ring +{ + static inline bool apply(Ring const& ring) + { + simplicity_failure_policy policy; + return ! boost::empty(ring) + && ! detail::is_valid::has_duplicates + < + Ring, geometry::closure::value + >::apply(ring, policy); + } +}; + + +template +class is_simple_polygon +{ +private: + template + static inline + bool are_simple_interior_rings(InteriorRings const& interior_rings) + { + return + detail::check_iterator_range + < + is_simple_ring + < + typename boost::range_value::type + > + >::apply(boost::begin(interior_rings), + boost::end(interior_rings)); + } + +public: + static inline bool apply(Polygon const& polygon) + { + return + is_simple_ring + < + typename ring_type::type + >::apply(exterior_ring(polygon)) + && + are_simple_interior_rings(geometry::interior_rings(polygon)); + } +}; + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A Ring is a Polygon. +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1) +template +struct is_simple + : detail::is_simple::is_simple_ring +{}; + + +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1) +template +struct is_simple + : detail::is_simple::is_simple_polygon +{}; + + +// Not clear what the definition is. +// Right now we consider a MultiPolygon as simple if it is valid. +// +// Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14) +template +struct is_simple +{ + static inline bool apply(MultiPolygon const& multipolygon) + { + return + detail::check_iterator_range + < + detail::is_simple::is_simple_polygon + < + typename boost::range_value::type + >, + true // allow empty multi-polygon + >::apply(boost::begin(multipolygon), boost::end(multipolygon)); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp new file mode 100755 index 0000000000..481a139303 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp @@ -0,0 +1,113 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#endif // BOOST_GEOMETRY_TEST_DEBUG + + +namespace boost { namespace geometry +{ + +namespace detail { namespace is_simple +{ + + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +template ::type> +struct debug_boundary_points_printer + : not_implemented +{}; + +template +struct debug_boundary_points_printer +{ + static inline void apply(Linestring const& linestring) + { + std::cout << "boundary points: "; + std::cout << " " << geometry::dsv(range::front(linestring)); + std::cout << " " << geometry::dsv(range::back(linestring)); + std::cout << std::endl << std::endl; + } +}; + +template +struct debug_boundary_points_printer +{ + static inline void apply(MultiLinestring const& multilinestring) + { + typedef typename point_type::type point_type; + typedef std::vector point_vector; + + point_vector boundary_points; + for (typename boost::range_iterator::type it + = boost::begin(multilinestring); + it != boost::end(multilinestring); ++it) + { + if ( boost::size(*it) > 1 + && !geometry::equals(range::front(*it), range::back(*it)) ) + { + boundary_points.push_back( range::front(*it) ); + boundary_points.push_back( range::back(*it) ); + } + } + + std::sort(boundary_points.begin(), boundary_points.end(), + geometry::less()); + + std::cout << "boundary points: "; + for (typename point_vector::const_iterator + pit = boundary_points.begin(); + pit != boundary_points.end(); ++pit) + { + std::cout << " " << geometry::dsv(*pit); + } + std::cout << std::endl << std::endl; + } +}; + + +template +inline void debug_print_boundary_points(Linear const& linear) +{ + debug_boundary_points_printer::apply(linear); +} +#else +template +inline void debug_print_boundary_points(Linear const&) +{ +} +#endif // BOOST_GEOMETRY_TEST_DEBUG + + +}} // namespace detail::is_simple + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_DEBUG_PRINT_BOUNDARY_POINTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/failure_policy.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/failure_policy.hpp new file mode 100755 index 0000000000..876f8bad48 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/failure_policy.hpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +struct simplicity_failure_policy +{ + template + static inline bool apply() + { + return Failure == no_failure; + } + + template + static inline bool apply(Data const&) + { + return apply(); + } + + template + static inline bool apply(Data1 const&, Data2 const&) + { + return apply(); + } +}; + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_FAILURE_POLICY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/implementation.hpp new file mode 100755 index 0000000000..401a02500b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/implementation.hpp @@ -0,0 +1,18 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_IMPLEMENTATION_HPP + +#include +#include +#include +#include + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/interface.hpp new file mode 100755 index 0000000000..3f3f8fe0b1 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/interface.hpp @@ -0,0 +1,80 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP + +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + + +namespace resolve_variant { + +template +struct is_simple +{ + static inline bool apply(Geometry const& geometry) + { + concepts::check(); + return dispatch::is_simple::apply(geometry); + } +}; + +template +struct is_simple > +{ + struct visitor : boost::static_visitor + { + template + bool operator()(Geometry const& geometry) const + { + return is_simple::apply(geometry); + } + }; + + static inline bool + apply(boost::variant const& geometry) + { + return boost::apply_visitor(visitor(), geometry); + } +}; + +} // namespace resolve_variant + + + +/*! +\brief \brief_check{is simple} +\ingroup is_simple +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\return \return_check{is simple} + +\qbk{[include reference/algorithms/is_simple.qbk]} +*/ +template +inline bool is_simple(Geometry const& geometry) +{ + return resolve_variant::is_simple::apply(geometry); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/linear.hpp new file mode 100755 index 0000000000..f27c0fe183 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -0,0 +1,320 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +template +inline bool check_segment_indices(Turn const& turn, + signed_size_type last_index) +{ + return + (turn.operations[0].seg_id.segment_index == 0 + && turn.operations[1].seg_id.segment_index == last_index) + || + (turn.operations[0].seg_id.segment_index == 0 + && turn.operations[1].seg_id.segment_index == last_index); +} + + +template ::type> +class is_acceptable_turn + : not_implemented +{}; + +template +class is_acceptable_turn +{ +public: + is_acceptable_turn(Linestring const& linestring) + : m_linestring(linestring) + , m_is_closed(geometry::equals(range::front(linestring), + range::back(linestring))) + {} + + template + inline bool apply(Turn const& turn) const + { + BOOST_GEOMETRY_ASSERT(boost::size(m_linestring) > 1); + return m_is_closed + && turn.method == overlay::method_none + && check_segment_indices(turn, boost::size(m_linestring) - 2) + && turn.operations[0].fraction.is_zero(); + } + +private: + Linestring const& m_linestring; + bool const m_is_closed; +}; + +template +class is_acceptable_turn +{ +private: + typedef typename boost::range_value::type linestring_type; + typedef is_acceptable_turn base_type; + + template + static inline bool is_boundary_point_of(Point const& point, + Linestring const& linestring) + { + BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); + return + ! geometry::equals(range::front(linestring), + range::back(linestring)) + && + (geometry::equals(point, range::front(linestring)) + || geometry::equals(point, range::back(linestring))); + } + + template + static inline bool is_closing_point_of(Turn const& turn, + Linestring const& linestring) + { + BOOST_GEOMETRY_ASSERT(boost::size(linestring) > 1); + return + turn.method == overlay::method_none + && + check_segment_indices(turn, boost::size(linestring) - 2) + && + geometry::equals(range::front(linestring), range::back(linestring)) + && + turn.operations[0].fraction.is_zero(); + ; + } + + template + static inline bool have_same_boundary_points(Linestring1 const& ls1, + Linestring2 const& ls2) + { + return + geometry::equals(range::front(ls1), range::front(ls2)) + ? + geometry::equals(range::back(ls1), range::back(ls2)) + : + (geometry::equals(range::front(ls1), range::back(ls2)) + && + geometry::equals(range::back(ls1), range::front(ls2))) + ; + } + +public: + is_acceptable_turn(MultiLinestring const& multilinestring) + : m_multilinestring(multilinestring) + {} + + template + inline bool apply(Turn const& turn) const + { + linestring_type const& ls1 = + range::at(m_multilinestring, turn.operations[0].seg_id.multi_index); + + linestring_type const& ls2 = + range::at(m_multilinestring, turn.operations[1].seg_id.multi_index); + + if (turn.operations[0].seg_id.multi_index + == turn.operations[1].seg_id.multi_index) + { + return is_closing_point_of(turn, ls1); + } + + return + is_boundary_point_of(turn.point, ls1) + && is_boundary_point_of(turn.point, ls2) + && + ( boost::size(ls1) != 2 + || boost::size(ls2) != 2 + || ! have_same_boundary_points(ls1, ls2) ); + } + +private: + MultiLinestring const& m_multilinestring; +}; + + +template +inline bool has_self_intersections(Linear const& linear) +{ + typedef typename point_type::type point_type; + + // compute self turns + typedef detail::overlay::turn_info + < + point_type, + geometry::segment_ratio + < + typename geometry::coordinate_type::type + > + > turn_info; + + std::deque turns; + + typedef detail::overlay::get_turn_info + < + detail::disjoint::assign_disjoint_policy + > turn_policy; + + is_acceptable_turn predicate(linear); + detail::overlay::predicate_based_interrupt_policy + < + is_acceptable_turn + > interrupt_policy(predicate); + + detail::self_get_turn_points::get_turns + < + turn_policy + >::apply(linear, + detail::no_rescale_policy(), + turns, + interrupt_policy); + + detail::is_valid::debug_print_turns(turns.begin(), turns.end()); + debug_print_boundary_points(linear); + + return interrupt_policy.has_intersections; +} + + +template +struct is_simple_linestring +{ + static inline bool apply(Linestring const& linestring) + { + simplicity_failure_policy policy; + return ! boost::empty(linestring) + && ! detail::is_valid::has_duplicates + < + Linestring, closed + >::apply(linestring, policy) + && ! detail::is_valid::has_spikes + < + Linestring, closed + >::apply(linestring, policy) + && ! (CheckSelfIntersections && has_self_intersections(linestring)); + } +}; + + +template +struct is_simple_multilinestring +{ + static inline bool apply(MultiLinestring const& multilinestring) + { + // check each of the linestrings for simplicity + // but do not compute self-intersections yet; these will be + // computed for the entire multilinestring + if ( ! detail::check_iterator_range + < + is_simple_linestring + < + typename boost::range_value::type, + false // do not compute self-intersections + >, + true // allow empty multilinestring + >::apply(boost::begin(multilinestring), + boost::end(multilinestring)) + ) + { + return false; + } + + return ! has_self_intersections(multilinestring); + } +}; + + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A linestring is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// Reference: OGC 06-103r4 (6.1.6.1) +template +struct is_simple + : detail::is_simple::is_simple_linestring +{}; + + +// A MultiLinestring is a MultiCurve +// A MultiCurve is simple if all of its elements are simple and the +// only intersections between any two elements occur at Points that +// are on the boundaries of both elements. +// +// Reference: OGC 06-103r4 (6.1.8.1; Fig. 9) +template +struct is_simple + : detail::is_simple::is_simple_multilinestring +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp new file mode 100755 index 0000000000..0e2ec0a8a0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_simple/multipoint.hpp @@ -0,0 +1,89 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_MULTIPOINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_MULTIPOINT_HPP + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +template +struct is_simple_multipoint +{ + static inline bool apply(MultiPoint const& multipoint) + { + if (boost::empty(multipoint)) + { + return true; + } + + MultiPoint mp(multipoint); + std::sort(boost::begin(mp), boost::end(mp), + geometry::less::type>()); + + simplicity_failure_policy policy; + return !detail::is_valid::has_duplicates + < + MultiPoint, closed + >::apply(mp, policy); + } +}; + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A MultiPoint is simple if no two Points in the MultiPoint are equal +// (have identical coordinate values in X and Y) +// +// Reference: OGC 06-103r4 (6.1.5) +template +struct is_simple + : detail::is_simple::is_simple_multipoint +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_MULTIPOINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/box.hpp new file mode 100755 index 0000000000..1f64889884 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/box.hpp @@ -0,0 +1,115 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP + +#include + +#include + +#include +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +template +struct has_valid_corners +{ + template + static inline bool apply(Box const& box, VisitPolicy& visitor) + { + if (math::equals(geometry::get(box), + geometry::get(box))) + { + return + visitor.template apply(); + } + else if (geometry::get(box) + > + geometry::get(box)) + { + return visitor.template apply(); + } + return has_valid_corners::apply(box, visitor); + } +}; + + +template +struct has_valid_corners +{ + template + static inline bool apply(Box const&, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + return visitor.template apply(); + } +}; + + +template +struct is_valid_box +{ + template + static inline bool apply(Box const& box, VisitPolicy& visitor) + { + return + ! has_invalid_coordinate::apply(box, visitor) + && + has_valid_corners::value>::apply(box, visitor); + } +}; + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A box is always simple +// A box is a Polygon, and it satisfies the conditions for Polygon validity. +// +// The only thing we have to check is whether the max corner lies in +// the upper-right quadrant as defined by the min corner +// +// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1) +template +struct is_valid + : detail::is_valid::is_valid_box +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp new file mode 100755 index 0000000000..3dca236ecf --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp @@ -0,0 +1,239 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP + +#include + +#include +#include +#include +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +namespace detail { namespace is_valid +{ + + +template +class complement_graph_vertex +{ +public: + complement_graph_vertex(std::size_t id) + : m_id(id) + , m_turn_point(NULL) + {} + + complement_graph_vertex(TurnPoint const* turn_point, + std::size_t expected_id) + : m_id(expected_id) + , m_turn_point(turn_point) + {} + + inline std::size_t id() const { return m_id; } + + inline bool operator<(complement_graph_vertex const& other) const + { + if ( m_turn_point != NULL && other.m_turn_point != NULL ) + { + return geometry::less + < + TurnPoint + >()(*m_turn_point, *other.m_turn_point); + } + if ( m_turn_point == NULL && other.m_turn_point == NULL ) + { + return m_id < other.m_id; + } + return m_turn_point == NULL; + } + +private: + // the value of m_turn_point determines the type of the vertex + // non-NULL: vertex corresponds to an IP + // NULL : vertex corresponds to a hole or outer space, and the id + // is the ring id of the corresponding ring of the polygon + std::size_t m_id; + TurnPoint const* m_turn_point; +}; + + + + +template +class complement_graph +{ +private: + typedef complement_graph_vertex vertex; + typedef std::set vertex_container; + +public: + typedef typename vertex_container::const_iterator vertex_handle; + +private: + struct vertex_handle_less + { + inline bool operator()(vertex_handle v1, vertex_handle v2) const + { + return v1->id() < v2->id(); + } + }; + + typedef std::set neighbor_container; + + class has_cycles_dfs_data + { + public: + has_cycles_dfs_data(std::size_t num_nodes) + : m_visited(num_nodes, false) + , m_parent_id(num_nodes, -1) + {} + + inline signed_size_type parent_id(vertex_handle v) const + { + return m_parent_id[v->id()]; + } + + inline void set_parent_id(vertex_handle v, signed_size_type id) + { + m_parent_id[v->id()] = id; + } + + inline bool visited(vertex_handle v) const + { + return m_visited[v->id()]; + } + + inline void set_visited(vertex_handle v, bool value) + { + m_visited[v->id()] = value; + } + private: + std::vector m_visited; + std::vector m_parent_id; + }; + + + inline bool has_cycles(vertex_handle start_vertex, + has_cycles_dfs_data& data) const + { + std::stack stack; + stack.push(start_vertex); + + while ( !stack.empty() ) + { + vertex_handle v = stack.top(); + stack.pop(); + + data.set_visited(v, true); + for (typename neighbor_container::const_iterator nit + = m_neighbors[v->id()].begin(); + nit != m_neighbors[v->id()].end(); ++nit) + { + if ( static_cast((*nit)->id()) != data.parent_id(v) ) + { + if ( data.visited(*nit) ) + { + return true; + } + else + { + data.set_parent_id(*nit, static_cast(v->id())); + stack.push(*nit); + } + } + } + } + return false; + } + +public: + // num_rings: total number of rings, including the exterior ring + complement_graph(std::size_t num_rings) + : m_num_rings(num_rings) + , m_num_turns(0) + , m_vertices() + , m_neighbors(num_rings) + {} + + // inserts a ring vertex in the graph and returns its handle + // ring id's are zero-based (so the first interior ring has id 1) + inline vertex_handle add_vertex(signed_size_type id) + { + return m_vertices.insert(vertex(static_cast(id))).first; + } + + // inserts an IP in the graph and returns its id + inline vertex_handle add_vertex(TurnPoint const& turn_point) + { + std::pair res + = m_vertices.insert(vertex(boost::addressof(turn_point), + m_num_rings + m_num_turns) + ); + + if ( res.second ) + { + // a new element is inserted + m_neighbors.push_back(neighbor_container()); + ++m_num_turns; + } + return res.first; + } + + inline void add_edge(vertex_handle v1, vertex_handle v2) + { + BOOST_GEOMETRY_ASSERT( v1 != m_vertices.end() ); + BOOST_GEOMETRY_ASSERT( v2 != m_vertices.end() ); + m_neighbors[v1->id()].insert(v2); + m_neighbors[v2->id()].insert(v1); + } + + inline bool has_cycles() const + { + // initialize all vertices as non-visited and with no parent set + // this is done by the constructor of has_cycles_dfs_data + has_cycles_dfs_data data(m_num_rings + m_num_turns); + + // for each non-visited vertex, start a DFS from that vertex + for (vertex_handle it = m_vertices.begin(); + it != m_vertices.end(); ++it) + { + if ( !data.visited(it) && has_cycles(it, data) ) + { + return true; + } + } + return false; + } + + template + friend inline + void debug_print_complement_graph(OStream&, complement_graph const&); + +private: + std::size_t m_num_rings, m_num_turns; + vertex_container m_vertices; + std::vector m_neighbors; +}; + + +}} // namespace detail::is_valid + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp new file mode 100755 index 0000000000..467462f50c --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp @@ -0,0 +1,70 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_COMPLEMENT_GRAPH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_COMPLEMENT_GRAPH_HPP + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#include +#endif + +namespace boost { namespace geometry +{ + +namespace detail { namespace is_valid +{ + + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +template +inline void +debug_print_complement_graph(OutputStream& os, + complement_graph const& graph) +{ + typedef typename complement_graph::vertex_handle vertex_handle; + + os << "num rings: " << graph.m_num_rings << std::endl; + os << "vertex ids: {"; + for (vertex_handle it = graph.m_vertices.begin(); + it != graph.m_vertices.end(); ++it) + { + os << " " << it->id(); + } + os << " }" << std::endl; + + for (vertex_handle it = graph.m_vertices.begin(); + it != graph.m_vertices.end(); ++it) + { + os << "neighbors of " << it->id() << ": {"; + for (typename complement_graph + < + TurnPoint + >::neighbor_container::const_iterator + nit = graph.m_neighbors[it->id()].begin(); + nit != graph.m_neighbors[it->id()].end(); ++nit) + { + os << " " << (*nit)->id(); + } + os << "}" << std::endl; + } +} +#else +template +inline void debug_print_complement_graph(OutputStream&, + complement_graph const&) +{ +} +#endif + + +}} // namespace detail::is_valid + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_COMPLEMENT_GRAPH_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp new file mode 100755 index 0000000000..cc486fe1eb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_print_turns.hpp @@ -0,0 +1,78 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#include + +#include +#include +#endif + + +namespace boost { namespace geometry +{ + +namespace detail { namespace is_valid +{ + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +template +inline void debug_print_turn(Turn const& turn) +{ + std::cout << " [" + << geometry::method_char(turn.method) + << "," + << geometry::operation_char(turn.operations[0].operation) + << "/" + << geometry::operation_char(turn.operations[1].operation) + << " {" + << turn.operations[0].seg_id.multi_index + << ", " + << turn.operations[1].seg_id.multi_index + << "} {" + << turn.operations[0].seg_id.ring_index + << ", " + << turn.operations[1].seg_id.ring_index + << "} {" + << turn.operations[0].seg_id.segment_index + << ", " + << turn.operations[1].seg_id.segment_index + << "} " + << geometry::dsv(turn.point) + << "]"; +} + +template +inline void debug_print_turns(TurnIterator first, TurnIterator beyond) +{ + std::cout << "turns:"; + for (TurnIterator tit = first; tit != beyond; ++tit) + { + debug_print_turn(*tit); + } + std::cout << std::endl << std::endl; +} +#else +template +inline void debug_print_turn(Turn const&) +{} + +template +inline void debug_print_turns(TurnIterator, TurnIterator) +{} +#endif // BOOST_GEOMETRY_TEST_DEBUG + +}} // namespace detail::is_valid + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_PRINT_TURNS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp new file mode 100755 index 0000000000..47ca6388ee --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/debug_validity_phase.hpp @@ -0,0 +1,68 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP + +#ifdef GEOMETRY_TEST_DEBUG +#include + +#include +#include +#endif + + +namespace boost { namespace geometry +{ + +namespace detail { namespace is_valid +{ + +template ::type> +struct debug_validity_phase +{ + static inline void apply(int) + { + } +}; + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +template +struct debug_validity_phase +{ + static inline void apply(int phase) + { + switch (phase) + { + case 1: + std::cout << "checking exterior ring..." << std::endl; + break; + case 2: + std::cout << "checking interior rings..." << std::endl; + break; + case 3: + std::cout << "computing and analyzing turns..." << std::endl; + break; + case 4: + std::cout << "checking if interior rings are inside " + << "the exterior ring..." << std::endl; + break; + case 5: + std::cout << "checking connectivity of interior..." << std::endl; + break; + } + } +}; +#endif + +}} // namespace detail::is_valid + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_DEBUG_VALIDITY_PHASE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp new file mode 100755 index 0000000000..96719077e4 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp @@ -0,0 +1,80 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP + +#include +#include + +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +template +struct has_duplicates +{ + template + static inline bool apply(Range const& range, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + typedef typename closeable_view::type view_type; + typedef typename boost::range_const_iterator + < + view_type const + >::type const_iterator; + + view_type view(range); + + if ( boost::size(view) < 2 ) + { + return ! visitor.template apply(); + } + + geometry::equal_to::type> equal; + + const_iterator it = boost::const_begin(view); + const_iterator next = it; + ++next; + for (; next != boost::const_end(view); ++it, ++next) + { + if ( equal(*it, *next) ) + { + return ! visitor.template apply(*it); + } + } + return ! visitor.template apply(); + } +}; + + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_DUPLICATES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp new file mode 100755 index 0000000000..02ac132b83 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp @@ -0,0 +1,151 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_INVALID_COORDINATE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_INVALID_COORDINATE_HPP + +#include + +#include + +#include +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +struct always_valid +{ + template + static inline bool apply(Geometry const&, VisitPolicy& visitor) + { + return ! visitor.template apply(); + } +}; + +struct point_has_invalid_coordinate +{ + template + static inline bool apply(Point const& point, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + return + geometry::has_non_finite_coordinate(point) + ? + (! visitor.template apply()) + : + (! visitor.template apply()); + } + + template + static inline bool apply(Point const& point) + { + return geometry::has_non_finite_coordinate(point); + } +}; + +struct indexed_has_invalid_coordinate +{ + template + static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) + { + geometry::detail::indexed_point_view p0(geometry); + geometry::detail::indexed_point_view p1(geometry); + + return point_has_invalid_coordinate::apply(p0, visitor) + || point_has_invalid_coordinate::apply(p1, visitor); + } +}; + + +struct range_has_invalid_coordinate +{ + struct point_has_valid_coordinates + { + template + static inline bool apply(Point const& point) + { + return ! point_has_invalid_coordinate::apply(point); + } + }; + + template + static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + bool const has_valid_coordinates = detail::check_iterator_range + < + point_has_valid_coordinates, + true // do not consider an empty range as problematic + >::apply(geometry::points_begin(geometry), + geometry::points_end(geometry)); + + return has_valid_coordinates + ? + (! visitor.template apply()) + : + (! visitor.template apply()); + } +}; + + +template +< + typename Geometry, + typename Tag = typename tag::type, + bool HasFloatingPointCoordinates = boost::is_floating_point + < + typename coordinate_type::type + >::value +> +struct has_invalid_coordinate + : range_has_invalid_coordinate +{}; + +template +struct has_invalid_coordinate + : always_valid +{}; + +template +struct has_invalid_coordinate + : point_has_invalid_coordinate +{}; + +template +struct has_invalid_coordinate + : indexed_has_invalid_coordinate +{}; + +template +struct has_invalid_coordinate + : indexed_has_invalid_coordinate +{}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_INVALID_COORDINATE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp new file mode 100755 index 0000000000..0fc0818cf8 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -0,0 +1,173 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +template +struct equal_to +{ + Point const& m_point; + + equal_to(Point const& point) + : m_point(point) + {} + + template + inline bool operator()(OtherPoint const& other) const + { + return geometry::equals(m_point, other); + } +}; + +template +struct not_equal_to +{ + Point const& m_point; + + not_equal_to(Point const& point) + : m_point(point) + {} + + template + inline bool operator()(OtherPoint const& other) const + { + return ! geometry::equals(other, m_point); + } +}; + + + +template +struct has_spikes +{ + template + static inline Iterator find_different_from_first(Iterator first, + Iterator last) + { + typedef not_equal_to::type> not_equal; + + BOOST_GEOMETRY_ASSERT(first != last); + + Iterator second = first; + ++second; + return std::find_if(second, last, not_equal(*first)); + } + + template + static inline bool apply(Range const& range, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + typedef typename closeable_view::type view_type; + typedef typename boost::range_iterator::type iterator; + + bool const is_linear + = boost::is_same::type, linestring_tag>::value; + + view_type const view(range); + + iterator prev = boost::begin(view); + + iterator cur = find_different_from_first(prev, boost::end(view)); + if (cur == boost::end(view)) + { + // the range has only one distinct point, so it + // cannot have a spike + return ! visitor.template apply(); + } + + iterator next = find_different_from_first(cur, boost::end(view)); + if (next == boost::end(view)) + { + // the range has only two distinct points, so it + // cannot have a spike + return ! visitor.template apply(); + } + + while (next != boost::end(view)) + { + if ( geometry::detail::point_is_spike_or_equal(*prev, + *next, + *cur) ) + { + return + ! visitor.template apply(is_linear, *cur); + } + prev = cur; + cur = next; + next = find_different_from_first(cur, boost::end(view)); + } + + if (geometry::equals(range::front(view), range::back(view))) + { + iterator cur = boost::begin(view); + typename boost::range_reverse_iterator + < + view_type const + >::type prev = find_different_from_first(boost::rbegin(view), + boost::rend(view)); + + iterator next = find_different_from_first(cur, boost::end(view)); + if (detail::point_is_spike_or_equal(*prev, *next, *cur)) + { + return + ! visitor.template apply(is_linear, *cur); + } + else + { + return ! visitor.template apply(); + } + } + + return ! visitor.template apply(); + } +}; + + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp new file mode 100755 index 0000000000..5c9ba4a632 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp @@ -0,0 +1,118 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +template +< + typename Geometry, + typename IsAcceptableTurn = is_acceptable_turn +> +class has_valid_self_turns +{ +private: + typedef typename point_type::type point_type; + + typedef typename geometry::rescale_policy_type + < + point_type + >::type rescale_policy_type; + + typedef detail::overlay::get_turn_info + < + detail::overlay::assign_null_policy + > turn_policy; + +public: + typedef detail::overlay::turn_info + < + point_type, + typename geometry::segment_ratio_type + < + point_type, + rescale_policy_type + >::type + > turn_type; + + // returns true if all turns are valid + template + static inline bool apply(Geometry const& geometry, + Turns& turns, + VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry); + + detail::overlay::stateless_predicate_based_interrupt_policy + < + IsAcceptableTurn + > interrupt_policy; + + geometry::self_turns(geometry, + robust_policy, + turns, + interrupt_policy); + + if (interrupt_policy.has_intersections) + { + BOOST_GEOMETRY_ASSERT(! boost::empty(turns)); + return visitor.template apply(turns); + } + else + { + return visitor.template apply(); + } + } + + // returns true if all turns are valid + template + static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) + { + std::vector turns; + return apply(geometry, turns, visitor); + } +}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_VALID_SELF_TURNS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/implementation.hpp new file mode 100755 index 0000000000..7fe906bc69 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/implementation.hpp @@ -0,0 +1,21 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IMPLEMENTATION_HPP + +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/interface.hpp new file mode 100755 index 0000000000..d7a7daa1ba --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/interface.hpp @@ -0,0 +1,159 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +namespace resolve_variant { + +template +struct is_valid +{ + template + static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) + { + concepts::check(); + return dispatch::is_valid::apply(geometry, visitor); + } +}; + +template +struct is_valid > +{ + template + struct visitor : boost::static_visitor + { + visitor(VisitPolicy& policy) : m_policy(policy) {} + + template + bool operator()(Geometry const& geometry) const + { + return is_valid::apply(geometry, m_policy); + } + + VisitPolicy& m_policy; + }; + + template + static inline bool + apply(boost::variant const& geometry, + VisitPolicy& policy_visitor) + { + return boost::apply_visitor(visitor(policy_visitor), + geometry); + } +}; + +} // namespace resolve_variant + + +// Undocumented for now +template +inline bool is_valid(Geometry const& geometry, VisitPolicy& visitor) +{ + return resolve_variant::is_valid::apply(geometry, visitor); +} + + +/*! +\brief \brief_check{is valid (in the OGC sense)} +\ingroup is_valid +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\return \return_check{is valid (in the OGC sense); + furthermore, the following geometries are considered valid: + multi-geometries with no elements, + linear geometries containing spikes, + areal geometries with duplicate (consecutive) points} + +\qbk{[include reference/algorithms/is_valid.qbk]} +*/ +template +inline bool is_valid(Geometry const& geometry) +{ + is_valid_default_policy<> policy_visitor; + return geometry::is_valid(geometry, policy_visitor); +} + + +/*! +\brief \brief_check{is valid (in the OGC sense)} +\ingroup is_valid +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\param failure An enumeration value indicating that the geometry is + valid or not, and if not valid indicating the reason why +\return \return_check{is valid (in the OGC sense); + furthermore, the following geometries are considered valid: + multi-geometries with no elements, + linear geometries containing spikes, + areal geometries with duplicate (consecutive) points} + +\qbk{distinguish,with failure value} +\qbk{[include reference/algorithms/is_valid_with_failure.qbk]} +*/ +template +inline bool is_valid(Geometry const& geometry, validity_failure_type& failure) +{ + failure_type_policy<> policy_visitor; + bool result = geometry::is_valid(geometry, policy_visitor); + failure = policy_visitor.failure(); + return result; +} + + +/*! +\brief \brief_check{is valid (in the OGC sense)} +\ingroup is_valid +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\param message A string containing a message stating if the geometry + is valid or not, and if not valid a reason why +\return \return_check{is valid (in the OGC sense); + furthermore, the following geometries are considered valid: + multi-geometries with no elements, + linear geometries containing spikes, + areal geometries with duplicate (consecutive) points} + +\qbk{distinguish,with message} +\qbk{[include reference/algorithms/is_valid_with_message.qbk]} +*/ +template +inline bool is_valid(Geometry const& geometry, std::string& message) +{ + std::ostringstream stream; + failing_reason_policy<> policy_visitor(stream); + bool result = geometry::is_valid(geometry, policy_visitor); + message = stream.str(); + return result; +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp new file mode 100755 index 0000000000..bdaec5aa70 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp @@ -0,0 +1,154 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +template +< + typename Geometry, + order_selector Order = geometry::point_order::value, + typename Tag = typename tag::type +> +struct acceptable_operation +{}; + +template +struct acceptable_operation +{ + static const detail::overlay::operation_type value = + detail::overlay::operation_union; +}; + +template +struct acceptable_operation +{ + static const detail::overlay::operation_type value = + detail::overlay::operation_intersection; +}; + +template +struct acceptable_operation +{ + static const detail::overlay::operation_type value = + detail::overlay::operation_intersection; +}; + +template +struct acceptable_operation +{ + static const detail::overlay::operation_type value = + detail::overlay::operation_union; +}; + + + + +template ::type> +struct is_acceptable_turn +{}; + +template +struct is_acceptable_turn +{ + template + static inline bool apply(Turn const&) + { + return false; + } +}; + +template +class is_acceptable_turn +{ +protected: + template + static inline bool check_turn(Turn const& turn, + Method method, + Operation operation) + { + return turn.method == method + && turn.operations[0].operation == operation + && turn.operations[1].operation == operation; + } + + +public: + template + static inline bool apply(Turn const& turn) + { + using namespace detail::overlay; + + if ( turn.operations[0].seg_id.ring_index + == turn.operations[1].seg_id.ring_index ) + { + return false; + } + + operation_type const op = acceptable_operation::value; + + return check_turn(turn, method_touch_interior, op) + || check_turn(turn, method_touch, op) + ; + } +}; + +template +class is_acceptable_turn + : is_acceptable_turn::type> +{ +private: + typedef typename boost::range_value::type polygon; + typedef is_acceptable_turn base; + +public: + template + static inline bool apply(Turn const& turn) + { + using namespace detail::overlay; + + if ( turn.operations[0].seg_id.multi_index + == turn.operations[1].seg_id.multi_index ) + { + return base::apply(turn); + } + + operation_type const op = acceptable_operation::value; + + return base::check_turn(turn, method_touch_interior, op) + || base::check_turn(turn, method_touch, op) + ; + } +}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/linear.hpp new file mode 100755 index 0000000000..7eee114b64 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/linear.hpp @@ -0,0 +1,173 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +template +struct is_valid_linestring +{ + template + static inline bool apply(Linestring const& linestring, + VisitPolicy& visitor) + { + if (has_invalid_coordinate::apply(linestring, visitor)) + { + return false; + } + + if (boost::size(linestring) < 2) + { + return visitor.template apply(); + } + + std::size_t num_distinct = detail::num_distinct_consecutive_points + < + Linestring, + 3u, + true, + not_equal_to::type> + >::apply(linestring); + + if (num_distinct < 2u) + { + return + visitor.template apply(); + } + + if (num_distinct == 2u) + { + return visitor.template apply(); + } + return ! has_spikes::apply(linestring, visitor); + } +}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A linestring is a curve. +// A curve is 1-dimensional so it has to have at least two distinct +// points. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// There is an option here as to whether spikes are allowed for linestrings; +// here we pass this as an additional template parameter: allow_spikes +// If allow_spikes is set to true, spikes are allowed, false otherwise. +// By default, spikes are disallowed +// +// Reference: OGC 06-103r4 (6.1.6.1) +template +struct is_valid + < + Linestring, linestring_tag, AllowEmptyMultiGeometries + > : detail::is_valid::is_valid_linestring +{}; + + +// A MultiLinestring is a MultiCurve +// A MultiCurve is simple if all of its elements are simple and the +// only intersections between any two elements occur at Points that +// are on the boundaries of both elements. +// +// Reference: OGC 06-103r4 (6.1.8.1; Fig. 9) +template +class is_valid + < + MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries + > +{ +private: + template + struct per_linestring + { + per_linestring(VisitPolicy& policy) : m_policy(policy) {} + + template + inline bool apply(Linestring const& linestring) const + { + return detail::is_valid::is_valid_linestring + < + Linestring + >::apply(linestring, m_policy); + } + + VisitPolicy& m_policy; + }; + +public: + template + static inline bool apply(MultiLinestring const& multilinestring, + VisitPolicy& visitor) + { + if (BOOST_GEOMETRY_CONDITION( + AllowEmptyMultiGeometries && boost::empty(multilinestring))) + { + return visitor.template apply(); + } + + return detail::check_iterator_range + < + per_linestring, + false // do not check for empty multilinestring (done above) + >::apply(boost::begin(multilinestring), + boost::end(multilinestring), + per_linestring(visitor)); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp new file mode 100755 index 0000000000..af26ef3191 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp @@ -0,0 +1,364 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTIPOLYGON_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTIPOLYGON_HPP + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +template +class is_valid_multipolygon + : is_valid_polygon + < + typename boost::range_value::type, + true // check only the validity of rings + > +{ +private: + typedef is_valid_polygon + < + typename boost::range_value::type, + true + > base; + + + + template + < + typename PolygonIterator, + typename TurnIterator, + typename VisitPolicy + > + static inline + bool are_polygon_interiors_disjoint(PolygonIterator polygons_first, + PolygonIterator polygons_beyond, + TurnIterator turns_first, + TurnIterator turns_beyond, + VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + // collect all polygons that have turns + std::set multi_indices; + for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit) + { + multi_indices.insert(tit->operations[0].seg_id.multi_index); + multi_indices.insert(tit->operations[1].seg_id.multi_index); + } + + // put polygon iterators without turns in a vector + std::vector polygon_iterators; + signed_size_type multi_index = 0; + for (PolygonIterator it = polygons_first; it != polygons_beyond; + ++it, ++multi_index) + { + if (multi_indices.find(multi_index) == multi_indices.end()) + { + polygon_iterators.push_back(it); + } + } + + typename base::item_visitor_type item_visitor; + + geometry::partition + < + geometry::model::box::type>, + typename base::expand_box, + typename base::overlaps_box + >::apply(polygon_iterators, item_visitor); + + if (item_visitor.items_overlap) + { + return visitor.template apply(); + } + else + { + return visitor.template apply(); + } + } + + + + class has_multi_index + { + public: + has_multi_index(signed_size_type multi_index) + : m_multi_index(multi_index) + {} + + template + inline bool operator()(Turn const& turn) const + { + return turn.operations[0].seg_id.multi_index == m_multi_index + && turn.operations[1].seg_id.multi_index == m_multi_index; + } + + private: + signed_size_type const m_multi_index; + }; + + + + template + struct has_property_per_polygon + { + template + < + typename PolygonIterator, + typename TurnIterator, + typename VisitPolicy + > + static inline bool apply(PolygonIterator polygons_first, + PolygonIterator polygons_beyond, + TurnIterator turns_first, + TurnIterator turns_beyond, + VisitPolicy& visitor) + { + signed_size_type multi_index = 0; + for (PolygonIterator it = polygons_first; it != polygons_beyond; + ++it, ++multi_index) + { + has_multi_index index_predicate(multi_index); + + typedef boost::filter_iterator + < + has_multi_index, TurnIterator + > filtered_turn_iterator; + + filtered_turn_iterator filtered_turns_first(index_predicate, + turns_first, + turns_beyond); + + filtered_turn_iterator filtered_turns_beyond(index_predicate, + turns_beyond, + turns_beyond); + + if (! Predicate::apply(*it, + filtered_turns_first, + filtered_turns_beyond, + visitor)) + { + return false; + } + } + return true; + } + }; + + + + template + < + typename PolygonIterator, + typename TurnIterator, + typename VisitPolicy + > + static inline bool have_holes_inside(PolygonIterator polygons_first, + PolygonIterator polygons_beyond, + TurnIterator turns_first, + TurnIterator turns_beyond, + VisitPolicy& visitor) + { + return has_property_per_polygon + < + typename base::has_holes_inside + >::apply(polygons_first, polygons_beyond, + turns_first, turns_beyond, visitor); + } + + + + template + < + typename PolygonIterator, + typename TurnIterator, + typename VisitPolicy + > + static inline bool have_connected_interior(PolygonIterator polygons_first, + PolygonIterator polygons_beyond, + TurnIterator turns_first, + TurnIterator turns_beyond, + VisitPolicy& visitor) + { + return has_property_per_polygon + < + typename base::has_connected_interior + >::apply(polygons_first, polygons_beyond, + turns_first, turns_beyond, visitor); + } + + + template + struct per_polygon + { + per_polygon(VisitPolicy& policy) : m_policy(policy) {} + + template + inline bool apply(Polygon const& polygon) const + { + return base::apply(polygon, m_policy); + } + + VisitPolicy& m_policy; + }; +public: + template + static inline bool apply(MultiPolygon const& multipolygon, + VisitPolicy& visitor) + { + typedef debug_validity_phase debug_phase; + + if (BOOST_GEOMETRY_CONDITION( + AllowEmptyMultiGeometries && boost::empty(multipolygon))) + { + return visitor.template apply(); + } + + // check validity of all polygons ring + debug_phase::apply(1); + + if (! detail::check_iterator_range + < + per_polygon, + false // do not check for empty multipolygon (done above) + >::apply(boost::begin(multipolygon), + boost::end(multipolygon), + per_polygon(visitor))) + { + return false; + } + + + // compute turns and check if all are acceptable + debug_phase::apply(2); + + typedef has_valid_self_turns has_valid_turns; + + std::deque turns; + bool has_invalid_turns = + ! has_valid_turns::apply(multipolygon, turns, visitor); + debug_print_turns(turns.begin(), turns.end()); + + if (has_invalid_turns) + { + return false; + } + + + // check if each polygon's interior rings are inside the + // exterior and not one inside the other + debug_phase::apply(3); + + if (! have_holes_inside(boost::begin(multipolygon), + boost::end(multipolygon), + turns.begin(), + turns.end(), + visitor)) + { + return false; + } + + + // check that each polygon's interior is connected + debug_phase::apply(4); + + if (! have_connected_interior(boost::begin(multipolygon), + boost::end(multipolygon), + turns.begin(), + turns.end(), + visitor)) + { + return false; + } + + + // check if polygon interiors are disjoint + debug_phase::apply(5); + return are_polygon_interiors_disjoint(boost::begin(multipolygon), + boost::end(multipolygon), + turns.begin(), + turns.end(), + visitor); + } +}; + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// Not clear what the definition is. +// Right now we check that each element is simple (in fact valid), and +// that the MultiPolygon is also valid. +// +// Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14) +template +struct is_valid + < + MultiPolygon, multi_polygon_tag, AllowEmptyMultiGeometries + > : detail::is_valid::is_valid_multipolygon + < + MultiPolygon, AllowEmptyMultiGeometries + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTIPOLYGON_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/pointlike.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/pointlike.hpp new file mode 100755 index 0000000000..dd934c57a5 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/pointlike.hpp @@ -0,0 +1,91 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP + +#include +#include + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A point is always simple +template +struct is_valid +{ + template + static inline bool apply(Point const& point, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + return ! detail::is_valid::has_invalid_coordinate + < + Point + >::apply(point, visitor); + } +}; + + + +// A MultiPoint is simple if no two Points in the MultiPoint are equal +// (have identical coordinate values in X and Y) +// +// Reference: OGC 06-103r4 (6.1.5) +template +struct is_valid +{ + template + static inline bool apply(MultiPoint const& multipoint, + VisitPolicy& visitor) + { + boost::ignore_unused(multipoint, visitor); + + if (BOOST_GEOMETRY_CONDITION( + AllowEmptyMultiGeometries || !boost::empty(multipoint))) + { + // we allow empty multi-geometries, so an empty multipoint + // is considered valid + return ! detail::is_valid::has_invalid_coordinate + < + MultiPoint + >::apply(multipoint, visitor); + } + else + { + // we do not allow an empty multipoint + return visitor.template apply(); + } + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp new file mode 100755 index 0000000000..1ff2e6f9dc --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -0,0 +1,425 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP + +#include +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#include +#endif // BOOST_GEOMETRY_TEST_DEBUG + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +template +class is_valid_polygon +{ +protected: + typedef debug_validity_phase debug_phase; + + template + struct per_ring + { + per_ring(VisitPolicy& policy) : m_policy(policy) {} + + template + inline bool apply(Ring const& ring) const + { + return detail::is_valid::is_valid_ring + < + Ring, false, true + >::apply(ring, m_policy); + } + + VisitPolicy& m_policy; + }; + + template + static bool has_valid_interior_rings(InteriorRings const& interior_rings, + VisitPolicy& visitor) + { + return + detail::check_iterator_range + < + per_ring, + true // allow for empty interior ring range + >::apply(boost::begin(interior_rings), + boost::end(interior_rings), + per_ring(visitor)); + } + + struct has_valid_rings + { + template + static inline bool apply(Polygon const& polygon, VisitPolicy& visitor) + { + typedef typename ring_type::type ring_type; + + // check validity of exterior ring + debug_phase::apply(1); + + if (! detail::is_valid::is_valid_ring + < + ring_type, + false // do not check self intersections + >::apply(exterior_ring(polygon), visitor)) + { + return false; + } + + // check validity of interior rings + debug_phase::apply(2); + + return has_valid_interior_rings(geometry::interior_rings(polygon), + visitor); + } + }; + + + // structs for partition -- start + struct expand_box + { + template + static inline void apply(Box& total, Iterator const& it) + { + geometry::expand(total, geometry::return_envelope(*it)); + } + + }; + + struct overlaps_box + { + template + static inline bool apply(Box const& box, Iterator const& it) + { + return ! geometry::disjoint(*it, box); + } + }; + + + struct item_visitor_type + { + bool items_overlap; + + item_visitor_type() : items_overlap(false) {} + + template + inline void apply(Item1 const& item1, Item2 const& item2) + { + if (! items_overlap + && (geometry::within(*points_begin(*item1), *item2) + || geometry::within(*points_begin(*item2), *item1)) + ) + { + items_overlap = true; + } + } + }; + // structs for partition -- end + + + template + < + typename RingIterator, + typename ExteriorRing, + typename TurnIterator, + typename VisitPolicy + > + static inline bool are_holes_inside(RingIterator rings_first, + RingIterator rings_beyond, + ExteriorRing const& exterior_ring, + TurnIterator turns_first, + TurnIterator turns_beyond, + VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + // collect the interior ring indices that have turns with the + // exterior ring + std::set ring_indices; + for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit) + { + if (tit->operations[0].seg_id.ring_index == -1) + { + BOOST_GEOMETRY_ASSERT(tit->operations[1].seg_id.ring_index != -1); + ring_indices.insert(tit->operations[1].seg_id.ring_index); + } + else if (tit->operations[1].seg_id.ring_index == -1) + { + BOOST_GEOMETRY_ASSERT(tit->operations[0].seg_id.ring_index != -1); + ring_indices.insert(tit->operations[0].seg_id.ring_index); + } + } + + signed_size_type ring_index = 0; + for (RingIterator it = rings_first; it != rings_beyond; + ++it, ++ring_index) + { + // do not examine interior rings that have turns with the + // exterior ring + if (ring_indices.find(ring_index) == ring_indices.end() + && ! geometry::covered_by(range::front(*it), exterior_ring)) + { + return visitor.template apply(); + } + } + + // collect all rings (exterior and/or interior) that have turns + for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit) + { + ring_indices.insert(tit->operations[0].seg_id.ring_index); + ring_indices.insert(tit->operations[1].seg_id.ring_index); + } + + // put iterators for interior rings without turns in a vector + std::vector ring_iterators; + ring_index = 0; + for (RingIterator it = rings_first; it != rings_beyond; + ++it, ++ring_index) + { + if (ring_indices.find(ring_index) == ring_indices.end()) + { + ring_iterators.push_back(it); + } + } + + // call partition to check is interior rings are disjoint from + // each other + item_visitor_type item_visitor; + + geometry::partition + < + geometry::model::box::type>, + expand_box, + overlaps_box + >::apply(ring_iterators, item_visitor); + + if (item_visitor.items_overlap) + { + return visitor.template apply(); + } + else + { + return visitor.template apply(); + } + } + + template + < + typename InteriorRings, + typename ExteriorRing, + typename TurnIterator, + typename VisitPolicy + > + static inline bool are_holes_inside(InteriorRings const& interior_rings, + ExteriorRing const& exterior_ring, + TurnIterator first, + TurnIterator beyond, + VisitPolicy& visitor) + { + return are_holes_inside(boost::begin(interior_rings), + boost::end(interior_rings), + exterior_ring, + first, + beyond, + visitor); + } + + struct has_holes_inside + { + template + static inline bool apply(Polygon const& polygon, + TurnIterator first, + TurnIterator beyond, + VisitPolicy& visitor) + { + return are_holes_inside(geometry::interior_rings(polygon), + geometry::exterior_ring(polygon), + first, + beyond, + visitor); + } + }; + + + + + struct has_connected_interior + { + template + static inline bool apply(Polygon const& polygon, + TurnIterator first, + TurnIterator beyond, + VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + typedef typename std::iterator_traits + < + TurnIterator + >::value_type turn_type; + typedef complement_graph graph; + + graph g(geometry::num_interior_rings(polygon) + 1); + for (TurnIterator tit = first; tit != beyond; ++tit) + { + typename graph::vertex_handle v1 = g.add_vertex + ( tit->operations[0].seg_id.ring_index + 1 ); + typename graph::vertex_handle v2 = g.add_vertex + ( tit->operations[1].seg_id.ring_index + 1 ); + typename graph::vertex_handle vip = g.add_vertex(tit->point); + + g.add_edge(v1, vip); + g.add_edge(v2, vip); + } + +#ifdef BOOST_GEOMETRY_TEST_DEBUG + debug_print_complement_graph(std::cout, g); +#endif // BOOST_GEOMETRY_TEST_DEBUG + + if (g.has_cycles()) + { + return visitor.template apply(); + } + else + { + return visitor.template apply(); + } + } + }; + +public: + template + static inline bool apply(Polygon const& polygon, VisitPolicy& visitor) + { + if (! has_valid_rings::apply(polygon, visitor)) + { + return false; + } + + if (BOOST_GEOMETRY_CONDITION(CheckRingValidityOnly)) + { + return true; + } + + // compute turns and check if all are acceptable + debug_phase::apply(3); + + typedef has_valid_self_turns has_valid_turns; + + std::deque turns; + bool has_invalid_turns + = ! has_valid_turns::apply(polygon, turns, visitor); + debug_print_turns(turns.begin(), turns.end()); + + if (has_invalid_turns) + { + return false; + } + + // check if all interior rings are inside the exterior ring + debug_phase::apply(4); + + if (! has_holes_inside::apply(polygon, + turns.begin(), turns.end(), + visitor)) + { + return false; + } + + // check whether the interior of the polygon is a connected set + debug_phase::apply(5); + + return has_connected_interior::apply(polygon, + turns.begin(), + turns.end(), + visitor); + } +}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1) +template +struct is_valid + < + Polygon, polygon_tag, AllowEmptyMultiGeometries + > : detail::is_valid::is_valid_polygon +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/ring.hpp new file mode 100755 index 0000000000..816b1c1ecf --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -0,0 +1,235 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef BOOST_GEOMETRY_TEST_DEBUG +#include +#endif + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +// struct to check whether a ring is topologically closed +template +struct is_topologically_closed +{ + template + static inline bool apply(Ring const&, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + return visitor.template apply(); + } +}; + +template +struct is_topologically_closed +{ + template + static inline bool apply(Ring const& ring, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + if (geometry::equals(range::front(ring), range::back(ring))) + { + return visitor.template apply(); + } + else + { + return visitor.template apply(); + } + } +}; + + + +template +struct ring_area_predicate +{ + typedef std::greater type; +}; + +template +struct ring_area_predicate +{ + typedef std::less type; +}; + + + +template +struct is_properly_oriented +{ + typedef typename point_type::type point_type; + + typedef typename strategy::area::services::default_strategy + < + typename cs_tag::type, + point_type + >::type strategy_type; + + typedef detail::area::ring_area + < + order_as_direction::value>::value, + geometry::closure::value + > ring_area_type; + + typedef typename default_area_result::type area_result_type; + + template + static inline bool apply(Ring const& ring, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + typename ring_area_predicate + < + area_result_type, IsInteriorRing + >::type predicate; + + // Check area + area_result_type const zero = area_result_type(); + if (predicate(ring_area_type::apply(ring, strategy_type()), zero)) + { + return visitor.template apply(); + } + else + { + return visitor.template apply(); + } + } +}; + + + +template +< + typename Ring, + bool CheckSelfIntersections = true, + bool IsInteriorRing = false +> +struct is_valid_ring +{ + template + static inline bool apply(Ring const& ring, VisitPolicy& visitor) + { + // return invalid if any of the following condition holds: + // (a) the ring's point coordinates are not invalid (e.g., NaN) + // (b) the ring's size is below the minimal one + // (c) the ring consists of at most two distinct points + // (d) the ring is not topologically closed + // (e) the ring has spikes + // (f) the ring has duplicate points (if AllowDuplicates is false) + // (g) the boundary of the ring has self-intersections + // (h) the order of the points is inconsistent with the defined order + // + // Note: no need to check if the area is zero. If this is the + // case, then the ring must have at least two spikes, which is + // checked by condition (d). + + if (has_invalid_coordinate::apply(ring, visitor)) + { + return false; + } + + closure_selector const closure = geometry::closure::value; + typedef typename closeable_view::type view_type; + + if (boost::size(ring) + < core_detail::closure::minimum_ring_size::value) + { + return visitor.template apply(); + } + + view_type const view(ring); + if (detail::num_distinct_consecutive_points + < + view_type, 4u, true, + not_equal_to::type> + >::apply(view) + < 4u) + { + return + visitor.template apply(); + } + + return + is_topologically_closed::apply(ring, visitor) + && ! has_duplicates::apply(ring, visitor) + && ! has_spikes::apply(ring, visitor) + && (! CheckSelfIntersections + || has_valid_self_turns::apply(ring, visitor)) + && is_properly_oriented::apply(ring, visitor); + } +}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A Ring is a Polygon with exterior boundary only. +// The Ring's boundary must be a LinearRing (see OGC 06-103-r4, +// 6.1.7.1, for the definition of LinearRing) +// +// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1) +template +struct is_valid + < + Ring, ring_tag, AllowEmptyMultiGeometries + > : detail::is_valid::is_valid_ring +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/segment.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/segment.hpp new file mode 100755 index 0000000000..c240bfa955 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -0,0 +1,83 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP + +#include + +#include +#include + +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A segment is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// A curve is 1-dimensional, hence we have to check is the two +// endpoints of the segment coincide, since in this case it is +// 0-dimensional. +// +// Reference: OGC 06-103r4 (6.1.6.1) +template +struct is_valid +{ + template + static inline bool apply(Segment const& segment, VisitPolicy& visitor) + { + boost::ignore_unused(visitor); + + typename point_type::type p[2]; + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); + + if (detail::is_valid::has_invalid_coordinate + < + Segment + >::apply(segment, visitor)) + { + return false; + } + else if (! geometry::equals(p[0], p[1])) + { + return visitor.template apply(); + } + else + { + return + visitor.template apply(); + } + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/max_interval_gap.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/max_interval_gap.hpp new file mode 100755 index 0000000000..08f4e382cb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/max_interval_gap.hpp @@ -0,0 +1,278 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace max_interval_gap +{ + +// the class Interval must provide the following: +// * must define the type value_type +// * must define the type difference_type +// * must have the methods: +// value_type get() const +// difference_type length() const +// where an Index value of 0 (resp., 1) refers to the left (resp., +// right) endpoint of the interval + +template +class sweep_event +{ +public: + typedef Interval interval_type; + typedef typename Interval::value_type time_type; + + sweep_event(Interval const& interval, bool start_event = true) + : m_interval(boost::cref(interval)) + , m_start_event(start_event) + {} + + inline bool is_start_event() const + { + return m_start_event; + } + + inline interval_type const& interval() const + { + return m_interval; + } + + inline time_type time() const + { + return (m_start_event) + ? interval().template get<0>() + : interval().template get<1>(); + } + + inline bool operator<(sweep_event const& other) const + { + if (! math::equals(time(), other.time())) + { + return time() < other.time(); + } + // a start-event is before an end-event with the same event time + return is_start_event() && ! other.is_start_event(); + } + +private: + boost::reference_wrapper m_interval; + bool m_start_event; +}; + +template +struct event_greater +{ + inline bool operator()(Event const& event1, Event const& event2) const + { + return event2 < event1; + } +}; + + +struct initialization_visitor +{ + template + static inline void apply(Range const& range, + PriorityQueue& queue, + EventVisitor&) + { + BOOST_GEOMETRY_ASSERT(queue.empty()); + + // it is faster to build the queue directly from the entire + // range, rather than insert elements one after the other + PriorityQueue pq(boost::begin(range), boost::end(range)); + std::swap(pq, queue); + } +}; + + +template +class event_visitor +{ + typedef typename Event::time_type event_time_type; + typedef typename Event::interval_type::difference_type difference_type; + + typedef typename boost::remove_const + < + typename boost::remove_reference + < + event_time_type + >::type + >::type bare_time_type; + + +public: + event_visitor() + : m_overlap_count(0) + , m_max_gap_left(0) + , m_max_gap_right(0) + {} + + template + inline void apply(Event const& event, PriorityQueue& queue) + { + if (event.is_start_event()) + { + ++m_overlap_count; + queue.push(Event(event.interval(), false)); + } + else + { + --m_overlap_count; + if (m_overlap_count == 0 && ! queue.empty()) + { + // we may have a gap + BOOST_GEOMETRY_ASSERT(queue.top().is_start_event()); + + event_time_type next_event_time + = queue.top().interval().template get<0>(); + difference_type gap = next_event_time - event.time(); + if (gap > max_gap()) + { + m_max_gap_left = event.time(); + m_max_gap_right = next_event_time; + } + } + } + } + + bare_time_type const& max_gap_left() const + { + return m_max_gap_left; + } + + bare_time_type const& max_gap_right() const + { + return m_max_gap_right; + } + + difference_type max_gap() const + { + return m_max_gap_right - m_max_gap_left; + } + +private: + std::size_t m_overlap_count; + bare_time_type m_max_gap_left, m_max_gap_right; +}; + +}} // namespace detail::max_interval_gap +#endif // DOXYGEN_NO_DETAIL + + +// Given a range of intervals I1, I2, ..., In, maximum_gap() returns +// the maximum length of an interval M that satisfies the following +// properties: +// +// 1. M.left >= min(I1, I2, ..., In) +// 2. M.right <= max(I1, I2, ..., In) +// 3. intersection(interior(M), Ik) is the empty set for all k=1, ..., n +// 4. length(M) is maximal +// +// where M.left and M.right denote the left and right extreme values +// for the interval M, and length(M) is equal to M.right - M.left. +// +// If M does not exist (or, alternatively, M is identified as the +// empty set), 0 is returned. +// +// The algorithm proceeds for performing a sweep: the left endpoints +// are inserted into a min-priority queue with the priority being the +// value of the endpoint. The sweep algorithm maintains an "overlap +// counter" that counts the number of overlaping intervals at any +// specific sweep-time value. +// There are two types of events encountered during the sweep: +// (a) a start event: the left endpoint of an interval is found. +// In this case the overlap count is increased by one and the +// right endpoint of the interval in inserted into the event queue +// (b) an end event: the right endpoint of an interval is found. +// In this case the overlap count is decreased by one. If the +// updated overlap count is 0, then we could expect to have a gap +// in-between intervals. This gap is measured as the (absolute) +// distance of the current interval right endpoint (being +// processed) to the upcoming left endpoint of the next interval +// to be processed (if such an interval exists). If the measured +// gap is greater than the current maximum gap, it is recorded. +// The initial maximum gap is initialized to 0. This value is returned +// if no gap is found during the sweeping procedure. + +template +inline typename boost::range_value::type::difference_type +maximum_gap(RangeOfIntervals const& range_of_intervals, + T& max_gap_left, T& max_gap_right) +{ + typedef typename boost::range_value::type interval_type; + typedef detail::max_interval_gap::sweep_event event_type; + + // create a min-priority queue for the events + std::priority_queue + < + event_type, + std::vector, + detail::max_interval_gap::event_greater + > queue; + + // define initialization and event-process visitors + detail::max_interval_gap::initialization_visitor init_visitor; + detail::max_interval_gap::event_visitor sweep_visitor; + + // perform the sweep + geometry::sweep(range_of_intervals, + queue, + init_visitor, + sweep_visitor); + + max_gap_left = sweep_visitor.max_gap_left(); + max_gap_right = sweep_visitor.max_gap_right(); + return sweep_visitor.max_gap(); +} + +template +inline typename boost::range_value::type::difference_type +maximum_gap(RangeOfIntervals const& range_of_intervals) +{ + typedef typename boost::remove_const + < + typename boost::remove_reference + < + typename boost::range_value + < + RangeOfIntervals + >::type::value_type + >::type + >::type value_type; + + value_type left, right; + + return maximum_gap(range_of_intervals, left, right); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_modify.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_modify.hpp new file mode 100755 index 0000000000..aadfd93fbf --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_modify.hpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_HPP + + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +template +struct multi_modify +{ + static inline void apply(MultiGeometry& multi) + { + typedef typename boost::range_iterator::type iterator_type; + for (iterator_type it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + Policy::apply(*it); + } + } +}; + + +} // namespace detail +#endif + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp new file mode 100755 index 0000000000..5041994ab0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_WITH_PREDICATE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_WITH_PREDICATE_HPP + + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct multi_modify_with_predicate +{ + static inline void apply(MultiGeometry& multi, Predicate const& predicate) + { + typedef typename boost::range_iterator::type iterator_type; + for (iterator_type it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + Policy::apply(*it, predicate); + } + } +}; + + +} // namespace detail +#endif + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_MODIFY_WITH_PREDICATE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_sum.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_sum.hpp new file mode 100755 index 0000000000..80f57da552 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/multi_sum.hpp @@ -0,0 +1,52 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_SUM_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_SUM_HPP + +#include + + +namespace boost { namespace geometry +{ +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +struct multi_sum +{ + template + static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy) + { + ReturnType sum = ReturnType(); + for (typename boost::range_iterator + < + MultiGeometry const + >::type it = boost::begin(geometry); + it != boost::end(geometry); + ++it) + { + sum += Policy::apply(*it, strategy); + } + return sum; + } +}; + + +} // namespace detail +#endif + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MULTI_SUM_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/normalize.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/normalize.hpp new file mode 100755 index 0000000000..8c12b8f6e6 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/normalize.hpp @@ -0,0 +1,294 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace normalization +{ + + +struct do_nothing +{ + template + static inline void apply(GeometryIn const&, GeometryOut&) + { + } +}; + + +template +struct assign_loop +{ + template + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set(point_out, boost::numeric_cast + < + typename coordinate_type::type + >(geometry::get(point_in))); + + assign_loop + < + Dimension + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template +struct assign_loop +{ + template + static inline void apply(CoordinateType const&, + CoordinateType const&, + PointIn const&, + PointOut&) + { + } +}; + +template +struct assign_loop<0, DimensionCount> +{ + template + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<0>(point_out, boost::numeric_cast + < + typename coordinate_type::type + >(longitude)); + + assign_loop + < + 1, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + +template +struct assign_loop<1, DimensionCount> +{ + template + static inline void apply(CoordinateType const& longitude, + CoordinateType const& latitude, + PointIn const& point_in, + PointOut& point_out) + { + geometry::set<1>(point_out, boost::numeric_cast + < + typename coordinate_type::type + >(latitude)); + + assign_loop + < + 2, DimensionCount + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template +struct normalize_point +{ + static inline void apply(PointIn const& point_in, PointOut& point_out) + { + typedef typename coordinate_type::type in_coordinate_type; + + in_coordinate_type longitude = geometry::get<0>(point_in); + in_coordinate_type latitude = geometry::get<1>(point_in); + + math::normalize_spheroidal_coordinates + < + typename coordinate_system::type::units, + in_coordinate_type + >(longitude, latitude); + + assign_loop + < + 0, dimension::value + >::apply(longitude, latitude, point_in, point_out); + } +}; + + +template +class normalize_box +{ + template + static inline void apply_to_coordinates(CoordinateInType& lon_min, + CoordinateInType& lat_min, + CoordinateInType& lon_max, + CoordinateInType& lat_max, + BoxIn const& box_in, + BoxOut& box_out) + { + detail::indexed_point_view p_min_out(box_out); + assign_loop + < + 0, dimension::value + >::apply(lon_min, + lat_min, + detail::indexed_point_view + < + BoxIn const, min_corner + >(box_in), + p_min_out); + + detail::indexed_point_view p_max_out(box_out); + assign_loop + < + 0, dimension::value + >::apply(lon_max, + lat_max, + detail::indexed_point_view + < + BoxIn const, max_corner + >(box_in), + p_max_out); + } + +public: + static inline void apply(BoxIn const& box_in, BoxOut& box_out) + { + typedef typename coordinate_type::type in_coordinate_type; + + in_coordinate_type lon_min = geometry::get(box_in); + in_coordinate_type lat_min = geometry::get(box_in); + in_coordinate_type lon_max = geometry::get(box_in); + in_coordinate_type lat_max = geometry::get(box_in); + + math::normalize_spheroidal_box_coordinates + < + typename coordinate_system::type::units, + in_coordinate_type + >(lon_min, lat_min, lon_max, lat_max); + + apply_to_coordinates + < + typename coordinate_system::type::units, + typename coordinate_system::type::units + >(lon_min, lat_min, lon_max, lat_max, box_in, box_out); + } +}; + + +}} // namespace detail::normalization +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename GeometryIn, + typename GeometryOut, + typename TagIn = typename tag::type, + typename TagOut = typename tag::type, + typename CSTagIn = typename cs_tag::type, + typename CSTagOut = typename cs_tag::type +> +struct normalize : detail::normalization::do_nothing +{}; + + +template +struct normalize + < + PointIn, PointOut, point_tag, point_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::normalization::normalize_point +{}; + + +template +struct normalize + < + PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag + > : detail::normalization::normalize_point +{}; + + +template +struct normalize + < + BoxIn, BoxOut, box_tag, box_tag, + spherical_equatorial_tag, spherical_equatorial_tag + > : detail::normalization::normalize_box +{}; + + +template +struct normalize + < + BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag + > : detail::normalization::normalize_box +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +template +inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out) +{ + dispatch::normalize + < + GeometryIn, GeometryOut + >::apply(geometry_in, geometry_out); +} + +template +inline GeometryOut return_normalized(GeometryIn const& geometry_in) +{ + GeometryOut geometry_out; + detail::normalize(geometry_in, geometry_out); + return geometry_out; +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/not.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/not.hpp new file mode 100755 index 0000000000..153b2ad807 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/not.hpp @@ -0,0 +1,57 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + + +/*! +\brief Structure negating the result of specified policy +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Policy +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\return Negation of the result of the policy + */ +template +struct not_ +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2) + { + return ! Policy::apply(geometry1, geometry2); + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp new file mode 100755 index 0000000000..5472444b7c --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp @@ -0,0 +1,93 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NUM_DISTINCT_CONSECUTIVE_POINTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NUM_DISTINCT_CONSECUTIVE_POINTS_HPP + +#include + +#include + +#include + + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + + +// returns the number of distinct values in the range; +// return values are 0u through MaximumNumber, where MaximumNumber +// corresponds to MaximumNumber or more distinct values +// +// FUTURE: take into account topologically closed ranges; +// add appropriate template parameter(s) to control whether +// the closing point for topologically closed ranges is to be +// accounted for separately or not +template +< + typename Range, + std::size_t MaximumNumber, + bool AllowDuplicates /* true */, + typename NotEqualTo +> +struct num_distinct_consecutive_points +{ + static inline std::size_t apply(Range const& range) + { + typedef typename boost::range_iterator::type iterator; + + std::size_t const size = boost::size(range); + + if ( size < 2u ) + { + return (size < MaximumNumber) ? size : MaximumNumber; + } + + iterator current = boost::begin(range); + std::size_t counter(0); + do + { + ++counter; + iterator next = std::find_if(current, + boost::end(range), + NotEqualTo(*current)); + current = next; + } + while ( current != boost::end(range) && counter <= MaximumNumber ); + + return counter; + } +}; + + +template +struct num_distinct_consecutive_points +{ + static inline std::size_t apply(Range const& range) + { + std::size_t const size = boost::size(range); + return (size < MaximumNumber) ? size : MaximumNumber; + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NUM_DISTINCT_CONSECUTIVE_POINTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/occupation_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/occupation_info.hpp new file mode 100755 index 0000000000..128386cae4 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/occupation_info.hpp @@ -0,0 +1,208 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP + +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct angle_info +{ + typedef T angle_type; + typedef Point point_type; + + segment_identifier seg_id; + std::size_t turn_index; + int operation_index; + std::size_t cluster_index; + Point intersection_point; + Point point; // either incoming or outgoing point + bool incoming; + bool blocked; + bool included; + + inline angle_info() + : blocked(false) + , included(false) + {} +}; + +template +class occupation_info +{ +public : + typedef std::vector collection_type; + + std::size_t count; + + inline occupation_info() + : count(0) + {} + + template + inline void add(RobustPoint const& incoming_point, + RobustPoint const& outgoing_point, + RobustPoint const& intersection_point, + std::size_t turn_index, int operation_index, + segment_identifier const& seg_id) + { + geometry::equal_to comparator; + if (comparator(incoming_point, intersection_point)) + { + return; + } + if (comparator(outgoing_point, intersection_point)) + { + return; + } + + AngleInfo info; + info.seg_id = seg_id; + info.turn_index = turn_index; + info.operation_index = operation_index; + info.intersection_point = intersection_point; + + { + info.point = incoming_point; + info.incoming = true; + m_angles.push_back(info); + } + { + info.point = outgoing_point; + info.incoming = false; + m_angles.push_back(info); + } + } + + template + inline void get_left_turns(RobustPoint const& origin, Turns& turns) + { + // Sort on angle + std::sort(m_angles.begin(), m_angles.end(), + detail::left_turns::angle_less(origin)); + + // Group same-angled elements + std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin); + // Block all turns on the right side of any turn + detail::left_turns::block_turns(m_angles, cluster_size); + detail::left_turns::get_left_turns(m_angles, turns); + } + +#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS) + template + inline bool has_rounding_issues(RobustPoint const& origin) const + { + return detail::left_turns::has_rounding_issues(angles, origin); + } +#endif + +private : + collection_type m_angles; // each turn splitted in incoming/outgoing vectors +}; + +template +inline void move_index(Pieces const& pieces, signed_size_type& index, signed_size_type& piece_index, int direction) +{ + BOOST_GEOMETRY_ASSERT(direction == 1 || direction == -1); + BOOST_GEOMETRY_ASSERT( + piece_index >= 0 + && piece_index < static_cast(boost::size(pieces)) ); + BOOST_GEOMETRY_ASSERT( + index >= 0 + && index < static_cast(boost::size(pieces[piece_index].robust_ring))); + + // NOTE: both index and piece_index must be in valid range + // this means that then they could be of type std::size_t + // if the code below was refactored + + index += direction; + if (direction == -1 && index < 0) + { + piece_index--; + if (piece_index < 0) + { + piece_index = boost::size(pieces) - 1; + } + index = boost::size(pieces[piece_index].robust_ring) - 1; + } + if (direction == 1 + && index >= static_cast(boost::size(pieces[piece_index].robust_ring))) + { + piece_index++; + if (piece_index >= static_cast(boost::size(pieces))) + { + piece_index = 0; + } + index = 0; + } +} + + +template +< + typename RobustPoint, + typename Turn, + typename Pieces, + typename Info +> +inline void add_incoming_and_outgoing_angles( + RobustPoint const& intersection_point, // rescaled + Turn const& turn, + Pieces const& pieces, // using rescaled offsets of it + int operation_index, + segment_identifier seg_id, + Info& info) +{ + segment_identifier real_seg_id = seg_id; + geometry::equal_to comparator; + + // Move backward and forward + RobustPoint direction_points[2]; + for (int i = 0; i < 2; i++) + { + signed_size_type index = turn.operations[operation_index].index_in_robust_ring; + signed_size_type piece_index = turn.operations[operation_index].piece_index; + while(comparator(pieces[piece_index].robust_ring[index], intersection_point)) + { + move_index(pieces, index, piece_index, i == 0 ? -1 : 1); + } + direction_points[i] = pieces[piece_index].robust_ring[index]; + } + + info.add(direction_points[0], direction_points[1], intersection_point, + turn.turn_index, operation_index, real_seg_id); +} + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp new file mode 100755 index 0000000000..49470ccbcb --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/add_rings.hpp @@ -0,0 +1,161 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP + +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +< + typename GeometryOut, + typename Geometry1, + typename Geometry2, + typename RingCollection +> +inline void convert_and_add(GeometryOut& result, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RingCollection const& collection, + ring_identifier id, + bool reversed, bool append) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + typedef typename geometry::tag::type tag_out; + + if (id.source_index == 0) + { + convert_ring::apply(result, + get_ring::apply(id, geometry1), + append, reversed); + } + else if (id.source_index == 1) + { + convert_ring::apply(result, + get_ring::apply(id, geometry2), + append, reversed); + } + else if (id.source_index == 2) + { + convert_ring::apply(result, + get_ring::apply(id, collection), + append, reversed); + } +} + +template +< + typename GeometryOut, + typename SelectionMap, + typename Geometry1, + typename Geometry2, + typename RingCollection, + typename OutputIterator +> +inline OutputIterator add_rings(SelectionMap const& map, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RingCollection const& collection, + OutputIterator out) +{ + typedef typename SelectionMap::const_iterator iterator; + typedef typename SelectionMap::mapped_type property_type; + typedef typename property_type::area_type area_type; + + area_type const zero = 0; + std::size_t const min_num_points = core_detail::closure::minimum_ring_size + < + geometry::closure + < + typename boost::range_value + < + RingCollection const + >::type + >::value + >::value; + + + for (iterator it = boost::begin(map); + it != boost::end(map); + ++it) + { + if (! it->second.discarded + && it->second.parent.source_index == -1) + { + GeometryOut result; + convert_and_add(result, geometry1, geometry2, collection, + it->first, it->second.reversed, false); + + // Add children + for (typename std::vector::const_iterator child_it + = it->second.children.begin(); + child_it != it->second.children.end(); + ++child_it) + { + iterator mit = map.find(*child_it); + if (mit != map.end() + && ! mit->second.discarded) + { + convert_and_add(result, geometry1, geometry2, collection, + *child_it, mit->second.reversed, true); + } + } + + // Only add rings if they satisfy minimal requirements. + // This cannot be done earlier (during traversal), not + // everything is figured out yet (sum of positive/negative rings) + if (geometry::num_points(result) >= min_num_points + && math::larger(geometry::area(result), zero)) + { + *out++ = result; + } + } + } + return out; +} + + +template +< + typename GeometryOut, + typename SelectionMap, + typename Geometry, + typename RingCollection, + typename OutputIterator +> +inline OutputIterator add_rings(SelectionMap const& map, + Geometry const& geometry, + RingCollection const& collection, + OutputIterator out) +{ + Geometry empty; + return add_rings(map, geometry, empty, collection, out); +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp new file mode 100755 index 0000000000..f254b08eab --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP + + +#include + +#include +#include + + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +inline void append_no_duplicates(Range& range, Point const& point, bool force = false) +{ + if (boost::size(range) == 0 + || force + || ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point)) + { +#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION + std::cout << " add: (" + << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")" + << std::endl; +#endif + geometry::append(range, point); + } +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp new file mode 100755 index 0000000000..f7730d79a9 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp @@ -0,0 +1,161 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP + +#include + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +// TODO: move this / rename this +template +inline bool points_equal_or_close(Point1 const& point1, + Point2 const& point2, + RobustPolicy const& robust_policy) +{ + if (detail::equals::equals_point_point(point1, point2)) + { + return true; + } + + if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled)) + { + return false; + } + + // Try using specified robust policy + typedef typename geometry::robust_point_type + < + Point1, + RobustPolicy + >::type robust_point_type; + + robust_point_type point1_rob, point2_rob; + geometry::recalculate(point1_rob, point1, robust_policy); + geometry::recalculate(point2_rob, point2, robust_policy); + + return detail::equals::equals_point_point(point1_rob, point2_rob); +} + + +template +inline void append_no_dups_or_spikes(Range& range, Point const& point, + RobustPolicy const& robust_policy) +{ +#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION + std::cout << " add: (" + << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")" + << std::endl; +#endif + // The code below this condition checks all spikes/dups + // for geometries >= 3 points. + // So we have to check the first potential duplicate differently + if (boost::size(range) == 1 + && points_equal_or_close(*(boost::begin(range)), point, robust_policy)) + { + return; + } + + traits::push_back::apply(range, point); + + // If a point is equal, or forming a spike, remove the pen-ultimate point + // because this one caused the spike. + // If so, the now-new-pen-ultimate point can again cause a spike + // (possibly at a corner). So keep doing this. + // Besides spikes it will also avoid adding duplicates. + while(boost::size(range) >= 3 + && point_is_spike_or_equal(point, + *(boost::end(range) - 3), + *(boost::end(range) - 2), + robust_policy)) + { + // Use the Concept/traits, so resize and append again + traits::resize::apply(range, boost::size(range) - 2); + traits::push_back::apply(range, point); + } +} + +template +inline void clean_closing_dups_and_spikes(Range& range, + RobustPolicy const& robust_policy) +{ + std::size_t const minsize + = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + + if (boost::size(range) <= minsize) + { + return; + } + + typedef typename boost::range_iterator::type iterator_type; + static bool const closed = geometry::closure::value == geometry::closed; + +// TODO: the following algorithm could be rewritten to first look for spikes +// and then erase some number of points from the beginning of the Range + + bool found = false; + do + { + found = false; + iterator_type first = boost::begin(range); + iterator_type second = first + 1; + iterator_type ultimate = boost::end(range) - 1; + if (BOOST_GEOMETRY_CONDITION(closed)) + { + ultimate--; + } + + // Check if closing point is a spike (this is so if the second point is + // considered as a spike w.r.t. the last segment) + if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy)) + { + range::erase(range, first); + if (BOOST_GEOMETRY_CONDITION(closed)) + { + // Remove closing last point + range::resize(range, boost::size(range) - 1); + // Add new closing point + range::push_back(range, range::front(range)); + } + found = true; + } + } while(found && boost::size(range) > minsize); +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp new file mode 100755 index 0000000000..b3586c66d0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -0,0 +1,335 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + + +template +< + typename Item, + typename Geometry1, typename Geometry2, + typename RingCollection +> +static inline bool within_selected_input(Item const& item2, ring_identifier const& ring_id, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RingCollection const& collection) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + + switch (ring_id.source_index) + { + case 0 : + return geometry::within(item2.point, + get_ring::apply(ring_id, geometry1)); + break; + case 1 : + return geometry::within(item2.point, + get_ring::apply(ring_id, geometry2)); + break; + case 2 : + return geometry::within(item2.point, + get_ring::apply(ring_id, collection)); + break; + } + return false; +} + + +template +struct ring_info_helper +{ + typedef typename geometry::default_area_result::type area_type; + + ring_identifier id; + area_type real_area; + area_type abs_area; + model::box envelope; + + inline ring_info_helper() + : real_area(0), abs_area(0) + {} + + inline ring_info_helper(ring_identifier i, area_type a) + : id(i), real_area(a), abs_area(geometry::math::abs(a)) + {} +}; + + +struct ring_info_helper_get_box +{ + template + static inline void apply(Box& total, InputItem const& item) + { + geometry::expand(total, item.envelope); + } +}; + +struct ring_info_helper_ovelaps_box +{ + template + static inline bool apply(Box const& box, InputItem const& item) + { + return ! geometry::detail::disjoint::disjoint_box_box(box, item.envelope); + } +}; + +template +struct assign_visitor +{ + typedef typename RingMap::mapped_type ring_info_type; + + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Collection const& m_collection; + RingMap& m_ring_map; + bool m_check_for_orientation; + + + inline assign_visitor(Geometry1 const& g1, Geometry2 const& g2, Collection const& c, + RingMap& map, bool check) + : m_geometry1(g1) + , m_geometry2(g2) + , m_collection(c) + , m_ring_map(map) + , m_check_for_orientation(check) + {} + + template + inline void apply(Item const& outer, Item const& inner, bool first = true) + { + if (first && outer.abs_area < inner.abs_area) + { + // Apply with reversed arguments + apply(inner, outer, false); + return; + } + + if (m_check_for_orientation + || (math::larger(outer.real_area, 0) + && math::smaller(inner.real_area, 0))) + { + ring_info_type& inner_in_map = m_ring_map[inner.id]; + + if (geometry::within(inner_in_map.point, outer.envelope) + && within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection) + ) + { + // Assign a parent if there was no earlier parent, or the newly + // found parent is smaller than the previous one + if (inner_in_map.parent.source_index == -1 + || outer.abs_area < inner_in_map.parent_area) + { + inner_in_map.parent = outer.id; + inner_in_map.parent_area = outer.abs_area; + } + } + } + } +}; + + + + +template +< + typename Geometry1, typename Geometry2, + typename RingCollection, + typename RingMap +> +inline void assign_parents(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RingCollection const& collection, + RingMap& ring_map, + bool check_for_orientation = false) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + + typedef typename RingMap::mapped_type ring_info_type; + typedef typename ring_info_type::point_type point_type; + typedef model::box box_type; + + typedef typename RingMap::iterator map_iterator_type; + + { + typedef ring_info_helper helper; + typedef std::vector vector_type; + typedef typename boost::range_iterator::type vector_iterator_type; + + std::size_t count_total = ring_map.size(); + std::size_t count_positive = 0; + std::size_t index_positive = 0; // only used if count_positive>0 + std::size_t index = 0; + + // Copy to vector (with new approach this might be obsolete as well, using the map directly) + vector_type vector(count_total); + + for (map_iterator_type it = boost::begin(ring_map); + it != boost::end(ring_map); ++it, ++index) + { + vector[index] = helper(it->first, it->second.get_area()); + helper& item = vector[index]; + switch(it->first.source_index) + { + case 0 : + geometry::envelope(get_ring::apply(it->first, geometry1), + item.envelope); + break; + case 1 : + geometry::envelope(get_ring::apply(it->first, geometry2), + item.envelope); + break; + case 2 : + geometry::envelope(get_ring::apply(it->first, collection), + item.envelope); + break; + } + if (item.real_area > 0) + { + count_positive++; + index_positive = index; + } + } + + if (! check_for_orientation) + { + if (count_positive == count_total) + { + // Optimization for only positive rings + // -> no assignment of parents or reversal necessary, ready here. + return; + } + + if (count_positive == 1) + { + // Optimization for one outer ring + // -> assign this as parent to all others (all interior rings) + // In unions, this is probably the most occuring case and gives + // a dramatic improvement (factor 5 for star_comb testcase) + ring_identifier id_of_positive = vector[index_positive].id; + ring_info_type& outer = ring_map[id_of_positive]; + index = 0; + for (vector_iterator_type it = boost::begin(vector); + it != boost::end(vector); ++it, ++index) + { + if (index != index_positive) + { + ring_info_type& inner = ring_map[it->id]; + inner.parent = id_of_positive; + outer.children.push_back(it->id); + } + } + return; + } + } + + assign_visitor + < + Geometry1, Geometry2, + RingCollection, RingMap + > visitor(geometry1, geometry2, collection, ring_map, check_for_orientation); + + geometry::partition + < + box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box + >::apply(vector, visitor); + } + + if (check_for_orientation) + { + for (map_iterator_type it = boost::begin(ring_map); + it != boost::end(ring_map); ++it) + { + if (geometry::math::equals(it->second.get_area(), 0)) + { + it->second.discarded = true; + } + else if (it->second.parent.source_index >= 0 + && math::larger(it->second.get_area(), 0)) + { + const ring_info_type& parent = ring_map[it->second.parent]; + + if (math::larger(parent.area, 0)) + { + // Discard positive inner ring with positive parent + it->second.discarded = true; + } + // Remove parent ID from any positive inner ring + it->second.parent.source_index = -1; + } + else if (it->second.parent.source_index < 0 + && math::smaller(it->second.get_area(), 0)) + { + // Reverse negative ring without parent + it->second.reversed = true; + } + } + } + + // Assign childlist + for (map_iterator_type it = boost::begin(ring_map); + it != boost::end(ring_map); ++it) + { + if (it->second.parent.source_index >= 0) + { + ring_map[it->second.parent].children.push_back(it->first); + } + } +} + + +// Version for one geometry (called by buffer) +template +< + typename Geometry, + typename RingCollection, + typename RingMap +> +inline void assign_parents(Geometry const& geometry, + RingCollection const& collection, + RingMap& ring_map, + bool check_for_orientation) +{ + // Call it with an empty geometry as second geometry (source_id == 1) + // (ring_map should be empty for source_id==1) + + Geometry empty; + assign_parents(geometry, empty, collection, ring_map, check_for_orientation); +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp new file mode 100755 index 0000000000..3640c9b5c6 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp @@ -0,0 +1,203 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP + +#include +#include + +#include + +#include +#include +#include +#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) +# include +# include +#endif + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +inline void clear_visit_info(Turns& turns) +{ + typedef typename boost::range_value::type tp_type; + + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + for (typename boost::range_iterator + < + typename tp_type::container_type + >::type op_it = boost::begin(it->operations); + op_it != boost::end(it->operations); + ++op_it) + { + op_it->visited.clear(); + } + } +} + +struct backtrack_state +{ + bool m_good; + + inline backtrack_state() : m_good(true) {} + inline void reset() { m_good = true; } + inline bool good() const { return m_good; } +}; + + +enum traverse_error_type +{ + traverse_error_none, + traverse_error_no_next_ip_at_start, + traverse_error_no_next_ip, + traverse_error_dead_end_at_start, + traverse_error_dead_end, + traverse_error_visit_again, + traverse_error_endless_loop +}; + +inline std::string traverse_error_string(traverse_error_type error) +{ + switch (error) + { + case traverse_error_none : return ""; + case traverse_error_no_next_ip_at_start : return "No next IP at start"; + case traverse_error_no_next_ip : return "No next IP"; + case traverse_error_dead_end_at_start : return "Dead end at start"; + case traverse_error_dead_end : return "Dead end"; + case traverse_error_visit_again : return "Visit again"; + case traverse_error_endless_loop : return "Endless loop"; + default : return ""; + } + return ""; +} + + +template +< + typename Geometry1, + typename Geometry2 +> +class backtrack_check_self_intersections +{ + struct state : public backtrack_state + { + bool m_checked; + inline state() + : m_checked(true) + {} + }; +public : + typedef state state_type; + + template + static inline void apply(std::size_t size_at_start, + Rings& rings, Ring& ring, + Turns& turns, + typename boost::range_value::type const& turn, + Operation& operation, + traverse_error_type traverse_error, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + state_type& state, + Visitor& visitor + ) + { + visitor.visit_traverse_reject(turns, turn, operation, traverse_error); + + state.m_good = false; + + // Check self-intersections and throw exception if appropriate + if (! state.m_checked) + { + state.m_checked = true; + has_self_intersections(geometry1, robust_policy); + has_self_intersections(geometry2, robust_policy); + } + + // Make bad output clean + rings.resize(size_at_start); + geometry::traits::clear::type>::apply(ring); + + // Reject this as a starting point + operation.visited.set_rejected(); + + // And clear all visit info + clear_visit_info(turns); + } +}; + +#ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT +template +< + typename Geometry1, + typename Geometry2 +> +class backtrack_debug +{ +public : + typedef backtrack_state state_type; + + template + static inline void apply(std::size_t size_at_start, + Rings& rings, typename boost::range_value::type& ring, + Turns& turns, Operation& operation, + std::string const& reason, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + state_type& state + ) + { + std::cout << " REJECT " << reason << std::endl; + + state.m_good = false; + + rings.resize(size_at_start); + ring.clear(); + operation.visited.set_rejected(); + clear_visit_info(turns); + + int c = 0; + for (int i = 0; i < turns.size(); i++) + { + for (int j = 0; j < 2; j++) + { + if (turns[i].operations[j].visited.rejected()) + { + c++; + } + } + } + std::cout << "BACKTRACK (" << reason << " )" + << " " << c << " of " << turns.size() << " rejected" + << std::endl; + std::cout + << geometry::wkt(geometry1) << std::endl + << geometry::wkt(geometry2) << std::endl; + } +}; +#endif // BOOST_GEOMETRY_OVERLAY_REPORT_WKT + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/check_enrich.hpp new file mode 100755 index 0000000000..e400a095d3 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/check_enrich.hpp @@ -0,0 +1,168 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP + + +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +struct meta_turn +{ + int index; + Turn const* turn; + bool handled[2]; + + inline meta_turn(int i, Turn const& t) + : index(i), turn(&t) + { + handled[0] = false; + handled[1] = false; + } +}; + + +template +inline void display(MetaTurn const& meta_turn, std::string const& reason = "") +{ +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + std::cout << meta_turn.index + << "\tMethods: " << method_char(meta_turn.turn->method) + << " operations: " << operation_char(meta_turn.turn->operations[0].operation) + << operation_char(meta_turn.turn->operations[1].operation) + << " travels to " << meta_turn.turn->operations[0].enriched.travels_to_ip_index + << " and " << meta_turn.turn->operations[1].enriched.travels_to_ip_index + //<< " -> " << op_index + << " " << reason + << std::endl; +#endif +} + + +template +inline void check_detailed(MetaTurns& meta_turns, MetaTurn const& meta_turn, + int op_index, int cycle, int start, operation_type for_operation, + bool& error) +{ + display(meta_turn); + int const ip_index = meta_turn.turn->operations[op_index].enriched.travels_to_ip_index; + if (ip_index >= 0) + { + bool found = false; + + if (ip_index == start) + { + display(meta_turns[ip_index], " FINISH"); + return; + } + + // check on continuing, or on same-operation-on-same-geometry + if (! meta_turns[ip_index].handled[op_index] + && (meta_turns[ip_index].turn->operations[op_index].operation == operation_continue + || meta_turns[ip_index].turn->operations[op_index].operation == for_operation) + ) + { + meta_turns[ip_index].handled[op_index] = true; + check_detailed(meta_turns, meta_turns[ip_index], op_index, cycle, start, for_operation, error); + found = true; + } + // check on other geometry + if (! found) + { + int const other_index = 1 - op_index; + if (! meta_turns[ip_index].handled[other_index] + && meta_turns[ip_index].turn->operations[other_index].operation == for_operation) + { + meta_turns[ip_index].handled[other_index] = true; + check_detailed(meta_turns, meta_turns[ip_index], other_index, cycle, start, for_operation, error); + found = true; + } + } + + if (! found) + { + display(meta_turns[ip_index], " STOP"); + error = true; +#ifndef BOOST_GEOMETRY_DEBUG_ENRICH + //std::cout << " STOP"; +#endif + } + } +} + + +template +inline bool check_graph(TurnPoints& turn_points, operation_type for_operation) +{ + typedef typename boost::range_value::type turn_point_type; + + bool error = false; + int index = 0; + + std::vector > meta_turns; + for (typename boost::range_iterator::type + it = boost::begin(turn_points); + it != boost::end(turn_points); + ++it, ++index) + { + meta_turns.push_back(meta_turn(index, *it)); + } + + int cycle = 0; + for (typename boost::range_iterator > > ::type + it = boost::begin(meta_turns); + it != boost::end(meta_turns); + ++it) + { + if (! (it->turn->blocked() || it->turn->discarded)) + { + for (int i = 0 ; i < 2; i++) + { + if (! it->handled[i] + && it->turn->operations[i].operation == for_operation) + { +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + std::cout << "CYCLE " << cycle << std::endl; +#endif + it->handled[i] = true; + check_detailed(meta_turns, *it, i, cycle++, it->index, for_operation, error); +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + std::cout <<" END CYCLE " << it->index << std::endl; +#endif + } + } + } + } + return error; +} + + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp new file mode 100755 index 0000000000..caa3ecbe89 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp @@ -0,0 +1,250 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP + +#include + +#include +#include + +#include + +#include +#include + +namespace boost { namespace geometry +{ + +namespace strategy { namespace intersection +{ + +/*! + \brief Strategy: line clipping algorithm after Liang Barsky + \ingroup overlay + \details The Liang-Barsky line clipping algorithm clips a line with a clipping box. + It is slightly adapted in the sense that it returns which points are clipped + \tparam B input box type of clipping box + \tparam P input/output point-type of segments to be clipped + \note The algorithm is currently only implemented for 2D Cartesian points + \note Though it is implemented in namespace strategy, and theoretically another + strategy could be used, it is not (yet) updated to the general strategy concepts, + and not (yet) splitted into a file in folder strategies + \author Barend Gehrels, and the following recourses + - A tutorial: http://www.skytopia.com/project/articles/compsci/clipping.html + - a German applet (link broken): http://ls7-www.cs.uni-dortmund.de/students/projectgroups/acit/lineclip.shtml +*/ +template +class liang_barsky +{ +private: + typedef model::referring_segment segment_type; + + template + inline bool check_edge(CoordinateType const& p, CoordinateType const& q, CalcType& t1, CalcType& t2) const + { + bool visible = true; + + if(p < 0) + { + CalcType const r = static_cast(q) / p; + if (r > t2) + visible = false; + else if (r > t1) + t1 = r; + } + else if(p > 0) + { + CalcType const r = static_cast(q) / p; + if (r < t1) + visible = false; + else if (r < t2) + t2 = r; + } + else + { + if (q < 0) + visible = false; + } + + return visible; + } + +public: + + inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const + { + typedef typename select_coordinate_type::type coordinate_type; + typedef typename select_most_precise::type calc_type; + + calc_type t1 = 0; + calc_type t2 = 1; + + coordinate_type const dx = get<1, 0>(s) - get<0, 0>(s); + coordinate_type const dy = get<1, 1>(s) - get<0, 1>(s); + + coordinate_type const p1 = -dx; + coordinate_type const p2 = dx; + coordinate_type const p3 = -dy; + coordinate_type const p4 = dy; + + coordinate_type const q1 = get<0, 0>(s) - get(b); + coordinate_type const q2 = get(b) - get<0, 0>(s); + coordinate_type const q3 = get<0, 1>(s) - get(b); + coordinate_type const q4 = get(b) - get<0, 1>(s); + + if (check_edge(p1, q1, t1, t2) // left + && check_edge(p2, q2, t1, t2) // right + && check_edge(p3, q3, t1, t2) // bottom + && check_edge(p4, q4, t1, t2)) // top + { + sp1_clipped = t1 > 0; + sp2_clipped = t2 < 1; + + if (sp2_clipped) + { + set<1, 0>(s, get<0, 0>(s) + t2 * dx); + set<1, 1>(s, get<0, 1>(s) + t2 * dy); + } + + if(sp1_clipped) + { + set<0, 0>(s, get<0, 0>(s) + t1 * dx); + set<0, 1>(s, get<0, 1>(s) + t1 * dy); + } + + return true; + } + + return false; + } + + template + inline void apply(Linestring& line_out, OutputIterator out) const + { + if (!boost::empty(line_out)) + { + *out = line_out; + ++out; + geometry::clear(line_out); + } + } +}; + + +}} // namespace strategy::intersection + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace intersection +{ + +/*! + \brief Clips a linestring with a box + \details A linestring is intersected (clipped) by the specified box + and the resulting linestring, or pieces of linestrings, are sent to the specified output operator. + \tparam OutputLinestring type of the output linestrings + \tparam OutputIterator an output iterator which outputs linestrings + \tparam Linestring linestring-type, for example a vector of points, matching the output-iterator type, + the points should also match the input-iterator type + \tparam Box box type + \tparam Strategy strategy, a clipping strategy which should implement the methods "clip_segment" and "apply" +*/ +template +< + typename OutputLinestring, + typename OutputIterator, + typename Range, + typename RobustPolicy, + typename Box, + typename Strategy +> +OutputIterator clip_range_with_box(Box const& b, Range const& range, + RobustPolicy const&, + OutputIterator out, Strategy const& strategy) +{ + if (boost::begin(range) == boost::end(range)) + { + return out; + } + + typedef typename point_type::type point_type; + + OutputLinestring line_out; + + typedef typename boost::range_iterator::type iterator_type; + iterator_type vertex = boost::begin(range); + for(iterator_type previous = vertex++; + vertex != boost::end(range); + ++previous, ++vertex) + { + point_type p1, p2; + geometry::convert(*previous, p1); + geometry::convert(*vertex, p2); + + // Clip the segment. Five situations: + // 1. Segment is invisible, finish line if any (shouldn't occur) + // 2. Segment is completely visible. Add (p1)-p2 to line + // 3. Point 1 is invisible (clipped), point 2 is visible. Start new line from p1-p2... + // 4. Point 1 is visible, point 2 is invisible (clipped). End the line with ...p2 + // 5. Point 1 and point 2 are both invisible (clipped). Start/finish an independant line p1-p2 + // + // This results in: + // a. if p1 is clipped, start new line + // b. if segment is partly or completely visible, add the segment + // c. if p2 is clipped, end the line + + bool c1 = false; + bool c2 = false; + model::referring_segment s(p1, p2); + + if (!strategy.clip_segment(b, s, c1, c2)) + { + strategy.apply(line_out, out); + } + else + { + // a. If necessary, finish the line and add a start a new one + if (c1) + { + strategy.apply(line_out, out); + } + + // b. Add p1 only if it is the first point, then add p2 + if (boost::empty(line_out)) + { + detail::overlay::append_no_duplicates(line_out, p1, true); + } + detail::overlay::append_no_duplicates(line_out, p2); + + // c. If c2 is clipped, finish the line + if (c2) + { + strategy.apply(line_out, out); + } + } + + } + + // Add last part + strategy.apply(line_out, out); + return out; +} + +}} // namespace detail::intersection +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp new file mode 100755 index 0000000000..01a6a9b07b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp @@ -0,0 +1,49 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2016 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +struct cluster_info +{ + std::set turn_indices; + + bool switch_source; // For clusters with a touch, conform turn_info uu + + //! Number of open spaces (e.g. 2 for touch) + std::size_t open_count; + + inline cluster_info() + : switch_source(false) + , open_count(0) + {} +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP + diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp new file mode 100755 index 0000000000..9deaa692d8 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/convert_ring.hpp @@ -0,0 +1,110 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP + + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +struct convert_ring +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TAG + , (types) + ); +}; + +template<> +struct convert_ring +{ + template + static inline void apply(Destination& destination, Source const& source, + bool append, bool reverse) + { + if (! append) + { + geometry::convert(source, destination); + if (reverse) + { + boost::reverse(destination); + } + } + } +}; + + +template<> +struct convert_ring +{ + template + static inline void apply(Destination& destination, Source const& source, + bool append, bool reverse) + { + if (! append) + { + geometry::convert(source, exterior_ring(destination)); + if (reverse) + { + boost::reverse(exterior_ring(destination)); + } + } + else + { + // Avoid adding interior rings which are invalid + // because of its number of points: + std::size_t const min_num_points + = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + + if (geometry::num_points(source) >= min_num_points) + { + interior_rings(destination).resize( + interior_rings(destination).size() + 1); + geometry::convert(source, interior_rings(destination).back()); + if (reverse) + { + boost::reverse(interior_rings(destination).back()); + } + } + } + } +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp new file mode 100755 index 0000000000..76e9d457b5 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -0,0 +1,399 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace copy_segments +{ + + +template +struct copy_segment_point_range +{ + static inline bool apply(Range const& range, + SegmentIdentifier const& seg_id, int offset, + PointOut& point) + { + typedef typename closeable_view + < + Range const, + closure::value + >::type cview_type; + + typedef typename reversible_view + < + cview_type const, + Reverse ? iterate_reverse : iterate_forward + >::type rview_type; + + cview_type cview(range); + rview_type view(cview); + + typedef typename boost::range_iterator::type iterator; + geometry::ever_circling_iterator it(boost::begin(view), boost::end(view), + boost::begin(view) + seg_id.segment_index, true); + + for (signed_size_type i = 0; i < offset; ++i, ++it) + { + } + + geometry::convert(*it, point); + return true; + } +}; + + +template +struct copy_segment_point_polygon +{ + static inline bool apply(Polygon const& polygon, + SegmentIdentifier const& seg_id, int offset, + PointOut& point) + { + // Call ring-version with the right ring + return copy_segment_point_range + < + typename geometry::ring_type::type, + Reverse, + SegmentIdentifier, + PointOut + >::apply + ( + seg_id.ring_index < 0 + ? geometry::exterior_ring(polygon) + : range::at(geometry::interior_rings(polygon), seg_id.ring_index), + seg_id, offset, + point + ); + } +}; + + +template +struct copy_segment_point_box +{ + static inline bool apply(Box const& box, + SegmentIdentifier const& seg_id, int offset, + PointOut& point) + { + signed_size_type index = seg_id.segment_index; + for (int i = 0; i < offset; i++) + { + index++; + } + + boost::array::type, 4> bp; + assign_box_corners_oriented(box, bp); + point = bp[index % 4]; + return true; + } +}; + + +template +< + typename MultiGeometry, + typename SegmentIdentifier, + typename PointOut, + typename Policy +> +struct copy_segment_point_multi +{ + static inline bool apply(MultiGeometry const& multi, + SegmentIdentifier const& seg_id, int offset, + PointOut& point) + { + + BOOST_GEOMETRY_ASSERT + ( + seg_id.multi_index >= 0 + && seg_id.multi_index < int(boost::size(multi)) + ); + + // Call the single-version + return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point); + } +}; + + +}} // namespace detail::copy_segments +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename Tag, + typename GeometryIn, + bool Reverse, + typename SegmentIdentifier, + typename PointOut +> +struct copy_segment_point +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (types) + ); +}; + + +template +struct copy_segment_point + : detail::copy_segments::copy_segment_point_range + < + LineString, Reverse, SegmentIdentifier, PointOut + > +{}; + + +template +struct copy_segment_point + : detail::copy_segments::copy_segment_point_range + < + Ring, Reverse, SegmentIdentifier, PointOut + > +{}; + +template +struct copy_segment_point + : detail::copy_segments::copy_segment_point_polygon + < + Polygon, Reverse, SegmentIdentifier, PointOut + > +{}; + + +template +struct copy_segment_point + : detail::copy_segments::copy_segment_point_box + < + Box, Reverse, SegmentIdentifier, PointOut + > +{}; + + +template +< + typename MultiGeometry, + bool Reverse, + typename SegmentIdentifier, + typename PointOut +> +struct copy_segment_point + < + multi_polygon_tag, + MultiGeometry, + Reverse, + SegmentIdentifier, + PointOut + > + : detail::copy_segments::copy_segment_point_multi + < + MultiGeometry, + SegmentIdentifier, + PointOut, + detail::copy_segments::copy_segment_point_polygon + < + typename boost::range_value::type, + Reverse, + SegmentIdentifier, + PointOut + > + > +{}; + +template +< + typename MultiGeometry, + bool Reverse, + typename SegmentIdentifier, + typename PointOut +> +struct copy_segment_point + < + multi_linestring_tag, + MultiGeometry, + Reverse, + SegmentIdentifier, + PointOut + > + : detail::copy_segments::copy_segment_point_multi + < + MultiGeometry, + SegmentIdentifier, + PointOut, + detail::copy_segments::copy_segment_point_range + < + typename boost::range_value::type, + Reverse, + SegmentIdentifier, + PointOut + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + + + +/*! + \brief Helper function, copies a point from a segment + \ingroup overlay + */ +template +inline bool copy_segment_point(Geometry const& geometry, + SegmentIdentifier const& seg_id, int offset, + PointOut& point_out) +{ + concepts::check(); + + return dispatch::copy_segment_point + < + typename tag::type, + Geometry, + Reverse, + SegmentIdentifier, + PointOut + >::apply(geometry, seg_id, offset, point_out); +} + + +/*! + \brief Helper function, to avoid the same construct several times, + copies a point, based on a source-index and two geometries + \ingroup overlay + */ +template +< + bool Reverse1, bool Reverse2, + typename Geometry1, typename Geometry2, + typename SegmentIdentifier, + typename PointOut +> +inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2, + SegmentIdentifier const& seg_id, int offset, + PointOut& point_out) +{ + concepts::check(); + concepts::check(); + + BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1); + + if (seg_id.source_index == 0) + { + return dispatch::copy_segment_point + < + typename tag::type, + Geometry1, + Reverse1, + SegmentIdentifier, + PointOut + >::apply(geometry1, seg_id, offset, point_out); + } + else if (seg_id.source_index == 1) + { + return dispatch::copy_segment_point + < + typename tag::type, + Geometry2, + Reverse2, + SegmentIdentifier, + PointOut + >::apply(geometry2, seg_id, offset, point_out); + } + // Exception? + return false; +} + + +/*! + \brief Helper function, to avoid the same construct several times, + copies a point, based on a source-index and two geometries + \ingroup overlay + */ +template +< + bool Reverse1, bool Reverse2, + typename Geometry1, typename Geometry2, + typename SegmentIdentifier, + typename PointOut +> +inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2, + SegmentIdentifier const& seg_id, + PointOut& point1, PointOut& point2) +{ + concepts::check(); + concepts::check(); + + return copy_segment_point(geometry1, geometry2, seg_id, 0, point1) + && copy_segment_point(geometry1, geometry2, seg_id, 1, point2); +} + +/*! + \brief Helper function, copies three points: two from the specified segment + (from, to) and the next one + \ingroup overlay + */ +template +< + bool Reverse1, bool Reverse2, + typename Geometry1, typename Geometry2, + typename SegmentIdentifier, + typename PointOut +> +inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2, + SegmentIdentifier const& seg_id, + PointOut& point1, PointOut& point2, PointOut& point3) +{ + concepts::check(); + concepts::check(); + + return copy_segment_point(geometry1, geometry2, seg_id, 0, point1) + && copy_segment_point(geometry1, geometry2, seg_id, 1, point2) + && copy_segment_point(geometry1, geometry2, seg_id, 2, point3); +} + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp new file mode 100755 index 0000000000..638c74acb0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -0,0 +1,365 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace copy_segments +{ + + +template +struct copy_segments_ring +{ + template + < + typename Ring, + typename SegmentIdentifier, + typename RobustPolicy, + typename RangeOut + > + static inline void apply(Ring const& ring, + SegmentIdentifier const& seg_id, + signed_size_type to_index, + RobustPolicy const& robust_policy, + RangeOut& current_output) + { + typedef typename closeable_view + < + Ring const, + closure::value + >::type cview_type; + + typedef typename reversible_view + < + cview_type const, + Reverse ? iterate_reverse : iterate_forward + >::type rview_type; + + typedef typename boost::range_iterator::type iterator; + typedef geometry::ever_circling_iterator ec_iterator; + + + cview_type cview(ring); + rview_type view(cview); + + // The problem: sometimes we want to from "3" to "2" + // -> end = "3" -> end == begin + // This is not convenient with iterators. + + // So we use the ever-circling iterator and determine when to step out + + signed_size_type const from_index = seg_id.segment_index + 1; + + // Sanity check + BOOST_GEOMETRY_ASSERT(from_index < static_cast(boost::size(view))); + + ec_iterator it(boost::begin(view), boost::end(view), + boost::begin(view) + from_index); + + // [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK + // [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK + // [1..1], travel the whole ring round + signed_size_type const count = from_index <= to_index + ? to_index - from_index + 1 + : static_cast(boost::size(view)) + - from_index + to_index + 1; + + for (signed_size_type i = 0; i < count; ++i, ++it) + { + detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy); + } + } +}; + +template +class copy_segments_linestring +{ +private: + // remove spikes + template + static inline void append_to_output(RangeOut& current_output, + Point const& point, + RobustPolicy const& robust_policy, + boost::true_type const&) + { + detail::overlay::append_no_dups_or_spikes(current_output, point, + robust_policy); + } + + // keep spikes + template + static inline void append_to_output(RangeOut& current_output, + Point const& point, + RobustPolicy const&, + boost::false_type const&) + { + detail::overlay::append_no_duplicates(current_output, point); + } + +public: + template + < + typename LineString, + typename SegmentIdentifier, + typename RobustPolicy, + typename RangeOut + > + static inline void apply(LineString const& ls, + SegmentIdentifier const& seg_id, + signed_size_type to_index, + RobustPolicy const& robust_policy, + RangeOut& current_output) + { + signed_size_type const from_index = seg_id.segment_index + 1; + + // Sanity check + if ( from_index > to_index + || from_index < 0 + || to_index >= static_cast(boost::size(ls)) ) + { + return; + } + + signed_size_type const count = to_index - from_index + 1; + + typename boost::range_iterator::type + it = boost::begin(ls) + from_index; + + for (signed_size_type i = 0; i < count; ++i, ++it) + { + append_to_output(current_output, *it, robust_policy, + boost::integral_constant()); + } + } +}; + +template +struct copy_segments_polygon +{ + template + < + typename Polygon, + typename SegmentIdentifier, + typename RobustPolicy, + typename RangeOut + > + static inline void apply(Polygon const& polygon, + SegmentIdentifier const& seg_id, + signed_size_type to_index, + RobustPolicy const& robust_policy, + RangeOut& current_output) + { + // Call ring-version with the right ring + copy_segments_ring::apply + ( + seg_id.ring_index < 0 + ? geometry::exterior_ring(polygon) + : range::at(geometry::interior_rings(polygon), seg_id.ring_index), + seg_id, to_index, + robust_policy, + current_output + ); + } +}; + + +template +struct copy_segments_box +{ + template + < + typename Box, + typename SegmentIdentifier, + typename RobustPolicy, + typename RangeOut + > + static inline void apply(Box const& box, + SegmentIdentifier const& seg_id, + signed_size_type to_index, + RobustPolicy const& robust_policy, + RangeOut& current_output) + { + signed_size_type index = seg_id.segment_index + 1; + BOOST_GEOMETRY_ASSERT(index < 5); + + signed_size_type const count = index <= to_index + ? to_index - index + 1 + : 5 - index + to_index + 1; + + // Create array of points, the fifth one closes it + boost::array::type, 5> bp; + assign_box_corners_oriented(box, bp); + bp[4] = bp[0]; + + // (possibly cyclic) copy to output + // (see comments in ring-version) + for (signed_size_type i = 0; i < count; i++, index++) + { + detail::overlay::append_no_dups_or_spikes(current_output, + bp[index % 5], robust_policy); + + } + } +}; + + +template +struct copy_segments_multi +{ + template + < + typename MultiGeometry, + typename SegmentIdentifier, + typename RobustPolicy, + typename RangeOut + > + static inline void apply(MultiGeometry const& multi_geometry, + SegmentIdentifier const& seg_id, + signed_size_type to_index, + RobustPolicy const& robust_policy, + RangeOut& current_output) + { + + BOOST_GEOMETRY_ASSERT + ( + seg_id.multi_index >= 0 + && static_cast(seg_id.multi_index) < boost::size(multi_geometry) + ); + + // Call the single-version + Policy::apply(range::at(multi_geometry, seg_id.multi_index), + seg_id, to_index, + robust_policy, + current_output); + } +}; + + +}} // namespace detail::copy_segments +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Tag, + bool Reverse +> +struct copy_segments : not_implemented +{}; + + +template +struct copy_segments + : detail::copy_segments::copy_segments_ring +{}; + + +template +struct copy_segments + : detail::copy_segments::copy_segments_linestring +{}; + +template +struct copy_segments + : detail::copy_segments::copy_segments_polygon +{}; + + +template +struct copy_segments + : detail::copy_segments::copy_segments_box +{}; + + +template +struct copy_segments + : detail::copy_segments::copy_segments_multi + < + detail::copy_segments::copy_segments_polygon + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! + \brief Copy segments from a geometry, starting with the specified segment (seg_id) + until the specified index (to_index) + \ingroup overlay + */ +template +< + bool Reverse, + typename Geometry, + typename SegmentIdentifier, + typename RobustPolicy, + typename RangeOut +> +inline void copy_segments(Geometry const& geometry, + SegmentIdentifier const& seg_id, + signed_size_type to_index, + RobustPolicy const& robust_policy, + RangeOut& range_out) +{ + concepts::check(); + + dispatch::copy_segments + < + typename tag::type, + Reverse + >::apply(geometry, seg_id, to_index, robust_policy, range_out); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp new file mode 100755 index 0000000000..68a63a3620 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp @@ -0,0 +1,66 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP + +#include +#include + + +namespace boost { namespace geometry +{ + +inline char method_char(detail::overlay::method_type const& method) +{ + using namespace detail::overlay; + switch(method) + { + case method_none : return '-'; + case method_disjoint : return 'd'; + case method_crosses : return 'i'; + case method_touch : return 't'; + case method_touch_interior : return 'm'; + case method_collinear : return 'c'; + case method_equal : return 'e'; + case method_error : return '!'; + default : return '?'; + } +} + +inline char operation_char(detail::overlay::operation_type const& operation) +{ + using namespace detail::overlay; + switch(operation) + { + case operation_none : return '-'; + case operation_union : return 'u'; + case operation_intersection : return 'i'; + case operation_blocked : return 'x'; + case operation_continue : return 'c'; + case operation_opposite : return 'o'; + default : return '?'; + } +} + +inline char visited_char(detail::overlay::visit_info const& v) +{ + if (v.rejected()) return 'R'; + if (v.started()) return 's'; + if (v.visited()) return 'v'; + if (v.none()) return '-'; + if (v.finished()) return 'f'; + return '?'; +} + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/do_reverse.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/do_reverse.hpp new file mode 100755 index 0000000000..65b45ef17b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/do_reverse.hpp @@ -0,0 +1,47 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DO_REVERSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DO_REVERSE_HPP + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +// Metafunction helper for intersection and union +template +struct do_reverse {}; + +template <> +struct do_reverse : boost::false_type {}; + +template <> +struct do_reverse : boost::true_type {}; + +template <> +struct do_reverse : boost::true_type {}; + +template <> +struct do_reverse : boost::false_type {}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DO_REVERSE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp new file mode 100755 index 0000000000..116785b0f8 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -0,0 +1,346 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP + +#include +#include +#include +#include +#include + +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH +# include +# include +# include +# define BOOST_GEOMETRY_DEBUG_IDENTIFIER +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH +# include +#endif + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +// Sorts IP-s of this ring on segment-identifier, and if on same segment, +// on distance. +// Then assigns for each IP which is the next IP on this segment, +// plus the vertex-index to travel to, plus the next IP +// (might be on another segment) +template +< + bool Reverse1, bool Reverse2, + typename Operations, + typename Turns, + typename Geometry1, typename Geometry2, + typename RobustPolicy, + typename Strategy +> +inline void enrich_sort(Operations& operations, + Turns const& turns, + operation_type for_operation, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Strategy const& /*strategy*/) +{ + std::sort(boost::begin(operations), + boost::end(operations), + less_by_segment_ratio + < + Turns, + typename boost::range_value::type, + Geometry1, Geometry2, + RobustPolicy, + Reverse1, Reverse2 + >(turns, for_operation, geometry1, geometry2, robust_policy)); +} + + +template +inline void enrich_assign(Operations& operations, Turns& turns) +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type op_type; + typedef typename boost::range_iterator::type iterator_type; + + + if (operations.size() > 0) + { + // Assign travel-to-vertex/ip index for each turning point. + // Iterator "next" is circular + + geometry::ever_circling_range_iterator next(operations); + ++next; + + for (iterator_type it = boost::begin(operations); + it != boost::end(operations); ++it) + { + turn_type& turn = turns[it->turn_index]; + op_type& op = turn.operations[it->operation_index]; + + // Normal behaviour: next should point at next turn: + if (it->turn_index == next->turn_index) + { + ++next; + } + + // Cluster behaviour: next should point after cluster, unless + // their seg_ids are not the same + while (turn.cluster_id != -1 + && it->turn_index != next->turn_index + && turn.cluster_id == turns[next->turn_index].cluster_id + && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id) + { + ++next; + } + + turn_type const& next_turn = turns[next->turn_index]; + op_type const& next_op = next_turn.operations[next->operation_index]; + + op.enriched.travels_to_ip_index + = static_cast(next->turn_index); + op.enriched.travels_to_vertex_index + = next->subject->seg_id.segment_index; + + if (op.seg_id.segment_index == next_op.seg_id.segment_index + && op.fraction < next_op.fraction) + { + // Next turn is located further on same segment + // assign next_ip_index + // (this is one not circular therefore fraction is considered) + op.enriched.next_ip_index = static_cast(next->turn_index); + } + } + } + + // DEBUG +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + { + for (iterator_type it = boost::begin(operations); + it != boost::end(operations); + ++it) + { + op_type& op = turns[it->turn_index] + .operations[it->operation_index]; + + std::cout << it->turn_index + << " cl=" << turns[it->turn_index].cluster_id + << " meth=" << method_char(turns[it->turn_index].method) + << " seg=" << op.seg_id + << " dst=" << op.fraction // needs define + << " op=" << operation_char(turns[it->turn_index].operations[0].operation) + << operation_char(turns[it->turn_index].operations[1].operation) + << " (" << operation_char(op.operation) << ")" + << " nxt=" << op.enriched.next_ip_index + << " / " << op.enriched.travels_to_ip_index + << " [vx " << op.enriched.travels_to_vertex_index << "]" + << std::boolalpha << turns[it->turn_index].discarded + << std::endl; + ; + } + } +#endif + // END DEBUG + +} + + +template +inline void create_map(Turns const& turns, + detail::overlay::operation_type for_operation, + MappedVector& mapped_vector) +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::container_type container_type; + typedef typename MappedVector::mapped_type mapped_type; + typedef typename boost::range_value::type indexed_type; + + std::size_t index = 0; + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it, ++index) + { + // Add all (non discarded) operations on this ring + // Blocked operations or uu on clusters (for intersection) + // should be included, to block potential paths in clusters + turn_type const& turn = *it; + if (turn.discarded) + { + continue; + } + + if (for_operation == operation_intersection + && turn.cluster_id == -1 + && turn.both(operation_union)) + { + // Only include uu turns if part of cluster (to block potential paths), + // otherwise they can block possibly viable paths + continue; + } + + std::size_t op_index = 0; + for (typename boost::range_iterator::type + op_it = boost::begin(turn.operations); + op_it != boost::end(turn.operations); + ++op_it, ++op_index) + { + ring_identifier const ring_id + ( + op_it->seg_id.source_index, + op_it->seg_id.multi_index, + op_it->seg_id.ring_index + ); + mapped_vector[ring_id].push_back + ( + indexed_type(index, op_index, *op_it, + it->operations[1 - op_index].seg_id) + ); + } + } +} + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + + +/*! +\brief All intersection points are enriched with successor information +\ingroup overlay +\tparam Turns type of intersection container + (e.g. vector of "intersection/turn point"'s) +\tparam Clusters type of cluster container +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Strategy side strategy type +\param turns container containing intersection points +\param clusters container containing clusters +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param robust_policy policy to handle robustness issues +\param strategy strategy + */ +template +< + bool Reverse1, bool Reverse2, + overlay_type OverlayType, + typename Turns, + typename Clusters, + typename Geometry1, typename Geometry2, + typename RobustPolicy, + typename Strategy +> +inline void enrich_intersection_points(Turns& turns, + Clusters& clusters, + Geometry1 const& geometry1, Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Strategy const& strategy) +{ + static const detail::overlay::operation_type for_operation + = detail::overlay::operation_from_overlay::value; + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type op_type; + typedef detail::overlay::indexed_turn_operation + < + op_type + > indexed_turn_operation; + + typedef std::map + < + ring_identifier, + std::vector + > mapped_vector_type; + + bool const has_colocations + = detail::overlay::handle_colocations(turns, + clusters, geometry1, geometry2); + + // Discard none turns, if any + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + if (it->both(detail::overlay::operation_none)) + { + it->discarded = true; + } + } + + // Create a map of vectors of indexed operation-types to be able + // to sort intersection points PER RING + mapped_vector_type mapped_vector; + + detail::overlay::create_map(turns, for_operation, mapped_vector); + + // No const-iterator; contents of mapped copy is temporary, + // and changed by enrich + for (typename mapped_vector_type::iterator mit + = mapped_vector.begin(); + mit != mapped_vector.end(); + ++mit) + { +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + std::cout << "ENRICH-sort Ring " + << mit->first << std::endl; +#endif + detail::overlay::enrich_sort( + mit->second, turns, for_operation, + geometry1, geometry2, + robust_policy, strategy); + } + + for (typename mapped_vector_type::iterator mit + = mapped_vector.begin(); + mit != mapped_vector.end(); + ++mit) + { +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + std::cout << "ENRICH-assign Ring " + << mit->first << std::endl; +#endif + detail::overlay::enrich_assign(mit->second, turns); + } + + if (has_colocations) + { + detail::overlay::gather_cluster_properties( + clusters, turns, for_operation, geometry1, geometry2); + } + +#ifdef BOOST_GEOMETRY_DEBUG_ENRICH + //detail::overlay::check_graph(turns, for_operation); +#endif + +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp new file mode 100755 index 0000000000..141bbf8f2e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp @@ -0,0 +1,71 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +/*! +\brief Keeps info to enrich intersection info (per source) +\details Class to keep information necessary for traversal phase (a phase + of the overlay process). The information is gathered during the + enrichment phase + */ +template +struct enrichment_info +{ + inline enrichment_info() + : travels_to_vertex_index(-1) + , travels_to_ip_index(-1) + , next_ip_index(-1) + , startable(true) + , count_left(0) + , count_right(0) + , zone(-1) + {} + + // vertex to which is free travel after this IP, + // so from "segment_index+1" to "travels_to_vertex_index", without IP-s, + // can be -1 + signed_size_type travels_to_vertex_index; + + // same but now IP index, so "next IP index" but not on THIS segment + signed_size_type travels_to_ip_index; + + // index of next IP on this segment, -1 if there is no one + signed_size_type next_ip_index; + + bool startable; // Can be used to start in traverse + + // Counts if polygons left/right of this operation + std::size_t count_left; + std::size_t count_right; + signed_size_type zone; // open zone, in cluster +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/follow.hpp new file mode 100755 index 0000000000..1ac07b248e --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -0,0 +1,522 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +namespace following +{ + +template +static inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op) +{ + // (Blocked means: blocked for polygon/polygon intersection, because + // they are reversed. But for polygon/line it is similar to continue) + return op.operation == operation_intersection + || op.operation == operation_continue + || op.operation == operation_blocked + ; +} + +template +< + typename Turn, + typename Operation, + typename LineString, + typename Polygon +> +static inline bool last_covered_by(Turn const& turn, Operation const& op, + LineString const& linestring, Polygon const& polygon) +{ + // Check any point between the this one and the first IP + typedef typename geometry::point_type::type point_type; + point_type point_in_between; + detail::point_on_border::midpoint_helper + < + point_type, + 0, dimension::value + >::apply(point_in_between, *(::boost::begin(linestring) + op.seg_id.segment_index), turn.point); + + return geometry::covered_by(point_in_between, polygon); +} + + +template +< + typename Turn, + typename Operation, + typename LineString, + typename Polygon +> +static inline bool is_leaving(Turn const& turn, Operation const& op, + bool entered, bool first, + LineString const& linestring, Polygon const& polygon) +{ + if (op.operation == operation_union) + { + return entered + || turn.method == method_crosses + || (first && last_covered_by(turn, op, linestring, polygon)) + ; + } + return false; +} + + +template +< + typename Turn, + typename Operation, + typename LineString, + typename Polygon +> +static inline bool is_staying_inside(Turn const& turn, Operation const& op, + bool entered, bool first, + LineString const& linestring, Polygon const& polygon) +{ + if (turn.method == method_crosses) + { + // The normal case, this is completely covered with entering/leaving + // so stay out of this time consuming "covered_by" + return false; + } + + if (is_entering(turn, op)) + { + return entered || (first && last_covered_by(turn, op, linestring, polygon)); + } + + return false; +} + +template +< + typename Turn, + typename Operation, + typename Linestring, + typename Polygon +> +static inline bool was_entered(Turn const& turn, Operation const& op, bool first, + Linestring const& linestring, Polygon const& polygon) +{ + if (first && (turn.method == method_collinear || turn.method == method_equal)) + { + return last_covered_by(turn, op, linestring, polygon); + } + return false; +} + + +// Template specialization structure to call the right actions for the right type +template +struct action_selector +{ + // If you get here the overlay type is not intersection or difference + // BOOST_MPL_ASSERT(false); +}; + +// Specialization for intersection, containing the implementation +template +struct action_selector +{ + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation, + typename RobustPolicy + > + static inline void enter(LineStringOut& current_piece, + LineString const& , + segment_identifier& segment_id, + signed_size_type , Point const& point, + Operation const& operation, + RobustPolicy const& , + OutputIterator& ) + { + // On enter, append the intersection point and remember starting point + // TODO: we don't check on spikes for linestrings (?). Consider this. + detail::overlay::append_no_duplicates(current_piece, point); + segment_id = operation.seg_id; + } + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation, + typename RobustPolicy + > + static inline void leave(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + signed_size_type index, Point const& point, + Operation const& , + RobustPolicy const& robust_policy, + OutputIterator& out) + { + // On leave, copy all segments from starting point, append the intersection point + // and add the output piece + detail::copy_segments::copy_segments_linestring + < + false, RemoveSpikes + >::apply(linestring, segment_id, index, robust_policy, current_piece); + detail::overlay::append_no_duplicates(current_piece, point); + if (::boost::size(current_piece) > 1) + { + *out++ = current_piece; + } + + geometry::clear(current_piece); + } + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation + > + static inline void isolated_point(LineStringOut&, + LineString const&, + segment_identifier&, + signed_size_type, Point const& point, + Operation const& , OutputIterator& out) + { + LineStringOut isolated_point_ls; + geometry::append(isolated_point_ls, point); + +#ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS + geometry::append(isolated_point_ls, point); +#endif // BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS + + *out++ = isolated_point_ls; + } + + static inline bool is_entered(bool entered) + { + return entered; + } + + template + < + typename Point, + typename Geometry, + typename RobustPolicy + > + static inline bool included(Point const& point, + Geometry const& geometry, + RobustPolicy const& ) + { + return geometry::covered_by(point, geometry); + } + +}; + +// Specialization for difference, which reverses these actions +template +struct action_selector +{ + typedef action_selector normal_action; + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation, + typename RobustPolicy + > + static inline void enter(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + signed_size_type index, Point const& point, + Operation const& operation, + RobustPolicy const& robust_policy, + OutputIterator& out) + { + normal_action::leave(current_piece, linestring, segment_id, index, + point, operation, robust_policy, out); + } + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation, + typename RobustPolicy + > + static inline void leave(LineStringOut& current_piece, + LineString const& linestring, + segment_identifier& segment_id, + signed_size_type index, Point const& point, + Operation const& operation, + RobustPolicy const& robust_policy, + OutputIterator& out) + { + normal_action::enter(current_piece, linestring, segment_id, index, + point, operation, robust_policy, out); + } + + template + < + typename OutputIterator, + typename LineStringOut, + typename LineString, + typename Point, + typename Operation + > + static inline void isolated_point(LineStringOut&, + LineString const&, + segment_identifier&, + signed_size_type, Point const&, + Operation const&, OutputIterator&) + { + } + + static inline bool is_entered(bool entered) + { + return ! normal_action::is_entered(entered); + } + + template + < + typename Point, + typename Geometry, + typename RobustPolicy + > + static inline bool included(Point const& point, + Geometry const& geometry, + RobustPolicy const& robust_policy) + { + return ! normal_action::included(point, geometry, robust_policy); + } + +}; + +} + +/*! +\brief Follows a linestring from intersection point to intersection point, outputting which + is inside, or outside, a ring or polygon +\ingroup overlay + */ +template +< + typename LineStringOut, + typename LineString, + typename Polygon, + overlay_type OverlayType, + bool RemoveSpikes = true +> +class follow +{ + + template + struct sort_on_segment + { + // In case of turn point at the same location, we want to have continue/blocked LAST + // because that should be followed (intersection) or skipped (difference). + inline int operation_order(Turn const& turn) const + { + operation_type const& operation = turn.operations[0].operation; + switch(operation) + { + case operation_opposite : return 0; + case operation_none : return 0; + case operation_union : return 1; + case operation_intersection : return 2; + case operation_blocked : return 3; + case operation_continue : return 4; + } + return -1; + }; + + inline bool use_operation(Turn const& left, Turn const& right) const + { + // If they are the same, OK. + return operation_order(left) < operation_order(right); + } + + inline bool use_distance(Turn const& left, Turn const& right) const + { + return left.operations[0].fraction == right.operations[0].fraction + ? use_operation(left, right) + : left.operations[0].fraction < right.operations[0].fraction + ; + } + + inline bool operator()(Turn const& left, Turn const& right) const + { + segment_identifier const& sl = left.operations[0].seg_id; + segment_identifier const& sr = right.operations[0].seg_id; + + return sl == sr + ? use_distance(left, right) + : sl < sr + ; + + } + }; + + + +public : + + template + < + typename Point, + typename Geometry, + typename RobustPolicy + > + static inline bool included(Point const& point, + Geometry const& geometry, + RobustPolicy const& robust_policy) + { + return following::action_selector + < + OverlayType, RemoveSpikes + >::included(point, geometry, robust_policy); + } + + template + < + typename Turns, + typename OutputIterator, + typename RobustPolicy + > + static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon, + detail::overlay::operation_type , // TODO: this parameter might be redundant + Turns& turns, + RobustPolicy const& robust_policy, + OutputIterator out) + { + typedef typename boost::range_iterator::type turn_iterator; + typedef typename boost::range_value::type turn_type; + typedef typename boost::range_iterator + < + typename turn_type::container_type + >::type turn_operation_iterator_type; + + typedef following::action_selector action; + + // Sort intersection points on segments-along-linestring, and distance + // (like in enrich is done for poly/poly) + std::sort(boost::begin(turns), boost::end(turns), sort_on_segment()); + + LineStringOut current_piece; + geometry::segment_identifier current_segment_id(0, -1, -1, -1); + + // Iterate through all intersection points (they are ordered along the line) + bool entered = false; + bool first = true; + for (turn_iterator it = boost::begin(turns); it != boost::end(turns); ++it) + { + turn_operation_iterator_type iit = boost::begin(it->operations); + + if (following::was_entered(*it, *iit, first, linestring, polygon)) + { + debug_traverse(*it, *iit, "-> Was entered"); + entered = true; + } + + if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon)) + { + debug_traverse(*it, *iit, "-> Staying inside"); + + entered = true; + } + else if (following::is_entering(*it, *iit)) + { + debug_traverse(*it, *iit, "-> Entering"); + + entered = true; + action::enter(current_piece, linestring, current_segment_id, + iit->seg_id.segment_index, it->point, *iit, + robust_policy, + out); + } + else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon)) + { + debug_traverse(*it, *iit, "-> Leaving"); + + entered = false; + action::leave(current_piece, linestring, current_segment_id, + iit->seg_id.segment_index, it->point, *iit, + robust_policy, + out); + } + first = false; + } + + if (action::is_entered(entered)) + { + detail::copy_segments::copy_segments_linestring + < + false, RemoveSpikes + >::apply(linestring, + current_segment_id, + static_cast(boost::size(linestring) - 1), + robust_policy, + current_piece); + } + + // Output the last one, if applicable + if (::boost::size(current_piece) > 1) + { + *out++ = current_piece; + } + return out; + } + +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp new file mode 100755 index 0000000000..a85597a27c --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp @@ -0,0 +1,543 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +namespace following { namespace linear +{ + + + + +// follower for linear/linear geometries set operations + +template +static inline bool is_entering(Turn const& turn, + Operation const& operation) +{ + if ( turn.method != method_touch && turn.method != method_touch_interior ) + { + return false; + } + return operation.operation == operation_intersection; +} + + + +template +static inline bool is_staying_inside(Turn const& turn, + Operation const& operation, + bool entered) +{ + if ( !entered ) + { + return false; + } + + if ( turn.method != method_equal && turn.method != method_collinear ) + { + return false; + } + return operation.operation == operation_continue; +} + + + +template +static inline bool is_leaving(Turn const& turn, + Operation const& operation, + bool entered) +{ + if ( !entered ) + { + return false; + } + + if ( turn.method != method_touch + && turn.method != method_touch_interior + && turn.method != method_equal + && turn.method != method_collinear ) + { + return false; + } + + if ( operation.operation == operation_blocked ) + { + return true; + } + + if ( operation.operation != operation_union ) + { + return false; + } + + return operation.is_collinear; +} + + + +template +static inline bool is_isolated_point(Turn const& turn, + Operation const& operation, + bool entered) +{ + if ( entered ) + { + return false; + } + + if ( turn.method == method_none ) + { + BOOST_GEOMETRY_ASSERT( operation.operation == operation_continue ); + return true; + } + + if ( turn.method == method_crosses ) + { + return true; + } + + if ( turn.method != method_touch && turn.method != method_touch_interior ) + { + return false; + } + + if ( operation.operation == operation_blocked ) + { + return true; + } + + if ( operation.operation != operation_union ) + { + return false; + } + + return !operation.is_collinear; +} + + + + + + + + + +template +< + typename LinestringOut, + typename Linestring, + typename Linear, + overlay_type OverlayType, + bool FollowIsolatedPoints, + bool FollowContinueTurns +> +class follow_linestring_linear_linestring +{ +protected: + // allow spikes (false indicates: do not remove spikes) + typedef following::action_selector action; + + template + < + typename TurnIterator, + typename TurnOperationIterator, + typename SegmentIdentifier, + typename OutputIterator + > + static inline OutputIterator + process_turn(TurnIterator it, + TurnOperationIterator op_it, + bool& entered, + std::size_t& enter_count, + Linestring const& linestring, + LinestringOut& current_piece, + SegmentIdentifier& current_segment_id, + OutputIterator oit) + { + // We don't rescale linear/linear + detail::no_rescale_policy robust_policy; + + if ( is_entering(*it, *op_it) ) + { + detail::turns::debug_turn(*it, *op_it, "-> Entering"); + + entered = true; + if ( enter_count == 0 ) + { + action::enter(current_piece, linestring, + current_segment_id, + op_it->seg_id.segment_index, + it->point, *op_it, robust_policy, oit); + } + ++enter_count; + } + else if ( is_leaving(*it, *op_it, entered) ) + { + detail::turns::debug_turn(*it, *op_it, "-> Leaving"); + + --enter_count; + if ( enter_count == 0 ) + { + entered = false; + action::leave(current_piece, linestring, + current_segment_id, + op_it->seg_id.segment_index, + it->point, *op_it, robust_policy, oit); + } + } + else if ( FollowIsolatedPoints + && is_isolated_point(*it, *op_it, entered) ) + { + detail::turns::debug_turn(*it, *op_it, "-> Isolated point"); + + action::isolated_point(current_piece, linestring, + current_segment_id, + op_it->seg_id.segment_index, + it->point, *op_it, oit); + } + else if ( FollowContinueTurns + && is_staying_inside(*it, *op_it, entered) ) + { + detail::turns::debug_turn(*it, *op_it, "-> Staying inside"); + + entered = true; + } + return oit; + } + + template + < + typename SegmentIdentifier, + typename OutputIterator + > + static inline OutputIterator + process_end(bool entered, + Linestring const& linestring, + SegmentIdentifier const& current_segment_id, + LinestringOut& current_piece, + OutputIterator oit) + { + if ( action::is_entered(entered) ) + { + // We don't rescale linear/linear + detail::no_rescale_policy robust_policy; + + detail::copy_segments::copy_segments_linestring + < + false, false // do not reverse; do not remove spikes + >::apply(linestring, + current_segment_id, + static_cast(boost::size(linestring) - 1), + robust_policy, + current_piece); + } + + // Output the last one, if applicable + if (::boost::size(current_piece) > 1) + { + *oit++ = current_piece; + } + + return oit; + } + +public: + template + static inline OutputIterator + apply(Linestring const& linestring, Linear const&, + TurnIterator first, TurnIterator beyond, + OutputIterator oit) + { + // Iterate through all intersection points (they are + // ordered along the each line) + + LinestringOut current_piece; + geometry::segment_identifier current_segment_id(0, -1, -1, -1); + + bool entered = false; + std::size_t enter_count = 0; + + for (TurnIterator it = first; it != beyond; ++it) + { + oit = process_turn(it, boost::begin(it->operations), + entered, enter_count, + linestring, + current_piece, current_segment_id, + oit); + } + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + if (enter_count != 0) + { + throw inconsistent_turns_exception(); + } +#else + BOOST_GEOMETRY_ASSERT(enter_count == 0); +#endif + + return process_end(entered, linestring, + current_segment_id, current_piece, + oit); + } +}; + + + + +template +< + typename LinestringOut, + typename MultiLinestring, + typename Linear, + overlay_type OverlayType, + bool FollowIsolatedPoints, + bool FollowContinueTurns +> +class follow_multilinestring_linear_linestring + : follow_linestring_linear_linestring + < + LinestringOut, + typename boost::range_value::type, + Linear, + OverlayType, + FollowIsolatedPoints, + FollowContinueTurns + > +{ +protected: + typedef typename boost::range_value::type Linestring; + + typedef follow_linestring_linear_linestring + < + LinestringOut, Linestring, Linear, + OverlayType, FollowIsolatedPoints, FollowContinueTurns + > Base; + + typedef following::action_selector action; + + typedef typename boost::range_iterator + < + MultiLinestring const + >::type linestring_iterator; + + + template + struct copy_linestrings_in_range + { + static inline OutputIt + apply(linestring_iterator, linestring_iterator, OutputIt oit) + { + return oit; + } + }; + + template + struct copy_linestrings_in_range + { + static inline OutputIt + apply(linestring_iterator first, linestring_iterator beyond, + OutputIt oit) + { + for (linestring_iterator ls_it = first; ls_it != beyond; ++ls_it) + { + LinestringOut line_out; + geometry::convert(*ls_it, line_out); + *oit++ = line_out; + } + return oit; + } + }; + + template + static inline signed_size_type get_multi_index(TurnIterator it) + { + return boost::begin(it->operations)->seg_id.multi_index; + } + + class has_other_multi_id + { + private: + signed_size_type m_multi_id; + + public: + has_other_multi_id(signed_size_type multi_id) + : m_multi_id(multi_id) {} + + template + bool operator()(Turn const& turn) const + { + return boost::begin(turn.operations)->seg_id.multi_index + != m_multi_id; + } + }; + +public: + template + static inline OutputIterator + apply(MultiLinestring const& multilinestring, Linear const& linear, + TurnIterator first, TurnIterator beyond, + OutputIterator oit) + { + BOOST_GEOMETRY_ASSERT( first != beyond ); + + typedef copy_linestrings_in_range + < + OutputIterator, OverlayType + > copy_linestrings; + + linestring_iterator ls_first = boost::begin(multilinestring); + linestring_iterator ls_beyond = boost::end(multilinestring); + + // Iterate through all intersection points (they are + // ordered along the each linestring) + + signed_size_type current_multi_id = get_multi_index(first); + + oit = copy_linestrings::apply(ls_first, + ls_first + current_multi_id, + oit); + + TurnIterator per_ls_next = first; + do { + TurnIterator per_ls_current = per_ls_next; + + // find turn with different multi-index + per_ls_next = std::find_if(per_ls_current, beyond, + has_other_multi_id(current_multi_id)); + + oit = Base::apply(*(ls_first + current_multi_id), + linear, per_ls_current, per_ls_next, oit); + + signed_size_type next_multi_id = -1; + linestring_iterator ls_next = ls_beyond; + if ( per_ls_next != beyond ) + { + next_multi_id = get_multi_index(per_ls_next); + ls_next = ls_first + next_multi_id; + } + oit = copy_linestrings::apply(ls_first + current_multi_id + 1, + ls_next, + oit); + + current_multi_id = next_multi_id; + } + while ( per_ls_next != beyond ); + + return oit; + } +}; + + + + + + +template +< + typename LinestringOut, + typename Geometry1, + typename Geometry2, + overlay_type OverlayType, + bool FollowIsolatedPoints, + bool FollowContinueTurns, + typename TagOut = typename tag::type, + typename TagIn1 = typename tag::type +> +struct follow + : not_implemented +{}; + + + +template +< + typename LinestringOut, + typename Linestring, + typename Linear, + overlay_type OverlayType, + bool FollowIsolatedPoints, + bool FollowContinueTurns +> +struct follow + < + LinestringOut, Linestring, Linear, + OverlayType, FollowIsolatedPoints, FollowContinueTurns, + linestring_tag, linestring_tag + > : follow_linestring_linear_linestring + < + LinestringOut, Linestring, Linear, + OverlayType, FollowIsolatedPoints, FollowContinueTurns + > +{}; + + +template +< + typename LinestringOut, + typename MultiLinestring, + typename Linear, + overlay_type OverlayType, + bool FollowIsolatedPoints, + bool FollowContinueTurns +> +struct follow + < + LinestringOut, MultiLinestring, Linear, + OverlayType, FollowIsolatedPoints, FollowContinueTurns, + linestring_tag, multi_linestring_tag + > : follow_multilinestring_linear_linestring + < + LinestringOut, MultiLinestring, Linear, + OverlayType, FollowIsolatedPoints, FollowContinueTurns + > +{}; + + + +}} // namespace following::linear + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp new file mode 100755 index 0000000000..1e9b2107ef --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -0,0 +1,154 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP + + +#include + +#include +#include + +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace get_intersection_points +{ + + +template +< + typename Point1, + typename Point2, + typename TurnInfo +> +struct get_turn_without_info +{ + template + static inline OutputIterator apply( + Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/, + Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/, + bool /*is_p_first*/, bool /*is_p_last*/, + bool /*is_q_first*/, bool /*is_q_last*/, + TurnInfo const& , + RobustPolicy const& robust_policy, + OutputIterator out) + { + typedef intersection_strategies + < + typename cs_tag::type, + Point1, + Point2, + typename TurnInfo::point_type, + RobustPolicy + > si; + + typedef typename si::segment_intersection_strategy_type strategy; + + typedef model::referring_segment segment_type1; + typedef model::referring_segment segment_type2; + segment_type1 p1(pi, pj); + segment_type2 q1(qi, qj); + + typedef typename geometry::robust_point_type + < + Point1, RobustPolicy + >::type robust_point_type; + + robust_point_type pi_rob, pj_rob, qi_rob, qj_rob; + geometry::recalculate(pi_rob, pi, robust_policy); + geometry::recalculate(pj_rob, pj, robust_policy); + geometry::recalculate(qi_rob, qi, robust_policy); + geometry::recalculate(qj_rob, qj, robust_policy); + typename strategy::return_type result + = strategy::apply(p1, q1, robust_policy, + pi_rob, pj_rob, qi_rob, qj_rob); + + for (std::size_t i = 0; i < result.template get<0>().count; i++) + { + + TurnInfo tp; + geometry::convert(result.template get<0>().intersections[i], tp.point); + *out++ = tp; + } + + return out; + } +}; + +}} // namespace detail::get_intersection_points +#endif // DOXYGEN_NO_DETAIL + + + + +template +< + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Turns +> +inline void get_intersection_points(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Turns& turns) +{ + concepts::check_concepts_and_equal_dimensions(); + + typedef detail::get_intersection_points::get_turn_without_info + < + typename point_type::type, + typename point_type::type, + typename boost::range_value::type + > TurnPolicy; + + detail::get_turns::no_interrupt_policy interrupt_policy; + + boost::mpl::if_c + < + reverse_dispatch::type::value, + dispatch::get_turns_reversed + < + typename tag::type, + typename tag::type, + Geometry1, Geometry2, + false, false, + TurnPolicy + >, + dispatch::get_turns + < + typename tag::type, + typename tag::type, + Geometry1, Geometry2, + false, false, + TurnPolicy + > + >::type::apply( + 0, geometry1, + 1, geometry2, + robust_policy, + turns, interrupt_policy); +} + + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp new file mode 100755 index 0000000000..9c7ad8c280 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp @@ -0,0 +1,101 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP + + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +/*! + \brief Get relative order + \details Can indicate which of two segments R and S, + both crossing a common segment P, comes first. + If the two segments cross P very close (e.g. in a spike), + the distance between the intersection points can be zero, + but we still need to know which comes first. + Therefore, it is useful that using sides we are able to discover this. + */ +template +struct get_relative_order +{ + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type strategy; + + template + static inline int value_via_product(Point const& ti, Point const& tj, + Point const& ui, Point const& uj, int factor) + { + int const side_ti_u = strategy::apply(ti, tj, ui); + int const side_tj_u = strategy::apply(ti, tj, uj); + +#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER + std::cout << (factor == 1 ? " r//s " : " s//r ") + << side_ti_u << " / " << side_tj_u; +#endif + + return side_ti_u * side_tj_u >= 0 + ? factor * (side_ti_u != 0 ? side_ti_u : side_tj_u) + : 0; + } + + + static inline int apply( + Point1 const& pi, Point1 const& pj, + Point1 const& ri, Point1 const& rj, + Point1 const& si, Point1 const& sj) + { + int const side_ri_p = strategy::apply(pi, pj, ri); + int const side_si_p = strategy::apply(pi, pj, si); + +#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER + int const side_rj_p = strategy::apply(pi, pj, rj); + int const side_sj_p = strategy::apply(pi, pj, sj); + std::cout << "r//p: " << side_ri_p << " / " << side_rj_p; + std::cout << " s//p: " << side_si_p << " / " << side_sj_p; +#endif + + int value = value_via_product(si, sj, ri, rj, 1); + if (value == 0) + { + value = value_via_product(ri, rj, si, sj, -1); + } + + int const order = side_ri_p * side_ri_p * side_si_p * value; + +#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER + std::cout + << " o: " << order + << std::endl << std::endl; +#endif + + return order; + } +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp new file mode 100755 index 0000000000..6d0727dfd8 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_ring.hpp @@ -0,0 +1,123 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +struct get_ring +{}; + +// A range of rings (multi-ring but that does not exist) +// gets the "void" tag and is dispatched here. +template<> +struct get_ring +{ + template + static inline typename boost::range_value::type const& + apply(ring_identifier const& id, Range const& container) + { + return range::at(container, id.multi_index); + } +}; + + + + +template<> +struct get_ring +{ + template + static inline Ring const& apply(ring_identifier const& , Ring const& ring) + { + return ring; + } +}; + + +template<> +struct get_ring +{ + template + static inline Box const& apply(ring_identifier const& , + Box const& box) + { + return box; + } +}; + + +template<> +struct get_ring +{ + template + static inline typename ring_return_type::type const apply( + ring_identifier const& id, + Polygon const& polygon) + { + BOOST_GEOMETRY_ASSERT + ( + id.ring_index >= -1 + && id.ring_index < int(boost::size(interior_rings(polygon))) + ); + return id.ring_index < 0 + ? exterior_ring(polygon) + : range::at(interior_rings(polygon), id.ring_index); + } +}; + + +template<> +struct get_ring +{ + template + static inline typename ring_type::type const& apply( + ring_identifier const& id, + MultiPolygon const& multi_polygon) + { + BOOST_GEOMETRY_ASSERT + ( + id.multi_index >= 0 + && id.multi_index < int(boost::size(multi_polygon)) + ); + return get_ring::apply(id, + range::at(multi_polygon, id.multi_index)); + } +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp new file mode 100755 index 0000000000..d42bcdc0d9 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -0,0 +1,1118 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP + + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +// Silence warning C4127: conditional expression is constant +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + + +namespace boost { namespace geometry +{ + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) +class turn_info_exception : public geometry::exception +{ + std::string message; +public: + + // NOTE: "char" will be replaced by enum in future version + inline turn_info_exception(char const method) + { + message = "Boost.Geometry Turn exception: "; + message += method; + } + + virtual ~turn_info_exception() throw() + {} + + virtual char const* what() const throw() + { + return message.c_str(); + } +}; +#endif + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +struct base_turn_handler +{ + // Returns true if both sides are opposite + static inline bool opposite(int side1, int side2) + { + // We cannot state side1 == -side2, because 0 == -0 + // So either side1*side2==-1 or side1==-side2 && side1 != 0 + return side1 * side2 == -1; + } + + // Same side of a segment (not being 0) + static inline bool same(int side1, int side2) + { + return side1 * side2 == 1; + } + + // Both continue + template + static inline void both(TurnInfo& ti, operation_type const op) + { + ti.operations[0].operation = op; + ti.operations[1].operation = op; + } + + // If condition, first union/second intersection, else vice versa + template + static inline void ui_else_iu(bool condition, TurnInfo& ti) + { + ti.operations[0].operation = condition + ? operation_union : operation_intersection; + ti.operations[1].operation = condition + ? operation_intersection : operation_union; + } + + // If condition, both union, else both intersection + template + static inline void uu_else_ii(bool condition, TurnInfo& ti) + { + both(ti, condition ? operation_union : operation_intersection); + } + + template + static inline void assign_point(TurnInfo& ti, + method_type method, + IntersectionInfo const& info, unsigned int index) + { + ti.method = method; + + BOOST_GEOMETRY_ASSERT(index < info.count); + + geometry::convert(info.intersections[index], ti.point); + ti.operations[0].fraction = info.fractions[index].robust_ra; + ti.operations[1].fraction = info.fractions[index].robust_rb; + } + + template + static inline unsigned int non_opposite_to_index(IntersectionInfo const& info) + { + return info.fractions[0].robust_rb < info.fractions[1].robust_rb + ? 1 : 0; + } + +}; + + +template +< + typename TurnInfo +> +struct touch_interior : public base_turn_handler +{ + // Index: 0, P is the interior, Q is touching and vice versa + template + < + unsigned int Index, + typename Point1, + typename Point2, + typename IntersectionInfo, + typename DirInfo, + typename SidePolicy + > + static inline void apply( + Point1 const& , Point1 const& , Point1 const& , + Point2 const& , Point2 const& , Point2 const& , + TurnInfo& ti, + IntersectionInfo const& intersection_info, + DirInfo const& dir_info, + SidePolicy const& side) + { + assign_point(ti, method_touch_interior, intersection_info, 0); + + // Both segments of q touch segment p somewhere in its interior + // 1) We know: if q comes from LEFT or RIGHT + // (i.e. dir_info.sides.get() == 1 or -1) + // 2) Important is: if q_k goes to LEFT, RIGHT, COLLINEAR + // and, if LEFT/COLL, if it is lying LEFT or RIGHT w.r.t. q_i + + BOOST_STATIC_ASSERT(Index <= 1); + static unsigned int const index_p = Index; + static unsigned int const index_q = 1 - Index; + + int const side_qi_p = dir_info.sides.template get(); + int const side_qk_p = side.qk_wrt_p1(); + + if (side_qi_p == -side_qk_p) + { + // Q crosses P from left->right or from right->left (test "ML1") + // Union: folow P (left->right) or Q (right->left) + // Intersection: other turn + unsigned int index = side_qk_p == -1 ? index_p : index_q; + ti.operations[index].operation = operation_union; + ti.operations[1 - index].operation = operation_intersection; + return; + } + + int const side_qk_q = side.qk_wrt_q1(); + + if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1) + { + // Q turns left on the right side of P (test "MR3") + // Both directions for "intersection" + both(ti, operation_intersection); + } + else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1) + { + // Q turns right on the left side of P (test "ML3") + // Union: take both operation + // Intersection: skip + both(ti, operation_union); + } + else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q) + { + // Q turns left on the left side of P (test "ML2") + // or Q turns right on the right side of P (test "MR2") + // Union: take left turn (Q if Q turns left, P if Q turns right) + // Intersection: other turn + unsigned int index = side_qk_q == 1 ? index_q : index_p; + ti.operations[index].operation = operation_union; + ti.operations[1 - index].operation = operation_intersection; + } + else if (side_qk_p == 0) + { + // Q intersects on interior of P and continues collinearly + if (side_qk_q == side_qi_p) + { + // Collinearly in the same direction + // (Q comes from left of P and turns left, + // OR Q comes from right of P and turns right) + // Omit intersection point. + // Union: just continue + // Intersection: just continue + both(ti, operation_continue); + } + else + { + // Opposite direction, which is never travelled. + // If Q turns left, P continues for intersection + // If Q turns right, P continues for union + ti.operations[index_p].operation = side_qk_q == 1 + ? operation_intersection + : operation_union; + ti.operations[index_q].operation = operation_blocked; + } + } + else + { + // Should not occur! + ti.method = method_error; + } + } +}; + + +template +< + typename TurnInfo +> +struct touch : public base_turn_handler +{ + static inline bool between(int side1, int side2, int turn) + { + return side1 == side2 && ! opposite(side1, turn); + } + + /*static inline void block_second(bool block, TurnInfo& ti) + { + if (block) + { + ti.operations[1].operation = operation_blocked; + } + }*/ + + + template + < + typename Point1, + typename Point2, + typename IntersectionInfo, + typename DirInfo, + typename SidePolicy + > + static inline void apply( + Point1 const& , Point1 const& , Point1 const& , + Point2 const& , Point2 const& , Point2 const& , + TurnInfo& ti, + IntersectionInfo const& intersection_info, + DirInfo const& dir_info, + SidePolicy const& side) + { + assign_point(ti, method_touch, intersection_info, 0); + + int const side_qi_p1 = dir_info.sides.template get<1, 0>(); + int const side_qk_p1 = side.qk_wrt_p1(); + + + // If Qi and Qk are both at same side of Pi-Pj, + // or collinear (so: not opposite sides) + if (! opposite(side_qi_p1, side_qk_p1)) + { + int const side_pk_q2 = side.pk_wrt_q2(); + int const side_pk_p = side.pk_wrt_p1(); + int const side_qk_q = side.qk_wrt_q1(); + + bool const q_turns_left = side_qk_q == 1; + bool const block_q = side_qk_p1 == 0 + && ! same(side_qi_p1, side_qk_q) + ; + + // If Pk at same side as Qi/Qk + // (the "or" is for collinear case) + // or Q is fully collinear && P turns not to left + if (side_pk_p == side_qi_p1 + || side_pk_p == side_qk_p1 + || (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1) + ) + { + // Collinear -> lines join, continue + // (#BRL2) + if (side_pk_q2 == 0 && ! block_q) + { + both(ti, operation_continue); + return; + } + + int const side_pk_q1 = side.pk_wrt_q1(); + + + // Collinear opposite case -> block P + // (#BRL4, #BLR8) + if (side_pk_q1 == 0) + { + ti.operations[0].operation = operation_blocked; + // Q turns right -> union (both independent), + // Q turns left -> intersection + ti.operations[1].operation = block_q ? operation_blocked + : q_turns_left ? operation_intersection + : operation_union; + return; + } + + // Pk between Qi and Qk + // (#BRL3, #BRL7) + if (between(side_pk_q1, side_pk_q2, side_qk_q)) + { + ui_else_iu(q_turns_left, ti); + if (block_q) + { + ti.operations[1].operation = operation_blocked; + } + //block_second(block_q, ti); + return; + } + + // Pk between Qk and P, so left of Qk (if Q turns right) and vv + // (#BRL1) + if (side_pk_q2 == -side_qk_q) + { + ui_else_iu(! q_turns_left, ti); + return; + } + + // + // (#BRL5, #BRL9) + if (side_pk_q1 == -side_qk_q) + { + uu_else_ii(! q_turns_left, ti); + if (block_q) + { + ti.operations[1].operation = operation_blocked; + } + //block_second(block_q, ti); + return; + } + } + else + { + // Pk at other side than Qi/Pk + ti.operations[0].operation = q_turns_left + ? operation_intersection + : operation_union; + ti.operations[1].operation = block_q + ? operation_blocked + : side_qi_p1 == 1 || side_qk_p1 == 1 + ? operation_union + : operation_intersection; + + return; + } + } + else + { + // From left to right or from right to left + int const side_pk_p = side.pk_wrt_p1(); + bool const right_to_left = side_qk_p1 == 1; + + // If p turns into direction of qi (1,2) + if (side_pk_p == side_qi_p1) + { + int const side_pk_q1 = side.pk_wrt_q1(); + + // Collinear opposite case -> block P + if (side_pk_q1 == 0) + { + ti.operations[0].operation = operation_blocked; + ti.operations[1].operation = right_to_left + ? operation_union : operation_intersection; + return; + } + + if (side_pk_q1 == side_qk_p1) + { + uu_else_ii(right_to_left, ti); + return; + } + } + + // If p turns into direction of qk (4,5) + if (side_pk_p == side_qk_p1) + { + int const side_pk_q2 = side.pk_wrt_q2(); + + // Collinear case -> lines join, continue + if (side_pk_q2 == 0) + { + both(ti, operation_continue); + return; + } + if (side_pk_q2 == side_qk_p1) + { + ui_else_iu(right_to_left, ti); + return; + } + } + // otherwise (3) + ui_else_iu(! right_to_left, ti); + return; + } + +#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS + // Normally a robustness issue. + // TODO: more research if still occuring + std::cout << "Not yet handled" << std::endl + << "pi " << get<0>(pi) << " , " << get<1>(pi) + << " pj " << get<0>(pj) << " , " << get<1>(pj) + << " pk " << get<0>(pk) << " , " << get<1>(pk) + << std::endl + << "qi " << get<0>(qi) << " , " << get<1>(qi) + << " qj " << get<0>(qj) << " , " << get<1>(qj) + << " qk " << get<0>(qk) << " , " << get<1>(qk) + << std::endl; +#endif + + } +}; + + +template +< + typename TurnInfo +> +struct equal : public base_turn_handler +{ + template + < + typename Point1, + typename Point2, + typename IntersectionInfo, + typename DirInfo, + typename SidePolicy + > + static inline void apply( + Point1 const& , Point1 const& , Point1 const& , + Point2 const& , Point2 const& , Point2 const& , + TurnInfo& ti, + IntersectionInfo const& info, + DirInfo const& , + SidePolicy const& side) + { + // Copy the intersection point in TO direction + assign_point(ti, method_equal, info, non_opposite_to_index(info)); + + int const side_pk_q2 = side.pk_wrt_q2(); + int const side_pk_p = side.pk_wrt_p1(); + int const side_qk_p = side.qk_wrt_p1(); + + + // If pk is collinear with qj-qk, they continue collinearly. + // This can be on either side of p1 (== q1), or collinear + // The second condition checks if they do not continue + // oppositely + if (side_pk_q2 == 0 && side_pk_p == side_qk_p) + { + both(ti, operation_continue); + + return; + } + + + // If they turn to same side (not opposite sides) + if (! opposite(side_pk_p, side_qk_p)) + { + // If pk is left of q2 or collinear: p: union, q: intersection + ui_else_iu(side_pk_q2 != -1, ti); + } + else + { + // They turn opposite sides. If p turns left (or collinear), + // p: union, q: intersection + ui_else_iu(side_pk_p != -1, ti); + } + } +}; + + +template +< + typename TurnInfo, + typename AssignPolicy +> +struct equal_opposite : public base_turn_handler +{ + template + < + typename Point1, + typename Point2, + typename OutputIterator, + typename IntersectionInfo + > + static inline void apply(Point1 const& pi, Point2 const& qi, + /* by value: */ TurnInfo tp, + OutputIterator& out, + IntersectionInfo const& intersection_info) + { + // For equal-opposite segments, normally don't do anything. + if (AssignPolicy::include_opposite) + { + tp.method = method_equal; + for (unsigned int i = 0; i < 2; i++) + { + tp.operations[i].operation = operation_opposite; + } + for (unsigned int i = 0; i < intersection_info.i_info().count; i++) + { + assign_point(tp, method_none, intersection_info.i_info(), i); + AssignPolicy::apply(tp, pi, qi, intersection_info); + *out++ = tp; + } + } + } +}; + +template +< + typename TurnInfo +> +struct collinear : public base_turn_handler +{ + /* + arrival P pk//p1 qk//q1 product* case result + 1 1 1 CLL1 ui + -1 1 -1 CLL2 iu + 1 1 1 CLR1 ui + -1 -1 1 CLR2 ui + + 1 -1 -1 CRL1 iu + -1 1 -1 CRL2 iu + 1 -1 -1 CRR1 iu + -1 -1 1 CRR2 ui + + 1 0 0 CC1 cc + -1 0 0 CC2 cc + + *product = arrival * (pk//p1 or qk//q1) + + Stated otherwise: + - if P arrives: look at turn P + - if Q arrives: look at turn Q + - if P arrives and P turns left: union for P + - if P arrives and P turns right: intersection for P + - if Q arrives and Q turns left: union for Q (=intersection for P) + - if Q arrives and Q turns right: intersection for Q (=union for P) + + ROBUSTNESS: p and q are collinear, so you would expect + that side qk//p1 == pk//q1. But that is not always the case + in near-epsilon ranges. Then decision logic is different. + If p arrives, q is further, so the angle qk//p1 is (normally) + more precise than pk//p1 + + */ + template + < + typename Point1, + typename Point2, + typename IntersectionInfo, + typename DirInfo, + typename SidePolicy + > + static inline void apply( + Point1 const& , Point1 const& pj, Point1 const& pk, + Point2 const& , Point2 const& qj, Point2 const& qk, + TurnInfo& ti, + IntersectionInfo const& info, + DirInfo const& dir_info, + SidePolicy const& side) + { + // Copy the intersection point in TO direction + assign_point(ti, method_collinear, info, non_opposite_to_index(info)); + + int const arrival = dir_info.arrival[0]; + // Should not be 0, this is checked before + BOOST_GEOMETRY_ASSERT(arrival != 0); + + int const side_p = side.pk_wrt_p1(); + int const side_q = side.qk_wrt_q1(); + + // If p arrives, use p, else use q + int const side_p_or_q = arrival == 1 + ? side_p + : side_q + ; + + // See comments above, + // resulting in a strange sort of mathematic rule here: + // The arrival-info multiplied by the relevant side + // delivers a consistent result. + + int const product = arrival * side_p_or_q; + + if(product == 0) + { + both(ti, operation_continue); + } + else + { + ui_else_iu(product == 1, ti); + } + + // Calculate remaining distance. If it continues collinearly it is + // measured until the end of the next segment + ti.operations[0].remaining_distance + = side_p == 0 + ? distance_measure(ti.point, pk) + : distance_measure(ti.point, pj); + ti.operations[1].remaining_distance + = side_q == 0 + ? distance_measure(ti.point, qk) + : distance_measure(ti.point, qj); + } + + template + static inline typename geometry::coordinate_type::type + distance_measure(Point1 const& a, Point2 const& b) + { + // TODO: use comparable distance for point-point instead - but that + // causes currently cycling include problems + typedef typename geometry::coordinate_type::type ctype; + ctype const dx = get<0>(a) - get<0>(b); + ctype const dy = get<1>(b) - get<1>(b); + return dx * dx + dy * dy; + } +}; + +template +< + typename TurnInfo, + typename AssignPolicy +> +struct collinear_opposite : public base_turn_handler +{ +private : + /* + arrival P arrival Q pk//p1 qk//q1 case result2 result + -------------------------------------------------------------- + 1 1 1 -1 CLO1 ix xu + 1 1 1 0 CLO2 ix (xx) + 1 1 1 1 CLO3 ix xi + + 1 1 0 -1 CCO1 (xx) xu + 1 1 0 0 CCO2 (xx) (xx) + 1 1 0 1 CCO3 (xx) xi + + 1 1 -1 -1 CRO1 ux xu + 1 1 -1 0 CRO2 ux (xx) + 1 1 -1 1 CRO3 ux xi + + -1 1 -1 CXO1 xu + -1 1 0 CXO2 (xx) + -1 1 1 CXO3 xi + + 1 -1 1 CXO1 ix + 1 -1 0 CXO2 (xx) + 1 -1 -1 CXO3 ux + */ + + template + < + unsigned int Index, + typename Point1, + typename Point2, + typename IntersectionInfo + > + static inline bool set_tp(Point1 const& , Point1 const& , Point1 const& , int side_rk_r, + bool const handle_robustness, + Point2 const& , Point2 const& , int side_rk_s, + TurnInfo& tp, IntersectionInfo const& intersection_info) + { + BOOST_STATIC_ASSERT(Index <= 1); + + boost::ignore_unused(handle_robustness, side_rk_s); + + operation_type blocked = operation_blocked; + switch(side_rk_r) + { + + case 1 : + // Turning left on opposite collinear: intersection + tp.operations[Index].operation = operation_intersection; + break; + case -1 : + // Turning right on opposite collinear: union + tp.operations[Index].operation = operation_union; + break; + case 0 : + // No turn on opposite collinear: block, do not traverse + // But this "xx" is usually ignored, it is useless to include + // two operations blocked, so the whole point does not need + // to be generated. + // So return false to indicate nothing is to be done. + if (AssignPolicy::include_opposite) + { + tp.operations[Index].operation = operation_opposite; + blocked = operation_opposite; + } + else + { + return false; + } + break; + } + + // The other direction is always blocked when collinear opposite + tp.operations[1 - Index].operation = blocked; + + // If P arrives within Q, set info on P (which is done above, index=0), + // this turn-info belongs to the second intersection point, index=1 + // (see e.g. figure CLO1) + assign_point(tp, method_collinear, intersection_info, 1 - Index); + return true; + } + +public: + static inline void empty_transformer(TurnInfo &) {} + + template + < + typename Point1, + typename Point2, + typename OutputIterator, + typename IntersectionInfo, + typename SidePolicy + > + static inline void apply( + Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + + // Opposite collinear can deliver 2 intersection points, + TurnInfo const& tp_model, + OutputIterator& out, + + IntersectionInfo const& intersection_info, + SidePolicy const& side) + { + apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer); + } + +public: + template + < + typename Point1, + typename Point2, + typename OutputIterator, + typename IntersectionInfo, + typename SidePolicy, + typename TurnTransformer + > + static inline void apply( + Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + + // Opposite collinear can deliver 2 intersection points, + TurnInfo const& tp_model, + OutputIterator& out, + + IntersectionInfo const& info, + SidePolicy const& side, + TurnTransformer turn_transformer, + bool const is_pk_valid = true, bool const is_qk_valid = true) + { + TurnInfo tp = tp_model; + + int const p_arrival = info.d_info().arrival[0]; + int const q_arrival = info.d_info().arrival[1]; + + // If P arrives within Q, there is a turn dependent on P + if ( p_arrival == 1 + && is_pk_valid + && set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) ) + { + turn_transformer(tp); + + AssignPolicy::apply(tp, pi, qi, info); + *out++ = tp; + } + + // If Q arrives within P, there is a turn dependent on Q + if ( q_arrival == 1 + && is_qk_valid + && set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) ) + { + turn_transformer(tp); + + AssignPolicy::apply(tp, pi, qi, info); + *out++ = tp; + } + + if (AssignPolicy::include_opposite) + { + // Handle cases not yet handled above + if ((q_arrival == -1 && p_arrival == 0) + || (p_arrival == -1 && q_arrival == 0)) + { + for (unsigned int i = 0; i < 2; i++) + { + tp.operations[i].operation = operation_opposite; + } + for (unsigned int i = 0; i < info.i_info().count; i++) + { + assign_point(tp, method_collinear, info.i_info(), i); + AssignPolicy::apply(tp, pi, qi, info); + *out++ = tp; + } + } + } + + } +}; + + +template +< + typename TurnInfo +> +struct crosses : public base_turn_handler +{ + template + < + typename Point1, + typename Point2, + typename IntersectionInfo, + typename DirInfo + > + static inline void apply( + Point1 const& , Point1 const& , Point1 const& , + Point2 const& , Point2 const& , Point2 const& , + TurnInfo& ti, + IntersectionInfo const& intersection_info, + DirInfo const& dir_info) + { + assign_point(ti, method_crosses, intersection_info, 0); + + // In all casees: + // If Q crosses P from left to right + // Union: take P + // Intersection: take Q + // Otherwise: vice versa + int const side_qi_p1 = dir_info.sides.template get<1, 0>(); + unsigned int const index = side_qi_p1 == 1 ? 0 : 1; + ti.operations[index].operation = operation_union; + ti.operations[1 - index].operation = operation_intersection; + } +}; + +struct only_convert : public base_turn_handler +{ + template + static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info) + { + assign_point(ti, method_none, intersection_info, 0); // was collinear + ti.operations[0].operation = operation_continue; + ti.operations[1].operation = operation_continue; + } +}; + +/*! +\brief Policy doing nothing +\details get_turn_info can have an optional policy to get/assign some + extra information. By default it does not, and this class + is that default. + */ +struct assign_null_policy +{ + static bool const include_no_turn = false; + static bool const include_degenerate = false; + static bool const include_opposite = false; + + template + < + typename Info, + typename Point1, + typename Point2, + typename IntersectionInfo + > + static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&) + {} + +}; + + +/*! + \brief Turn information: intersection point, method, and turn information + \details Information necessary for traversal phase (a phase + of the overlay process). The information is gathered during the + get_turns (segment intersection) phase. + \tparam Point1 point type of first segment + \tparam Point2 point type of second segment + \tparam TurnInfo type of class getting intersection and turn info + \tparam AssignPolicy policy to assign extra info, + e.g. to calculate distance from segment's first points + to intersection points. + It also defines if a certain class of points + (degenerate, non-turns) should be included. + */ +template +struct get_turn_info +{ + // Intersect pi-pj with qi-qj + // The points pk and qk are used do determine more information + // about the turn (turn left/right) + template + < + typename Point1, + typename Point2, + typename TurnInfo, + typename RobustPolicy, + typename OutputIterator + > + static inline OutputIterator apply( + Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + bool /*is_p_first*/, bool /*is_p_last*/, + bool /*is_q_first*/, bool /*is_q_last*/, + TurnInfo const& tp_model, + RobustPolicy const& robust_policy, + OutputIterator out) + { + typedef intersection_info + inters_info; + + inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); + + char const method = inters.d_info().how; + + // Copy, to copy possibly extended fields + TurnInfo tp = tp_model; + + // Select method and apply + switch(method) + { + case 'a' : // collinear, "at" + case 'f' : // collinear, "from" + case 's' : // starts from the middle + if (AssignPolicy::include_no_turn + && inters.i_info().count > 0) + { + only_convert::apply(tp, inters.i_info()); + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + break; + + case 'd' : // disjoint: never do anything + break; + + case 'm' : + { + typedef touch_interior + < + TurnInfo + > policy; + + // If Q (1) arrives (1) + if ( inters.d_info().arrival[1] == 1 ) + { + policy::template apply<0>(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), + inters.sides()); + } + else + { + // Swap p/q + side_calculator + < + typename inters_info::cs_tag, + typename inters_info::robust_point2_type, + typename inters_info::robust_point1_type + > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk()); + policy::template apply<1>(qi, qj, qk, pi, pj, pk, + tp, inters.i_info(), inters.d_info(), + swapped_side_calc); + } + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + break; + case 'i' : + { + crosses::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info()); + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + break; + case 't' : + { + // Both touch (both arrive there) + touch::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + break; + case 'e': + { + if ( ! inters.d_info().opposite ) + { + // Both equal + // or collinear-and-ending at intersection point + equal::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + else + { + equal_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, qi, + tp, out, inters); + } + } + break; + case 'c' : + { + // Collinear + if ( ! inters.d_info().opposite ) + { + + if ( inters.d_info().arrival[0] == 0 ) + { + // Collinear, but similar thus handled as equal + equal::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + // override assigned method + tp.method = method_collinear; + } + else + { + collinear::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + } + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + else + { + collinear_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, pj, pk, qi, qj, qk, + tp, out, inters, inters.sides()); + } + } + break; + case '0' : + { + // degenerate points + if (AssignPolicy::include_degenerate) + { + only_convert::apply(tp, inters.i_info()); + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + } + break; + default : + { +#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS) + std::cout << "TURN: Unknown method: " << method << std::endl; +#endif +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw turn_info_exception(method); +#endif + } + break; + } + + return out; + } +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp new file mode 100755 index 0000000000..bdfeb4913b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -0,0 +1,662 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP + +#include +#include +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { + +// SEGMENT_INTERSECTION RESULT + +// C H0 H1 A0 A1 O IP1 IP2 + +// D0 and D1 == 0 + +// |--------> 2 0 0 0 0 F i/i x/x +// |--------> +// +// |--------> 2 0 0 0 0 T i/x x/i +// <--------| +// +// |-----> 1 0 0 0 0 T x/x +// <-----| +// + +// |---------> 2 0 0 0 1 T i/x x/i +// <----| +// +// |---------> 2 0 0 0 0 F i/i x/x +// |----> +// +// |---------> 2 0 0 -1 1 F i/i u/x +// |----> +// +// |---------> 2 0 0 -1 0 T i/x u/i +// <----| + +// |-------> 2 0 0 1 -1 F and i/i x/u +// |-------> 2 0 0 -1 1 F symetric i/i u/x +// |-------> +// +// |-------> 2 0 0 -1 -1 T i/u u/i +// <-------| +// +// |-------> 2 0 0 1 1 T i/x x/i +// <-------| +// +// |--------> 2 0 0 -1 1 F i/i u/x +// |----> +// +// |--------> 2 0 0 -1 1 T i/x u/i +// <----| + +// |-----> 1 -1 -1 -1 -1 T u/u +// <-----| +// +// |-----> 1 -1 0 -1 0 F and u/x +// |-----> 1 0 -1 0 -1 F symetric x/u +// |-----> + +// D0 or D1 != 0 + +// ^ +// | +// + 1 -1 1 -1 1 F and u/x (P is vertical) +// |--------> 1 1 -1 1 -1 F symetric x/u (P is horizontal) +// ^ +// | +// + +// +// + +// | +// v +// |--------> 1 1 1 1 1 F x/x (P is vertical) +// +// ^ +// | +// + +// |--------> 1 -1 -1 -1 -1 F u/u (P is vertical) +// +// ^ +// | +// + +// |--------> 1 0 -1 0 -1 F u/u (P is vertical) +// +// + +// | +// v +// |--------> 1 0 1 0 1 F u/x (P is vertical) +// + +class linear_intersections +{ +public: + template + linear_intersections(Point1 const& pi, + Point2 const& qi, + IntersectionResult const& result, + bool is_p_last, bool is_q_last) + { + int arrival_a = result.template get<1>().arrival[0]; + int arrival_b = result.template get<1>().arrival[1]; + bool same_dirs = result.template get<1>().dir_a == 0 + && result.template get<1>().dir_b == 0; + + if ( same_dirs ) + { + if ( result.template get<0>().count == 2 ) + { + if ( ! result.template get<1>().opposite ) + { + ips[0].p_operation = operation_intersection; + ips[0].q_operation = operation_intersection; + ips[1].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last); + ips[1].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last); + + ips[0].is_pi + = equals::equals_point_point( + pi, result.template get<0>().intersections[0]); + ips[0].is_qi + = equals::equals_point_point( + qi, result.template get<0>().intersections[0]); + ips[1].is_pj = arrival_a != -1; + ips[1].is_qj = arrival_b != -1; + } + else + { + ips[0].p_operation = operation_intersection; + ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last); + ips[1].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last); + ips[1].q_operation = operation_intersection; + + ips[0].is_pi = arrival_b != 1; + ips[0].is_qj = arrival_b != -1; + ips[1].is_pj = arrival_a != -1; + ips[1].is_qi = arrival_a != 1; + } + } + else + { + BOOST_GEOMETRY_ASSERT(result.template get<0>().count == 1); + ips[0].p_operation = union_or_blocked_same_dirs(arrival_a, is_p_last); + ips[0].q_operation = union_or_blocked_same_dirs(arrival_b, is_q_last); + + ips[0].is_pi = arrival_a == -1; + ips[0].is_qi = arrival_b == -1; + ips[0].is_pj = arrival_a == 0; + ips[0].is_qj = arrival_b == 0; + } + } + else + { + ips[0].p_operation = union_or_blocked_different_dirs(arrival_a, is_p_last); + ips[0].q_operation = union_or_blocked_different_dirs(arrival_b, is_q_last); + + ips[0].is_pi = arrival_a == -1; + ips[0].is_qi = arrival_b == -1; + ips[0].is_pj = arrival_a == 1; + ips[0].is_qj = arrival_b == 1; + } + } + + struct ip_info + { + inline ip_info() + : p_operation(operation_none), q_operation(operation_none) + , is_pi(false), is_pj(false), is_qi(false), is_qj(false) + {} + + operation_type p_operation, q_operation; + bool is_pi, is_pj, is_qi, is_qj; + }; + + template + ip_info const& get() const + { + BOOST_STATIC_ASSERT(I < 2); + return ips[I]; + } + +private: + + // only if collinear (same_dirs) + static inline operation_type union_or_blocked_same_dirs(int arrival, bool is_last) + { + if ( arrival == 1 ) + return operation_blocked; + else if ( arrival == -1 ) + return operation_union; + else + return is_last ? operation_blocked : operation_union; + //return operation_blocked; + } + + // only if not collinear (!same_dirs) + static inline operation_type union_or_blocked_different_dirs(int arrival, bool is_last) + { + if ( arrival == 1 ) + //return operation_blocked; + return is_last ? operation_blocked : operation_union; + else + return operation_union; + } + + ip_info ips[2]; +}; + +template +struct get_turn_info_for_endpoint +{ + BOOST_STATIC_ASSERT(EnableFirst || EnableLast); + + template + static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, + TurnInfo const& tp_model, + IntersectionInfo const& inters, + method_type /*method*/, + OutputIterator out) + { + std::size_t ip_count = inters.i_info().count; + // no intersection points + if ( ip_count == 0 ) + return false; + + if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last ) + return false; + + linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last); + + bool append0_last + = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + intersections.template get<0>(), + tp_model, inters, 0, out); + + // NOTE: opposite && ip_count == 1 may be true! + bool opposite = inters.d_info().opposite; + + // don't ignore only for collinear opposite + bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite ); + + if ( intersections.template get<1>().p_operation == operation_none ) + return result_ignore_ip0; + + bool append1_last + = analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + intersections.template get<1>(), + tp_model, inters, 1, out); + + // don't ignore only for collinear opposite + bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/; + + return result_ignore_ip0 || result_ignore_ip1; + } + + template + static inline + bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, + linear_intersections::ip_info const& ip_info, + TurnInfo const& tp_model, + IntersectionInfo const& inters, + unsigned int ip_index, + OutputIterator out) + { +#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR + // may this give false positives for INTs? + typename IntersectionResult::point_type const& + inters_pt = result.template get<0>().intersections[ip_index]; + BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt)); +#endif + + // TODO - calculate first/last only if needed + bool is_p_first_ip = is_p_first && ip_info.is_pi; + bool is_p_last_ip = is_p_last && ip_info.is_pj; + bool is_q_first_ip = is_q_first && ip_info.is_qi; + bool is_q_last_ip = is_q_last && ip_info.is_qj; + bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip); + bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip); + + operation_type p_operation = ip_info.p_operation; + operation_type q_operation = ip_info.q_operation; + + if ( append_first || append_last ) + { + bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk, + inters.rpi(), inters.rpj(), inters.rpk(), + inters.rqi(), inters.rqj(), inters.rqk(), + is_p_first_ip, is_p_last_ip, + is_q_first_ip, is_q_last_ip, + ip_info.is_qi, ip_info.is_qj, + tp_model, inters, ip_index, + p_operation, q_operation); + if ( !handled ) + { + handle_internal<1>(qi, qj, qk, pi, pj, pk, + inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk(), + is_q_first_ip, is_q_last_ip, + is_p_first_ip, is_p_last_ip, + ip_info.is_pi, ip_info.is_pj, + tp_model, inters, ip_index, + q_operation, p_operation); + } + + if ( p_operation != operation_none ) + { + method_type method = endpoint_ip_method(ip_info.is_pi, ip_info.is_pj, + ip_info.is_qi, ip_info.is_qj); + turn_position p_pos = ip_position(is_p_first_ip, is_p_last_ip); + turn_position q_pos = ip_position(is_q_first_ip, is_q_last_ip); + + // handle spikes + + // P is spike and should be handled + if ( !is_p_last + && ip_info.is_pj // this check is redundant (also in is_spike_p) but faster + && inters.i_info().count == 2 + && inters.is_spike_p() ) + { + assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation, + p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out); + assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation, + p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out); + } + // Q is spike and should be handled + else if ( !is_q_last + && ip_info.is_qj // this check is redundant (also in is_spike_q) but faster + && inters.i_info().count == 2 + && inters.is_spike_q() ) + { + assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked, + p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out); + assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection, + p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out); + } + // no spikes + else + { + assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation, + p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, false, tp_model, out); + } + } + } + + return append_last; + } + + // TODO: IT'S ALSO PROBABLE THAT ALL THIS FUNCTION COULD BE INTEGRATED WITH handle_segment + // however now it's lazily calculated and then it would be always calculated + + template + static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/, + Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/, + RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/, + RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2, + bool first1, bool last1, bool first2, bool last2, + bool ip_i2, bool ip_j2, TurnInfo const& tp_model, + IntersectionInfo const& inters, unsigned int ip_index, + operation_type & op1, operation_type & op2) + { + typedef typename cs_tag::type cs_tag; + + boost::ignore_unused_variable_warning(i2); + boost::ignore_unused_variable_warning(j2); + boost::ignore_unused_variable_warning(ip_index); + boost::ignore_unused_variable_warning(tp_model); + + if ( !first2 && !last2 ) + { + if ( first1 ) + { +#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR + // may this give false positives for INTs? + typename IntersectionResult::point_type const& + inters_pt = inters.i_info().intersections[ip_index]; + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); +#endif + if ( ip_i2 ) + { + // don't output this IP - for the first point of other geometry segment + op1 = operation_none; + op2 = operation_none; + return true; + } + else if ( ip_j2 ) + { + side_calculator + side_calc(ri2, ri1, rj1, ri2, rj2, rk2); + + std::pair + operations = operations_of_equal(side_calc); + +// TODO: must the above be calculated? +// wouldn't it be enough to check if segments are collinear? + + if ( operations_both(operations, operation_continue) ) + { + if ( op1 != operation_union + || op2 != operation_union + || ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) ) + { + // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE! + bool opposite = inters.d_info().opposite; + + op1 = operation_intersection; + op2 = opposite ? operation_union : operation_intersection; + } + } + else + { + BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union)); + //op1 = operation_union; + //op2 = operation_union; + } + + return true; + } + // else do nothing - shouldn't be handled this way + } + else if ( last1 ) + { +#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR + // may this give false positives for INTs? + typename IntersectionResult::point_type const& + inters_pt = inters.i_info().intersections[ip_index]; + BOOST_GEOMETRY_ASSERT(ip_i2 == equals::equals_point_point(i2, inters_pt)); + BOOST_GEOMETRY_ASSERT(ip_j2 == equals::equals_point_point(j2, inters_pt)); +#endif + if ( ip_i2 ) + { + // don't output this IP - for the first point of other geometry segment + op1 = operation_none; + op2 = operation_none; + return true; + } + else if ( ip_j2 ) + { + side_calculator + side_calc(ri2, rj1, ri1, ri2, rj2, rk2); + + std::pair + operations = operations_of_equal(side_calc); + +// TODO: must the above be calculated? +// wouldn't it be enough to check if segments are collinear? + + if ( operations_both(operations, operation_continue) ) + { + if ( op1 != operation_blocked + || op2 != operation_union + || ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) ) + { + // THIS IS WRT THE ORIGINAL SEGMENTS! NOT THE ONES ABOVE! + bool second_going_out = inters.i_info().count > 1; + + op1 = operation_blocked; + op2 = second_going_out ? operation_union : operation_intersection; + } + } + else + { + BOOST_GEOMETRY_ASSERT(operations_combination(operations, operation_intersection, operation_union)); + //op1 = operation_blocked; + //op2 = operation_union; + } + + return true; + } + // else do nothing - shouldn't be handled this way + } + // else do nothing - shouldn't be handled this way + } + + return false; + } + + static inline method_type endpoint_ip_method(bool ip_pi, bool ip_pj, bool ip_qi, bool ip_qj) + { + if ( (ip_pi || ip_pj) && (ip_qi || ip_qj) ) + return method_touch; + else + return method_touch_interior; + } + + static inline turn_position ip_position(bool is_ip_first_i, bool is_ip_last_j) + { + return is_ip_first_i ? position_front : + ( is_ip_last_j ? position_back : position_middle ); + } + + template + static inline void assign(Point1 const& pi, Point2 const& qi, + IntersectionResult const& result, + unsigned int ip_index, + method_type method, + operation_type op0, operation_type op1, + turn_position pos0, turn_position pos1, + bool is_p_first_ip, bool is_q_first_ip, + bool is_p_spike, bool is_q_spike, + TurnInfo const& tp_model, + OutputIterator out) + { + TurnInfo tp = tp_model; + + //geometry::convert(ip, tp.point); + //tp.method = method; + base_turn_handler::assign_point(tp, method, result.template get<0>(), ip_index); + + tp.operations[0].operation = op0; + tp.operations[1].operation = op1; + tp.operations[0].position = pos0; + tp.operations[1].position = pos1; + + if ( result.template get<0>().count > 1 ) + { + // NOTE: is_collinear is NOT set for the first endpoint + // for which there is no preceding segment + + //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); + if ( ! is_p_first_ip ) + { + tp.operations[0].is_collinear = op0 != operation_intersection + || is_p_spike; + } + + if ( ! is_q_first_ip ) + { + tp.operations[1].is_collinear = op1 != operation_intersection + || is_q_spike; + } + } + else //if ( result.template get<0>().count == 1 ) + { + if ( op0 == operation_blocked && op1 == operation_intersection ) + { + tp.operations[0].is_collinear = true; + } + else if ( op0 == operation_intersection && op1 == operation_blocked ) + { + tp.operations[1].is_collinear = true; + } + } + + // TODO: this should get an intersection_info, which is unavailable here + // Because the assign_null policy accepts any structure, we pass the result instead for now + AssignPolicy::apply(tp, pi, qi, result); + *out++ = tp; + } + + template + static inline std::pair operations_of_equal(SidePolicy const& side) + { + int const side_pk_q2 = side.pk_wrt_q2(); + int const side_pk_p = side.pk_wrt_p1(); + int const side_qk_p = side.qk_wrt_p1(); + + // If pk is collinear with qj-qk, they continue collinearly. + // This can be on either side of p1 (== q1), or collinear + // The second condition checks if they do not continue + // oppositely + if ( side_pk_q2 == 0 && side_pk_p == side_qk_p ) + { + return std::make_pair(operation_continue, operation_continue); + } + + // If they turn to same side (not opposite sides) + if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) ) + { + // If pk is left of q2 or collinear: p: union, q: intersection + if ( side_pk_q2 != -1 ) + { + return std::make_pair(operation_union, operation_intersection); + } + else + { + return std::make_pair(operation_intersection, operation_union); + } + } + else + { + // They turn opposite sides. If p turns left (or collinear), + // p: union, q: intersection + if ( side_pk_p != -1 ) + { + return std::make_pair(operation_union, operation_intersection); + } + else + { + return std::make_pair(operation_intersection, operation_union); + } + } + } + + static inline bool operations_both( + std::pair const& operations, + operation_type const op) + { + return operations.first == op && operations.second == op; + } + + static inline bool operations_combination( + std::pair const& operations, + operation_type const op1, operation_type const op2) + { + return ( operations.first == op1 && operations.second == op2 ) + || ( operations.first == op2 && operations.second == op1 ); + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp new file mode 100755 index 0000000000..772f44bc1b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp @@ -0,0 +1,355 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { + +enum turn_position { position_middle, position_front, position_back }; + +template +struct turn_operation_linear + : public turn_operation +{ + turn_operation_linear() + : position(position_middle) + , is_collinear(false) + {} + + turn_position position; + bool is_collinear; // valid only for Linear geometry +}; + +template +struct side_calculator +{ + // This strategy should be the same as side strategy defined in + // intersection_strategies<> which is used in various places + // of the library + typedef typename strategy::side::services::default_strategy + < + TurnPointCSTag + >::type side; + + inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk, + Qi const& qi, Qj const& qj, Qk const& qk) + : m_pi(pi), m_pj(pj), m_pk(pk) + , m_qi(qi), m_qj(qj), m_qk(qk) + {} + + inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); } + inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); } + inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); } + inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); } + + inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); } + inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); } + + Pi const& m_pi; + Pj const& m_pj; + Pk const& m_pk; + Qi const& m_qi; + Qj const& m_qj; + Qk const& m_qk; +}; + +template +struct robust_points +{ + typedef typename geometry::robust_point_type + < + Point1, RobustPolicy + >::type robust_point1_type; + + // TODO: define robust_point2_type using Point2? + typedef robust_point1_type robust_point2_type; + + inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + RobustPolicy const& robust_policy) + { + geometry::recalculate(m_rpi, pi, robust_policy); + geometry::recalculate(m_rpj, pj, robust_policy); + geometry::recalculate(m_rpk, pk, robust_policy); + geometry::recalculate(m_rqi, qi, robust_policy); + geometry::recalculate(m_rqj, qj, robust_policy); + geometry::recalculate(m_rqk, qk, robust_policy); + } + + robust_point1_type m_rpi, m_rpj, m_rpk; + robust_point2_type m_rqi, m_rqj, m_rqk; +}; + +template +class intersection_info_base + : private robust_points +{ + typedef robust_points base; + +public: + typedef Point1 point1_type; + typedef Point2 point2_type; + + typedef typename base::robust_point1_type robust_point1_type; + typedef typename base::robust_point2_type robust_point2_type; + + typedef typename cs_tag::type cs_tag; + + typedef side_calculator side_calculator_type; + + intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + RobustPolicy const& robust_policy) + : base(pi, pj, pk, qi, qj, qk, robust_policy) + , m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk, + base::m_rqi, base::m_rqj, base::m_rqk) + , m_pi(pi), m_pj(pj), m_pk(pk) + , m_qi(qi), m_qj(qj), m_qk(qk) + {} + + inline Point1 const& pi() const { return m_pi; } + inline Point1 const& pj() const { return m_pj; } + inline Point1 const& pk() const { return m_pk; } + + inline Point2 const& qi() const { return m_qi; } + inline Point2 const& qj() const { return m_qj; } + inline Point2 const& qk() const { return m_qk; } + + inline robust_point1_type const& rpi() const { return base::m_rpi; } + inline robust_point1_type const& rpj() const { return base::m_rpj; } + inline robust_point1_type const& rpk() const { return base::m_rpk; } + + inline robust_point2_type const& rqi() const { return base::m_rqi; } + inline robust_point2_type const& rqj() const { return base::m_rqj; } + inline robust_point2_type const& rqk() const { return base::m_rqk; } + + inline side_calculator_type const& sides() const { return m_side_calc; } + +private: + side_calculator_type m_side_calc; + + point1_type const& m_pi; + point1_type const& m_pj; + point1_type const& m_pk; + point2_type const& m_qi; + point2_type const& m_qj; + point2_type const& m_qk; +}; + +template +class intersection_info_base +{ +public: + typedef Point1 point1_type; + typedef Point2 point2_type; + + typedef Point1 robust_point1_type; + typedef Point2 robust_point2_type; + + typedef typename cs_tag::type cs_tag; + + typedef side_calculator side_calculator_type; + + intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + no_rescale_policy const& /*robust_policy*/) + : m_side_calc(pi, pj, pk, qi, qj, qk) + {} + + inline Point1 const& pi() const { return m_side_calc.m_pi; } + inline Point1 const& pj() const { return m_side_calc.m_pj; } + inline Point1 const& pk() const { return m_side_calc.m_pk; } + + inline Point2 const& qi() const { return m_side_calc.m_qi; } + inline Point2 const& qj() const { return m_side_calc.m_qj; } + inline Point2 const& qk() const { return m_side_calc.m_qk; } + + inline Point1 const& rpi() const { return pi(); } + inline Point1 const& rpj() const { return pj(); } + inline Point1 const& rpk() const { return pk(); } + + inline Point2 const& rqi() const { return qi(); } + inline Point2 const& rqj() const { return qj(); } + inline Point2 const& rqk() const { return qk(); } + + inline side_calculator_type const& sides() const { return m_side_calc; } + +private: + side_calculator_type m_side_calc; +}; + + +template +< + typename Point1, + typename Point2, + typename TurnPoint, + typename RobustPolicy +> +class intersection_info + : public intersection_info_base +{ + typedef intersection_info_base base; + + typedef typename intersection_strategies + < + typename base::cs_tag, + Point1, + Point2, + TurnPoint, + RobustPolicy + >::segment_intersection_strategy_type strategy; + +public: + typedef model::referring_segment segment_type1; + typedef model::referring_segment segment_type2; + typedef typename base::side_calculator_type side_calculator_type; + + typedef typename strategy::return_type result_type; + typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info + typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info + + intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + RobustPolicy const& robust_policy) + : base(pi, pj, pk, qi, qj, qk, robust_policy) + , m_result(strategy::apply(segment_type1(pi, pj), + segment_type2(qi, qj), + robust_policy, + base::rpi(), base::rpj(), + base::rqi(), base::rqj())) + , m_robust_policy(robust_policy) + {} + + inline result_type const& result() const { return m_result; } + inline i_info_type const& i_info() const { return m_result.template get<0>(); } + inline d_info_type const& d_info() const { return m_result.template get<1>(); } + + // TODO: it's more like is_spike_ip_p + inline bool is_spike_p() const + { + if (base::sides().pk_wrt_p1() == 0) + { + if (! is_ip_j<0>()) + { + return false; + } + + int const qk_p1 = base::sides().qk_wrt_p1(); + int const qk_p2 = base::sides().qk_wrt_p2(); + + if (qk_p1 == -qk_p2) + { + if (qk_p1 == 0) + { + return is_spike_of_collinear(base::pi(), base::pj(), + base::pk()); + } + + return true; + } + } + + return false; + } + + // TODO: it's more like is_spike_ip_q + inline bool is_spike_q() const + { + if (base::sides().qk_wrt_q1() == 0) + { + if (! is_ip_j<1>()) + { + return false; + } + + int const pk_q1 = base::sides().pk_wrt_q1(); + int const pk_q2 = base::sides().pk_wrt_q2(); + + if (pk_q1 == -pk_q2) + { + if (pk_q1 == 0) + { + return is_spike_of_collinear(base::qi(), base::qj(), + base::qk()); + } + + return true; + } + } + + return false; + } + +private: + template + inline bool is_spike_of_collinear(Point const& i, Point const& j, + Point const& k) const + { + typedef model::referring_segment seg; + + typedef intersection_strategies + < + typename base::cs_tag, Point, Point, Point, RobustPolicy + > si; + + typedef typename si::segment_intersection_strategy_type strategy; + + typename strategy::return_type result + = strategy::apply(seg(i, j), seg(j, k), m_robust_policy); + + return result.template get<0>().count == 2; + } + + template + bool is_ip_j() const + { + int arrival = d_info().arrival[OpId]; + bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0; + + if (same_dirs) + { + if (i_info().count == 2) + { + return arrival != -1; + } + else + { + return arrival == 0; + } + } + else + { + return arrival == 1; + } + } + + result_type m_result; + RobustPolicy const& m_robust_policy; +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp new file mode 100755 index 0000000000..316ae1475b --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp @@ -0,0 +1,878 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP + +#include + +#include + +#include +#include + +// TEMP, for spikes detector +//#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { + +template +struct get_turn_info_linear_areal +{ + // Currently only Linear spikes are handled + // Areal spikes are ignored + static const bool handle_spikes = true; + + template + < + typename Point1, + typename Point2, + typename TurnInfo, + typename RobustPolicy, + typename OutputIterator + > + static inline OutputIterator apply( + Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, + TurnInfo const& tp_model, + RobustPolicy const& robust_policy, + OutputIterator out) + { + typedef intersection_info + inters_info; + + inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); + + char const method = inters.d_info().how; + + // Copy, to copy possibly extended fields + TurnInfo tp = tp_model; + + // Select method and apply + switch(method) + { + case 'a' : // collinear, "at" + case 'f' : // collinear, "from" + case 's' : // starts from the middle + get_turn_info_for_endpoint( + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_none, out); + break; + + case 'd' : // disjoint: never do anything + break; + + case 'm' : + { + if ( get_turn_info_for_endpoint( + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_touch_interior, out) ) + { + // do nothing + } + else + { + typedef touch_interior + < + TurnInfo + > policy; + + // If Q (1) arrives (1) + if ( inters.d_info().arrival[1] == 1 ) + { + policy::template apply<0>(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), + inters.sides()); + } + else + { + // Swap p/q + side_calculator + < + typename inters_info::cs_tag, + typename inters_info::robust_point2_type, + typename inters_info::robust_point1_type + > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk()); + policy::template apply<1>(qi, qj, qk, pi, pj, pk, + tp, inters.i_info(), inters.d_info(), + swapped_side_calc); + } + + if ( tp.operations[1].operation == operation_blocked ) + { + tp.operations[0].is_collinear = true; + } + + replace_method_and_operations_tm(tp.method, + tp.operations[0].operation, + tp.operations[1].operation); + + // this function assumes that 'u' must be set for a spike + calculate_spike_operation(tp.operations[0].operation, + inters, is_p_last); + + AssignPolicy::apply(tp, pi, qi, inters); + + *out++ = tp; + } + } + break; + case 'i' : + { + crosses::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info()); + + replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + break; + case 't' : + { + // Both touch (both arrive there) + if ( get_turn_info_for_endpoint( + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_touch, out) ) + { + // do nothing + } + else + { + touch::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + if ( tp.operations[1].operation == operation_blocked ) + { + tp.operations[0].is_collinear = true; + } + + // workarounds for touch<> not taking spikes into account starts here + // those was discovered empirically + // touch<> is not symmetrical! + // P spikes and Q spikes may produce various operations! + // Only P spikes are valid for L/A + // TODO: this is not optimal solution - think about rewriting touch<> + + if ( tp.operations[0].operation == operation_blocked ) + { + // a spike on P on the same line with Q1 + if ( inters.is_spike_p() ) + { + if ( inters.sides().qk_wrt_p1() == 0 ) + { + tp.operations[0].is_collinear = true; + } + else + { + tp.operations[0].operation = operation_union; + } + } + } + else if ( tp.operations[0].operation == operation_continue + && tp.operations[1].operation == operation_continue ) + { + // P spike on the same line with Q2 (opposite) + if ( inters.sides().pk_wrt_q1() == -inters.sides().qk_wrt_q1() + && inters.is_spike_p() ) + { + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_union; + } + } + else if ( tp.operations[0].operation == operation_none + && tp.operations[1].operation == operation_none ) + { + // spike not handled by touch<> + if ( inters.is_spike_p() ) + { + tp.operations[0].operation = operation_intersection; + tp.operations[1].operation = operation_union; + + if ( inters.sides().pk_wrt_q2() == 0 ) + { + tp.operations[0].operation = operation_continue; // will be converted to i + tp.operations[0].is_collinear = true; + } + } + } + + // workarounds for touch<> not taking spikes into account ends here + + replace_method_and_operations_tm(tp.method, + tp.operations[0].operation, + tp.operations[1].operation); + + bool ignore_spike + = calculate_spike_operation(tp.operations[0].operation, + inters, is_p_last); + +// TODO: move this into the append_xxx and call for each turn? + AssignPolicy::apply(tp, pi, qi, inters); + + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) + || ignore_spike + || ! append_opposite_spikes( // for 'i' or 'c' i??? + tp, inters, is_p_last, is_q_last, out) ) + { + *out++ = tp; + } + } + } + break; + case 'e': + { + if ( get_turn_info_for_endpoint( + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_equal, out) ) + { + // do nothing + } + else + { + tp.operations[0].is_collinear = true; + + if ( ! inters.d_info().opposite ) + { + // Both equal + // or collinear-and-ending at intersection point + equal::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + turn_transformer_ec transformer(method_touch); + transformer(tp); + +// TODO: move this into the append_xxx and call for each turn? + AssignPolicy::apply(tp, pi, qi, inters); + + // conditionally handle spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) + || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, + method_touch, append_equal, out) ) + { + *out++ = tp; // no spikes + } + } + else + { + equal_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, qi, + tp, out, inters); + } + } + } + break; + case 'c' : + { + // Collinear + if ( get_turn_info_for_endpoint( + pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_collinear, out) ) + { + // do nothing + } + else + { + tp.operations[0].is_collinear = true; + + if ( ! inters.d_info().opposite ) + { + method_type method_replace = method_touch_interior; + append_version_c version = append_collinear; + + if ( inters.d_info().arrival[0] == 0 ) + { + // Collinear, but similar thus handled as equal + equal::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + method_replace = method_touch; + version = append_equal; + } + else + { + collinear::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + //method_replace = method_touch_interior; + //version = append_collinear; + } + + turn_transformer_ec transformer(method_replace); + transformer(tp); + +// TODO: move this into the append_xxx and call for each turn? + AssignPolicy::apply(tp, pi, qi, inters); + + // conditionally handle spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) + || ! append_collinear_spikes(tp, inters, is_p_last, is_q_last, + method_replace, version, out) ) + { + // no spikes + *out++ = tp; + } + } + else + { + // Is this always 'm' ? + turn_transformer_ec transformer(method_touch_interior); + + // conditionally handle spikes + if ( BOOST_GEOMETRY_CONDITION(handle_spikes) ) + { + append_opposite_spikes( + tp, inters, is_p_last, is_q_last, out); + } + + // TODO: ignore for spikes? + // E.g. pass is_p_valid = !is_p_last && !is_pj_spike, + // the same with is_q_valid + + collinear_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, pj, pk, qi, qj, qk, + tp, out, inters, + inters.sides(), transformer, + !is_p_last, true); // qk is always valid + } + } + } + break; + case '0' : + { + // degenerate points + if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) + { + only_convert::apply(tp, inters.i_info()); + + if ( is_p_first + && equals::equals_point_point(pi, tp.point) ) + { + tp.operations[0].position = position_front; + } + else if ( is_p_last + && equals::equals_point_point(pj, tp.point) ) + { + tp.operations[0].position = position_back; + } + // tp.operations[1].position = position_middle; + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + } + break; + default : + { +#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS) + std::cout << "TURN: Unknown method: " << method << std::endl; +#endif +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw turn_info_exception(method); +#endif + } + break; + } + + return out; + } + + template + static inline bool calculate_spike_operation(Operation & op, + IntersectionInfo const& inters, + bool is_p_last) + { + bool is_p_spike = ( op == operation_union || op == operation_intersection ) + && ! is_p_last + && inters.is_spike_p(); + + if ( is_p_spike ) + { + int const pk_q1 = inters.sides().pk_wrt_q1(); + + bool going_in = pk_q1 < 0; // Pk on the right + bool going_out = pk_q1 > 0; // Pk on the left + + int const qk_q1 = inters.sides().qk_wrt_q1(); + + // special cases + if ( qk_q1 < 0 ) // Q turning R + { + // spike on the edge point + // if it's already known that the spike is going out this musn't be checked + if ( ! going_out + && equals::equals_point_point(inters.rpj(), inters.rqj()) ) + { + int const pk_q2 = inters.sides().pk_wrt_q2(); + going_in = pk_q1 < 0 && pk_q2 < 0; // Pk on the right of both + going_out = pk_q1 > 0 || pk_q2 > 0; // Pk on the left of one of them + } + } + else if ( qk_q1 > 0 ) // Q turning L + { + // spike on the edge point + // if it's already known that the spike is going in this musn't be checked + if ( ! going_in + && equals::equals_point_point(inters.rpj(), inters.rqj()) ) + { + int const pk_q2 = inters.sides().pk_wrt_q2(); + going_in = pk_q1 < 0 || pk_q2 < 0; // Pk on the right of one of them + going_out = pk_q1 > 0 && pk_q2 > 0; // Pk on the left of both + } + } + + if ( going_in ) + { + op = operation_intersection; + return true; + } + else if ( going_out ) + { + op = operation_union; + return true; + } + } + + return false; + } + + enum append_version_c { append_equal, append_collinear }; + + template + static inline bool append_collinear_spikes(TurnInfo & tp, + IntersectionInfo const& inters, + bool is_p_last, bool /*is_q_last*/, + method_type method, append_version_c version, + OutIt out) + { + // method == touch || touch_interior + // both position == middle + + bool is_p_spike = ( version == append_equal ? + ( tp.operations[0].operation == operation_union + || tp.operations[0].operation == operation_intersection ) : + tp.operations[0].operation == operation_continue ) + && ! is_p_last + && inters.is_spike_p(); + + // TODO: throw an exception for spike in Areal? + /*bool is_q_spike = tp.operations[1].operation == operation_continue + && inters.is_spike_q(); + + // both are collinear spikes on the same IP, we can just follow both + if ( is_p_spike && is_q_spike ) + { + return false; + } + // spike on Linear - it's turning back on the boundary of Areal + else*/ + if ( is_p_spike ) + { + tp.method = method; + tp.operations[0].operation = operation_blocked; + tp.operations[1].operation = operation_union; + *out++ = tp; + tp.operations[0].operation = operation_continue; // boundary + //tp.operations[1].operation = operation_union; + *out++ = tp; + + return true; + } + // spike on Areal - Linear is going outside + /*else if ( is_q_spike ) + { + tp.method = method; + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_continue; + *out++ = tp; + *out++ = tp; + + return true; + }*/ + + return false; + } + + enum append_version_o { append_touches, append_collinear_opposite }; + + template + static inline bool append_opposite_spikes(TurnInfo & tp, + IntersectionInfo const& inters, + bool is_p_last, bool /*is_q_last*/, + OutIt out) + { + static const bool is_version_touches = (Version == append_touches); + + bool is_p_spike = ( is_version_touches ? + ( tp.operations[0].operation == operation_continue + || tp.operations[0].operation == operation_intersection ) : // i ??? + true ) + && ! is_p_last + && inters.is_spike_p(); + + // TODO: throw an exception for spike in Areal? + /*bool is_q_spike = ( ( Version == append_touches + && tp.operations[1].operation == operation_continue ) + || ( Version == append_collinear_opposite + && tp.operations[1].operation == operation_none ) ) + && inters.is_spike_q(); + + if ( is_p_spike && is_q_spike ) + { + // u/u or nothing? + return false; + } + else*/ + if ( is_p_spike ) + { + if ( BOOST_GEOMETRY_CONDITION(is_version_touches) + || inters.d_info().arrival[0] == 1 ) + { + if ( BOOST_GEOMETRY_CONDITION(is_version_touches) ) + { + tp.operations[0].is_collinear = true; + //tp.operations[1].is_collinear = false; + tp.method = method_touch; + } + else + { + tp.operations[0].is_collinear = true; + //tp.operations[1].is_collinear = false; + + BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1); + base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1); + + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); + } + + tp.operations[0].operation = operation_blocked; + tp.operations[1].operation = operation_continue; // boundary + *out++ = tp; + tp.operations[0].operation = operation_continue; // boundary + //tp.operations[1].operation = operation_continue; // boundary + *out++ = tp; + + return true; + } + } + /*else if ( is_q_spike ) + { + tp.operations[0].is_collinear = true; + tp.method = is_version_touches ? method_touch : method_touch_interior; + tp.operations[0].operation = operation_continue; + tp.operations[1].operation = operation_continue; // boundary + *out++ = tp; + *out++ = tp; + + return true; + }*/ + + return false; + } + + static inline void replace_method_and_operations_tm(method_type & method, + operation_type & op0, + operation_type & op1) + { + if ( op0 == operation_blocked && op1 == operation_blocked ) + { + // NOTE: probably only if methods are WRT IPs, not segments! + method = (method == method_touch ? method_equal : method_collinear); + } + + // Assuming G1 is always Linear + if ( op0 == operation_blocked ) + { + op0 = operation_continue; + } + + if ( op1 == operation_blocked ) + { + op1 = operation_continue; + } + else if ( op1 == operation_intersection ) + { + op1 = operation_union; + } + + // spikes in 'm' + if ( method == method_error ) + { + method = method_touch_interior; + op0 = operation_union; + op1 = operation_union; + } + } + + template + class turn_transformer_ec + { + public: + explicit turn_transformer_ec(method_type method_t_or_m) + : m_method(method_t_or_m) + {} + + template + void operator()(Turn & turn) const + { + operation_type & op0 = turn.operations[0].operation; + operation_type & op1 = turn.operations[1].operation; + + // NOTE: probably only if methods are WRT IPs, not segments! + if ( BOOST_GEOMETRY_CONDITION(IsFront) + || op0 == operation_intersection || op0 == operation_union + || op1 == operation_intersection || op1 == operation_union ) + { + turn.method = m_method; + } + + turn.operations[0].is_collinear = op0 != operation_blocked; + + // Assuming G1 is always Linear + if ( op0 == operation_blocked ) + { + op0 = operation_continue; + } + + if ( op1 == operation_blocked ) + { + op1 = operation_continue; + } + else if ( op1 == operation_intersection ) + { + op1 = operation_union; + } + } + + private: + method_type m_method; + }; + + static inline void replace_operations_i(operation_type & /*op0*/, operation_type & op1) + { + // assuming Linear is always the first one + op1 = operation_union; + } + + // NOTE: Spikes may NOT be handled for Linear endpoints because it's not + // possible to define a spike on an endpoint. Areal geometries must + // NOT have spikes at all. One thing that could be done is to throw + // an exception when spike is detected in Areal geometry. + + template + static inline bool get_turn_info_for_endpoint( + Point1 const& pi, Point1 const& /*pj*/, Point1 const& /*pk*/, + Point2 const& qi, Point2 const& /*qj*/, Point2 const& /*qk*/, + bool is_p_first, bool is_p_last, + bool /*is_q_first*/, bool is_q_last, + TurnInfo const& tp_model, + IntersectionInfo const& inters, + method_type /*method*/, + OutputIterator out) + { + namespace ov = overlay; + typedef ov::get_turn_info_for_endpoint get_info_e; + + const std::size_t ip_count = inters.i_info().count; + // no intersection points + if ( ip_count == 0 ) + return false; + + if ( !is_p_first && !is_p_last ) + return false; + +// TODO: is_q_last could probably be replaced by false and removed from parameters + + linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last); + linear_intersections::ip_info const& ip0 = intersections.template get<0>(); + linear_intersections::ip_info const& ip1 = intersections.template get<1>(); + + const bool opposite = inters.d_info().opposite; + + // ANALYSE AND ASSIGN FIRST + + // IP on the first point of Linear Geometry + bool was_first_point_handled = false; + if ( BOOST_GEOMETRY_CONDITION(EnableFirst) + && is_p_first && ip0.is_pi && !ip0.is_qi ) // !q0i prevents duplication + { + TurnInfo tp = tp_model; + tp.operations[0].position = position_front; + tp.operations[1].position = position_middle; + + if ( opposite ) // opposite -> collinear + { + tp.operations[0].operation = operation_continue; + tp.operations[1].operation = operation_union; + tp.method = ip0.is_qj ? method_touch : method_touch_interior; + } + else + { + method_type replaced_method = method_touch_interior; + + if ( ip0.is_qj ) + { + side_calculator + < + typename IntersectionInfo::cs_tag, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point2_type + > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), + inters.rqi(), inters.rqj(), inters.rqk()); + + std::pair + operations = get_info_e::operations_of_equal(side_calc); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; + + replaced_method = method_touch; + } + else + { + side_calculator + < + typename IntersectionInfo::cs_tag, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type + > side_calc(inters.rqi(), inters.rpi(), inters.rpj(), + inters.rqi(), inters.rpi(), inters.rqj()); + + std::pair + operations = get_info_e::operations_of_equal(side_calc); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; + } + + turn_transformer_ec transformer(replaced_method); + transformer(tp); + } + + // equals<> or collinear<> will assign the second point, + // we'd like to assign the first one + base_turn_handler::assign_point(tp, tp.method, inters.i_info(), 0); + + // NOTE: is_collinear is not set for the first endpoint of L + // for which there is no preceding segment + // here is_p_first_ip == true + tp.operations[0].is_collinear = false; + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + + was_first_point_handled = true; + } + + // ANALYSE AND ASSIGN LAST + + // IP on the last point of Linear Geometry + if ( BOOST_GEOMETRY_CONDITION(EnableLast) + && is_p_last + && ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication + { + TurnInfo tp = tp_model; + + if ( inters.i_info().count > 1 ) + { + //BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 ); + tp.operations[0].is_collinear = true; + tp.operations[1].operation = opposite ? operation_continue : operation_union; + } + else //if ( result.template get<0>().count == 1 ) + { + side_calculator + < + typename IntersectionInfo::cs_tag, + typename IntersectionInfo::robust_point1_type, + typename IntersectionInfo::robust_point2_type, + typename IntersectionInfo::robust_point2_type + > side_calc(inters.rqi(), inters.rpj(), inters.rpi(), + inters.rqi(), inters.rqj(), inters.rqk()); + + std::pair + operations = get_info_e::operations_of_equal(side_calc); + + tp.operations[0].operation = operations.first; + tp.operations[1].operation = operations.second; + + turn_transformer_ec transformer(method_none); + transformer(tp); + + tp.operations[0].is_collinear = tp.both(operation_continue); + } + + tp.method = ( ip_count > 1 ? ip1.is_qj : ip0.is_qj ) ? method_touch : method_touch_interior; + tp.operations[0].operation = operation_blocked; + tp.operations[0].position = position_back; + tp.operations[1].position = position_middle; + + // equals<> or collinear<> will assign the second point, + // we'd like to assign the first one + unsigned int ip_index = ip_count > 1 ? 1 : 0; + base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index); + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + + // don't ignore the first IP if the segment is opposite + return !( opposite && ip_count > 1 ) || was_first_point_handled; + } + + // don't ignore anything for now + return false; + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LA_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp new file mode 100755 index 0000000000..60896b4912 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp @@ -0,0 +1,747 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP + +#include + +#include +#include + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { + +template +struct get_turn_info_linear_linear +{ + static const bool handle_spikes = true; + + template + < + typename Point1, + typename Point2, + typename TurnInfo, + typename RobustPolicy, + typename OutputIterator + > + static inline OutputIterator apply( + Point1 const& pi, Point1 const& pj, Point1 const& pk, + Point2 const& qi, Point2 const& qj, Point2 const& qk, + bool is_p_first, bool is_p_last, + bool is_q_first, bool is_q_last, + TurnInfo const& tp_model, + RobustPolicy const& robust_policy, + OutputIterator out) + { + typedef intersection_info + inters_info; + + inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy); + + char const method = inters.d_info().how; + + // Copy, to copy possibly extended fields + TurnInfo tp = tp_model; + + // Select method and apply + switch(method) + { + case 'a' : // collinear, "at" + case 'f' : // collinear, "from" + case 's' : // starts from the middle + get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_none, out); + break; + + case 'd' : // disjoint: never do anything + break; + + case 'm' : + { + if ( get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_touch_interior, out) ) + { + // do nothing + } + else + { + typedef touch_interior + < + TurnInfo + > policy; + + // If Q (1) arrives (1) + if ( inters.d_info().arrival[1] == 1) + { + policy::template apply<0>(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), + inters.sides()); + } + else + { + // Swap p/q + side_calculator + < + typename inters_info::cs_tag, + typename inters_info::robust_point2_type, + typename inters_info::robust_point1_type + > swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(), + inters.rpi(), inters.rpj(), inters.rpk()); + + policy::template apply<1>(qi, qj, qk, pi, pj, pk, + tp, inters.i_info(), inters.d_info(), + swapped_side_calc); + } + + if ( tp.operations[0].operation == operation_blocked ) + { + tp.operations[1].is_collinear = true; + } + if ( tp.operations[1].operation == operation_blocked ) + { + tp.operations[0].is_collinear = true; + } + + replace_method_and_operations_tm(tp.method, + tp.operations[0].operation, + tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + } + break; + case 'i' : + { + crosses::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info()); + + replace_operations_i(tp.operations[0].operation, tp.operations[1].operation); + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + break; + case 't' : + { + // Both touch (both arrive there) + if ( get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_touch, out) ) + { + // do nothing + } + else + { + touch::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + // workarounds for touch<> not taking spikes into account starts here + // those was discovered empirically + // touch<> is not symmetrical! + // P spikes and Q spikes may produce various operations! + // TODO: this is not optimal solution - think about rewriting touch<> + + if ( tp.operations[0].operation == operation_blocked + && tp.operations[1].operation == operation_blocked ) + { + // two touching spikes on the same line + if ( inters.is_spike_p() && inters.is_spike_q() ) + { + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_union; + } + else + { + tp.operations[0].is_collinear = true; + tp.operations[1].is_collinear = true; + } + } + else if ( tp.operations[0].operation == operation_blocked ) + { + // a spike on P on the same line with Q1 + if ( inters.is_spike_p() ) + { + if ( inters.sides().qk_wrt_p1() == 0 ) + { + tp.operations[0].is_collinear = true; + } + else + { + tp.operations[0].operation = operation_union; + } + } + else + { + tp.operations[1].is_collinear = true; + } + } + else if ( tp.operations[1].operation == operation_blocked ) + { + // a spike on Q on the same line with P1 + if ( inters.is_spike_q() ) + { + if ( inters.sides().pk_wrt_q1() == 0 ) + { + tp.operations[1].is_collinear = true; + } + else + { + tp.operations[1].operation = operation_union; + } + } + else + { + tp.operations[0].is_collinear = true; + } + } + else if ( tp.operations[0].operation == operation_continue + && tp.operations[1].operation == operation_continue ) + { + // P spike on the same line with Q2 (opposite) + if ( inters.sides().pk_wrt_q1() == -inters.sides().qk_wrt_q1() + && inters.is_spike_p() ) + { + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_union; + } + } + else if ( tp.operations[0].operation == operation_none + && tp.operations[1].operation == operation_none ) + { + // spike not handled by touch<> + bool const is_p = inters.is_spike_p(); + bool const is_q = inters.is_spike_q(); + + if ( is_p || is_q ) + { + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_union; + + if ( inters.sides().pk_wrt_q2() == 0 ) + { + tp.operations[0].operation = operation_continue; // will be converted to i + if ( is_p ) + { + tp.operations[0].is_collinear = true; + } + } + + if ( inters.sides().qk_wrt_p2() == 0 ) + { + tp.operations[1].operation = operation_continue; // will be converted to i + if ( is_q ) + { + tp.operations[1].is_collinear = true; + } + } + } + } + + // workarounds for touch<> not taking spikes into account ends here + + replace_method_and_operations_tm(tp.method, + tp.operations[0].operation, + tp.operations[1].operation); + +// TODO: move this into the append_xxx and call for each turn? + AssignPolicy::apply(tp, pi, qi, inters); + + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) + || ! append_opposite_spikes(tp, inters, + is_p_last, is_q_last, + out) ) + { + *out++ = tp; + } + } + } + break; + case 'e': + { + if ( get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_equal, out) ) + { + // do nothing + } + else + { + tp.operations[0].is_collinear = true; + tp.operations[1].is_collinear = true; + + if ( ! inters.d_info().opposite ) + { + // Both equal + // or collinear-and-ending at intersection point + equal::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + operation_type spike_op + = ( tp.operations[0].operation != operation_continue + || tp.operations[1].operation != operation_continue ) ? + operation_union : + operation_continue; + + // transform turn + turn_transformer_ec transformer(method_touch); + transformer(tp); + +// TODO: move this into the append_xxx and call for each turn? + AssignPolicy::apply(tp, pi, qi, inters); + + // conditionally handle spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) + || ! append_collinear_spikes(tp, inters, + is_p_last, is_q_last, + method_touch, spike_op, + out) ) + { + *out++ = tp; // no spikes + } + } + else + { + // TODO: ignore for spikes or generate something else than opposite? + + equal_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, qi, tp, out, inters); + } + } + } + break; + case 'c' : + { + // Collinear + if ( get_turn_info_for_endpoint + ::apply(pi, pj, pk, qi, qj, qk, + is_p_first, is_p_last, is_q_first, is_q_last, + tp_model, inters, method_collinear, out) ) + { + // do nothing + } + else + { + // NOTE: this is for spikes since those are set in the turn_transformer_ec + tp.operations[0].is_collinear = true; + tp.operations[1].is_collinear = true; + + if ( ! inters.d_info().opposite ) + { + method_type method_replace = method_touch_interior; + operation_type spike_op = operation_continue; + + if ( inters.d_info().arrival[0] == 0 ) + { + // Collinear, but similar thus handled as equal + equal::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + method_replace = method_touch; + if ( tp.operations[0].operation != operation_continue + || tp.operations[1].operation != operation_continue ) + { + spike_op = operation_union; + } + } + else + { + collinear::apply(pi, pj, pk, qi, qj, qk, + tp, inters.i_info(), inters.d_info(), inters.sides()); + + //method_replace = method_touch_interior; + //spike_op = operation_continue; + } + + // transform turn + turn_transformer_ec transformer(method_replace); + transformer(tp); + +// TODO: move this into the append_xxx and call for each turn? + AssignPolicy::apply(tp, pi, qi, inters); + + // conditionally handle spikes + if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes) + || ! append_collinear_spikes(tp, inters, + is_p_last, is_q_last, + method_replace, spike_op, + out) ) + { + // no spikes + *out++ = tp; + } + } + else + { + // If this always 'm' ? + turn_transformer_ec transformer(method_touch_interior); + + // conditionally handle spikes + if ( BOOST_GEOMETRY_CONDITION(handle_spikes) ) + { + append_opposite_spikes(tp, inters, + is_p_last, is_q_last, + out); + } + + // TODO: ignore for spikes? + // E.g. pass is_p_valid = !is_p_last && !is_pj_spike, + // the same with is_q_valid + + collinear_opposite + < + TurnInfo, + AssignPolicy + >::apply(pi, pj, pk, qi, qj, qk, + tp, out, inters, inters.sides(), + transformer, !is_p_last, !is_q_last); + } + } + } + break; + case '0' : + { + // degenerate points + if ( BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate) ) + { + only_convert::apply(tp, inters.i_info()); + + // if any, only one of those should be true + if ( is_p_first + && equals::equals_point_point(pi, tp.point) ) + { + tp.operations[0].position = position_front; + } + else if ( is_p_last + && equals::equals_point_point(pj, tp.point) ) + { + tp.operations[0].position = position_back; + } + else if ( is_q_first + && equals::equals_point_point(qi, tp.point) ) + { + tp.operations[1].position = position_front; + } + else if ( is_q_last + && equals::equals_point_point(qj, tp.point) ) + { + tp.operations[1].position = position_back; + } + + AssignPolicy::apply(tp, pi, qi, inters); + *out++ = tp; + } + } + break; + default : + { +#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS) + std::cout << "TURN: Unknown method: " << method << std::endl; +#endif +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) + throw turn_info_exception(method); +#endif + } + break; + } + + return out; + } + + template + static inline bool append_collinear_spikes(TurnInfo & tp, + IntersectionInfo const& inters_info, + bool is_p_last, bool is_q_last, + method_type method, operation_type spike_op, + OutIt out) + { + // method == touch || touch_interior + // both position == middle + + bool is_p_spike = tp.operations[0].operation == spike_op + && ! is_p_last + && inters_info.is_spike_p(); + bool is_q_spike = tp.operations[1].operation == spike_op + && ! is_q_last + && inters_info.is_spike_q(); + + if ( is_p_spike && is_q_spike ) + { + if ( tp.method == method_equal + && tp.operations[0].operation == operation_continue + && tp.operations[1].operation == operation_continue ) + { + // treat both non-opposite collinear spikes as no-spikes + return false; + } + + tp.method = method; + tp.operations[0].operation = operation_blocked; + tp.operations[1].operation = operation_blocked; + *out++ = tp; + tp.operations[0].operation = operation_intersection; + tp.operations[1].operation = operation_intersection; + *out++ = tp; + + return true; + } + else if ( is_p_spike ) + { + tp.method = method; + tp.operations[0].operation = operation_blocked; + tp.operations[1].operation = operation_union; + *out++ = tp; + tp.operations[0].operation = operation_intersection; + //tp.operations[1].operation = operation_union; + *out++ = tp; + + return true; + } + else if ( is_q_spike ) + { + tp.method = method; + tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_blocked; + *out++ = tp; + //tp.operations[0].operation = operation_union; + tp.operations[1].operation = operation_intersection; + *out++ = tp; + + return true; + } + + return false; + } + + enum append_version { append_touches, append_collinear_opposite }; + + template + static inline bool append_opposite_spikes(TurnInfo & tp, + IntersectionInfo const& inters, + bool is_p_last, bool is_q_last, + OutIt out) + { + static const bool is_version_touches = (Version == append_touches); + + bool is_p_spike = ( is_version_touches ? + ( tp.operations[0].operation == operation_continue + || tp.operations[0].operation == operation_intersection ) : + true ) + && ! is_p_last + && inters.is_spike_p(); + bool is_q_spike = ( is_version_touches ? + ( tp.operations[1].operation == operation_continue + || tp.operations[1].operation == operation_intersection ) : + true ) + && ! is_q_last + && inters.is_spike_q(); + + bool res = false; + + if ( is_p_spike + && ( BOOST_GEOMETRY_CONDITION(is_version_touches) + || inters.d_info().arrival[0] == 1 ) ) + { + if ( BOOST_GEOMETRY_CONDITION(is_version_touches) ) + { + tp.operations[0].is_collinear = true; + tp.operations[1].is_collinear = false; + tp.method = method_touch; + } + else // Version == append_collinear_opposite + { + tp.operations[0].is_collinear = true; + tp.operations[1].is_collinear = false; + + BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1); + + base_turn_handler::assign_point(tp, method_touch_interior, + inters.i_info(), 1); + + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); + } + + tp.operations[0].operation = operation_blocked; + tp.operations[1].operation = operation_intersection; + *out++ = tp; + tp.operations[0].operation = operation_intersection; + //tp.operations[1].operation = operation_intersection; + *out++ = tp; + + res = true; + } + + if ( is_q_spike + && ( BOOST_GEOMETRY_CONDITION(is_version_touches) + || inters.d_info().arrival[1] == 1 ) ) + { + if ( BOOST_GEOMETRY_CONDITION(is_version_touches) ) + { + tp.operations[0].is_collinear = false; + tp.operations[1].is_collinear = true; + tp.method = method_touch; + } + else // Version == append_collinear_opposite + { + tp.operations[0].is_collinear = false; + tp.operations[1].is_collinear = true; + + BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0); + + base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0); + + AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters); + } + + tp.operations[0].operation = operation_intersection; + tp.operations[1].operation = operation_blocked; + *out++ = tp; + //tp.operations[0].operation = operation_intersection; + tp.operations[1].operation = operation_intersection; + *out++ = tp; + + res = true; + } + + return res; + } + + static inline void replace_method_and_operations_tm(method_type & method, + operation_type & op0, + operation_type & op1) + { + if ( op0 == operation_blocked && op1 == operation_blocked ) + { + // NOTE: probably only if methods are WRT IPs, not segments! + method = (method == method_touch ? method_equal : method_collinear); + op0 = operation_continue; + op1 = operation_continue; + } + else + { + if ( op0 == operation_continue || op0 == operation_blocked ) + { + op0 = operation_intersection; + } + else if ( op0 == operation_intersection ) + { + op0 = operation_union; + } + + if ( op1 == operation_continue || op1 == operation_blocked ) + { + op1 = operation_intersection; + } + else if ( op1 == operation_intersection ) + { + op1 = operation_union; + } + + // spikes in 'm' + if ( method == method_error ) + { + method = method_touch_interior; + op0 = operation_union; + op1 = operation_union; + } + } + } + + class turn_transformer_ec + { + public: + explicit turn_transformer_ec(method_type method_t_or_m) + : m_method(method_t_or_m) + {} + + template + void operator()(Turn & turn) const + { + operation_type & op0 = turn.operations[0].operation; + operation_type & op1 = turn.operations[1].operation; + + BOOST_GEOMETRY_ASSERT(op0 != operation_blocked || op1 != operation_blocked ); + + if ( op0 == operation_blocked ) + { + op0 = operation_intersection; + } + else if ( op0 == operation_intersection ) + { + op0 = operation_union; + } + + if ( op1 == operation_blocked ) + { + op1 = operation_intersection; + } + else if ( op1 == operation_intersection ) + { + op1 = operation_union; + } + + if ( op0 == operation_intersection || op0 == operation_union + || op1 == operation_intersection || op1 == operation_union ) + { + turn.method = m_method; + } + +// TODO: is this correct? +// it's equivalent to comparing to operation_blocked at the beginning of the function + turn.operations[0].is_collinear = op0 != operation_intersection; + turn.operations[1].is_collinear = op1 != operation_intersection; + } + + private: + method_type m_method; + }; + + static inline void replace_operations_i(operation_type & op0, operation_type & op1) + { + if ( op0 == operation_intersection ) + { + op0 = operation_union; + } + + if ( op1 == operation_intersection ) + { + op1 = operation_union; + } + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_LL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp new file mode 100755 index 0000000000..3c2ffcd499 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -0,0 +1,1012 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014, 2016. +// Modifications copyright (c) 2014, 2016 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP + + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION +# include +# include +#endif + + +namespace boost { namespace geometry +{ + +// Silence warning C4127: conditional expression is constant +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace get_turns +{ + + +struct no_interrupt_policy +{ + static bool const enabled = false; + + template + static inline bool apply(Range const&) + { + return false; + } +}; + + +template +< + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, + typename Section1, typename Section2, + typename TurnPolicy +> +class get_turns_in_sections +{ + typedef typename closeable_view + < + typename range_type::type const, + closure::value + >::type cview_type1; + typedef typename closeable_view + < + typename range_type::type const, + closure::value + >::type cview_type2; + + typedef typename reversible_view + < + cview_type1 const, + Reverse1 ? iterate_reverse : iterate_forward + >::type view_type1; + typedef typename reversible_view + < + cview_type2 const, + Reverse2 ? iterate_reverse : iterate_forward + >::type view_type2; + + typedef typename boost::range_iterator + < + view_type1 const + >::type range1_iterator; + + typedef typename boost::range_iterator + < + view_type2 const + >::type range2_iterator; + + + template + static inline bool neighbouring(Section const& section, + signed_size_type index1, signed_size_type index2) + { + // About n-2: + // (square: range_count=5, indices 0,1,2,3 + // -> 0-3 are adjacent, don't check on intersections) + // Also tested for open polygons, and/or duplicates + // About first condition: will be optimized by compiler (static) + // It checks if it is areal (box,ring,(multi)polygon + signed_size_type const n = static_cast(section.range_count); + + boost::ignore_unused_variable_warning(n); + boost::ignore_unused_variable_warning(index1); + boost::ignore_unused_variable_warning(index2); + + return boost::is_same + < + typename tag_cast + < + typename geometry::tag::type, + areal_tag + >::type, + areal_tag + >::value + && index1 == 0 + && index2 >= n - 2 + ; + } + + +public : + // Returns true if terminated, false if interrupted + template + static inline bool apply( + int source_id1, Geometry1 const& geometry1, Section1 const& sec1, + int source_id2, Geometry2 const& geometry2, Section2 const& sec2, + bool skip_larger, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) + { + boost::ignore_unused_variable_warning(interrupt_policy); + + if ((sec1.duplicate && (sec1.count + 1) < sec1.range_count) + || (sec2.duplicate && (sec2.count + 1) < sec2.range_count)) + { + // Skip sections containig only duplicates. + // They are still important (can indicate non-disjointness) + // but they will be found processing adjacent sections. + // Do NOT skip if they are the ONLY section + return true; + } + + cview_type1 cview1(range_by_section(geometry1, sec1)); + cview_type2 cview2(range_by_section(geometry2, sec2)); + view_type1 view1(cview1); + view_type2 view2(cview2); + + range1_iterator begin_range_1 = boost::begin(view1); + range1_iterator end_range_1 = boost::end(view1); + + range2_iterator begin_range_2 = boost::begin(view2); + range2_iterator end_range_2 = boost::end(view2); + + int const dir1 = sec1.directions[0]; + int const dir2 = sec2.directions[0]; + signed_size_type index1 = sec1.begin_index; + signed_size_type ndi1 = sec1.non_duplicate_index; + + bool const same_source = + source_id1 == source_id2 + && sec1.ring_id.multi_index == sec2.ring_id.multi_index + && sec1.ring_id.ring_index == sec2.ring_id.ring_index; + + range1_iterator prev1, it1, end1; + + get_start_point_iterator(sec1, view1, prev1, it1, end1, + index1, ndi1, dir1, sec2.bounding_box, robust_policy); + + // We need a circular iterator because it might run through the closing point. + // One circle is actually enough but this one is just convenient. + ever_circling_iterator next1(begin_range_1, end_range_1, it1, true); + next1++; + + // Walk through section and stop if we exceed the other box + // section 2: [--------------] + // section 1: |----|---|---|---|---| + for (prev1 = it1++, next1++; + it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy); + ++prev1, ++it1, ++index1, ++next1, ++ndi1) + { + ever_circling_iterator nd_next1( + begin_range_1, end_range_1, next1, true); + advance_to_non_duplicate_next(nd_next1, it1, sec1, robust_policy); + + signed_size_type index2 = sec2.begin_index; + signed_size_type ndi2 = sec2.non_duplicate_index; + + range2_iterator prev2, it2, end2; + + get_start_point_iterator(sec2, view2, prev2, it2, end2, + index2, ndi2, dir2, sec1.bounding_box, robust_policy); + ever_circling_iterator next2(begin_range_2, end_range_2, it2, true); + next2++; + + for (prev2 = it2++, next2++; + it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy); + ++prev2, ++it2, ++index2, ++next2, ++ndi2) + { + bool skip = same_source; + if (skip) + { + // If sources are the same (possibly self-intersecting): + // skip if it is a neighbouring segment. + // (including first-last segment + // and two segments with one or more degenerate/duplicate + // (zero-length) segments in between) + + // Also skip if index1 < index2 to avoid getting all + // intersections twice (only do this on same source!) + + skip = (skip_larger && index1 >= index2) + || ndi2 == ndi1 + 1 + || neighbouring(sec1, index1, index2) + ; + } + + if (! skip) + { + // Move to the "non duplicate next" + ever_circling_iterator nd_next2( + begin_range_2, end_range_2, next2, true); + advance_to_non_duplicate_next(nd_next2, it2, sec2, robust_policy); + + typedef typename boost::range_value::type turn_info; + + turn_info ti; + ti.operations[0].seg_id + = segment_identifier(source_id1, sec1.ring_id.multi_index, + sec1.ring_id.ring_index, index1); + ti.operations[1].seg_id + = segment_identifier(source_id2, sec2.ring_id.multi_index, + sec2.ring_id.ring_index, index2); + + std::size_t const size_before = boost::size(turns); + + bool const is_1_first = sec1.is_non_duplicate_first && index1 == sec1.begin_index; + bool const is_1_last = sec1.is_non_duplicate_last && index1+1 >= sec1.end_index; + bool const is_2_first = sec2.is_non_duplicate_first && index2 == sec2.begin_index; + bool const is_2_last = sec2.is_non_duplicate_last && index2+1 >= sec2.end_index; + + TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2, + is_1_first, is_1_last, is_2_first, is_2_last, + ti, robust_policy, std::back_inserter(turns)); + + if (InterruptPolicy::enabled) + { + if (interrupt_policy.apply( + std::make_pair(range::pos(turns, size_before), + boost::end(turns)))) + { + return false; + } + } + } + } + } + return true; + } + + +private : + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; + typedef typename model::referring_segment segment1_type; + typedef typename model::referring_segment segment2_type; + + template + static inline void advance_to_non_duplicate_next(Iterator& next, + RangeIterator const& it, Section const& section, RobustPolicy const& robust_policy) + { + typedef typename robust_point_type::type robust_point_type; + robust_point_type robust_point_from_it; + robust_point_type robust_point_from_next; + geometry::recalculate(robust_point_from_it, *it, robust_policy); + geometry::recalculate(robust_point_from_next, *next, robust_policy); + + // To see where the next segments bend to, in case of touch/intersections + // on end points, we need (in case of degenerate/duplicate points) an extra + // iterator which moves to the REAL next point, so non duplicate. + // This needs an extra comparison (disjoint). + // (Note that within sections, non duplicate points are already asserted, + // by the sectionalize process). + + // So advance to the "non duplicate next" + // (the check is defensive, to avoid endless loops) + std::size_t check = 0; + while(! detail::disjoint::disjoint_point_point + ( + robust_point_from_it, robust_point_from_next + ) + && check++ < section.range_count) + { + next++; + geometry::recalculate(robust_point_from_next, *next, robust_policy); + } + } + + // It is NOT possible to have section-iterators here + // because of the logistics of "index" (the section-iterator automatically + // skips to the begin-point, we loose the index or have to recalculate it) + // So we mimic it here + template + static inline void get_start_point_iterator(Section & section, + Range const& range, + typename boost::range_iterator::type& it, + typename boost::range_iterator::type& prev, + typename boost::range_iterator::type& end, + signed_size_type& index, signed_size_type& ndi, + int dir, Box const& other_bounding_box, RobustPolicy const& robust_policy) + { + it = boost::begin(range) + section.begin_index; + end = boost::begin(range) + section.end_index + 1; + + // Mimic section-iterator: + // Skip to point such that section interects other box + prev = it++; + for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy); + prev = it++, index++, ndi++) + {} + // Go back one step because we want to start completely preceding + it = prev; + } +}; + +template +< + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, + typename Turns, + typename TurnPolicy, + typename RobustPolicy, + typename InterruptPolicy +> +struct section_visitor +{ + int m_source_id1; + Geometry1 const& m_geometry1; + int m_source_id2; + Geometry2 const& m_geometry2; + RobustPolicy const& m_rescale_policy; + Turns& m_turns; + InterruptPolicy& m_interrupt_policy; + + section_visitor(int id1, Geometry1 const& g1, + int id2, Geometry2 const& g2, + RobustPolicy const& robust_policy, + Turns& turns, InterruptPolicy& ip) + : m_source_id1(id1), m_geometry1(g1) + , m_source_id2(id2), m_geometry2(g2) + , m_rescale_policy(robust_policy) + , m_turns(turns) + , m_interrupt_policy(ip) + {} + + template + inline bool apply(Section const& sec1, Section const& sec2) + { + if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box)) + { + return get_turns_in_sections + < + Geometry1, + Geometry2, + Reverse1, Reverse2, + Section, Section, + TurnPolicy + >::apply( + m_source_id1, m_geometry1, sec1, + m_source_id2, m_geometry2, sec2, + false, + m_rescale_policy, + m_turns, m_interrupt_policy); + } + return true; + } + +}; + +template +< + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, + typename TurnPolicy +> +class get_turns_generic +{ + +public: + template + static inline void apply( + int source_id1, Geometry1 const& geometry1, + int source_id2, Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) + { + // First create monotonic sections... + typedef typename boost::range_value::type ip_type; + typedef typename ip_type::point_type point_type; + + typedef model::box + < + typename geometry::robust_point_type + < + point_type, RobustPolicy + >::type + > box_type; + typedef geometry::sections sections_type; + + sections_type sec1, sec2; + typedef boost::mpl::vector_c dimensions; + + geometry::sectionalize(geometry1, robust_policy, + sec1, 0); + geometry::sectionalize(geometry2, robust_policy, + sec2, 1); + + // ... and then partition them, intersecting overlapping sections in visitor method + section_visitor + < + Geometry1, Geometry2, + Reverse1, Reverse2, + Turns, TurnPolicy, RobustPolicy, InterruptPolicy + > visitor(source_id1, geometry1, source_id2, geometry2, robust_policy, turns, interrupt_policy); + + geometry::partition + < + box_type, + detail::section::get_section_box, + detail::section::overlaps_section_box + >::apply(sec1, sec2, visitor); + } +}; + + +// Get turns for a range with a box, following Cohen-Sutherland (cs) approach +template +< + typename Range, typename Box, + bool ReverseRange, bool ReverseBox, + typename TurnPolicy +> +struct get_turns_cs +{ + typedef typename geometry::point_type::type point_type; + typedef typename geometry::point_type::type box_point_type; + + typedef typename closeable_view + < + Range const, + closure::value + >::type cview_type; + + typedef typename reversible_view + < + cview_type const, + ReverseRange ? iterate_reverse : iterate_forward + >::type view_type; + + typedef typename boost::range_iterator + < + view_type const + >::type iterator_type; + + + template + static inline void apply( + int source_id1, Range const& range, + int source_id2, Box const& box, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy, + signed_size_type multi_index = -1, + signed_size_type ring_index = -1) + { + if ( boost::size(range) <= 1) + { + return; + } + + boost::array bp; + assign_box_corners_oriented(box, bp); + + cview_type cview(range); + view_type view(cview); + + typedef typename boost::range_size::type size_type; + size_type segments_count1 = boost::size(view) - 1; + + iterator_type it = boost::begin(view); + + ever_circling_iterator next( + boost::begin(view), boost::end(view), it, true); + next++; + next++; + + //bool first = true; + + //char previous_side[2] = {0, 0}; + + signed_size_type index = 0; + + for (iterator_type prev = it++; + it != boost::end(view); + prev = it++, next++, index++) + { + segment_identifier seg_id(source_id1, + multi_index, ring_index, index); + + /*if (first) + { + previous_side[0] = get_side<0>(box, *prev); + previous_side[1] = get_side<1>(box, *prev); + } + + char current_side[2]; + current_side[0] = get_side<0>(box, *it); + current_side[1] = get_side<1>(box, *it); + + // There can NOT be intersections if + // 1) EITHER the two points are lying on one side of the box (! 0 && the same) + // 2) OR same in Y-direction + // 3) OR all points are inside the box (0) + if (! ( + (current_side[0] != 0 && current_side[0] == previous_side[0]) + || (current_side[1] != 0 && current_side[1] == previous_side[1]) + || (current_side[0] == 0 + && current_side[1] == 0 + && previous_side[0] == 0 + && previous_side[1] == 0) + ) + )*/ + if (true) + { + get_turns_with_box(seg_id, source_id2, + *prev, *it, *next, + bp[0], bp[1], bp[2], bp[3], + // NOTE: some dummy values could be passed below since this would be called only for Polygons and Boxes + index == 0, + size_type(index) == segments_count1, + robust_policy, + turns, interrupt_policy); + // Future performance enhancement: + // return if told by the interrupt policy + } + } + } + +private: + template + static inline int get_side(Box const& box, Point const& point) + { + // Inside -> 0 + // Outside -> -1 (left/below) or 1 (right/above) + // On border -> -2 (left/lower) or 2 (right/upper) + // The only purpose of the value is to not be the same, + // and to denote if it is inside (0) + + typename coordinate_type::type const& c = get(point); + typename coordinate_type::type const& left = get(box); + typename coordinate_type::type const& right = get(box); + + if (geometry::math::equals(c, left)) return -2; + else if (geometry::math::equals(c, right)) return 2; + else if (c < left) return -1; + else if (c > right) return 1; + else return 0; + } + + template + static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2, + // Points from a range: + point_type const& rp0, + point_type const& rp1, + point_type const& rp2, + // Points from the box + box_point_type const& bp0, + box_point_type const& bp1, + box_point_type const& bp2, + box_point_type const& bp3, + bool const is_range_first, + bool const is_range_last, + RobustPolicy const& robust_policy, + // Output + Turns& turns, + InterruptPolicy& interrupt_policy) + { + boost::ignore_unused_variable_warning(interrupt_policy); + + // Depending on code some relations can be left out + + typedef typename boost::range_value::type turn_info; + + turn_info ti; + ti.operations[0].seg_id = seg_id; + + ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0); + TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2, + is_range_first, is_range_last, + true, false, + ti, robust_policy, std::back_inserter(turns)); + + ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1); + TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3, + is_range_first, is_range_last, + false, false, + ti, robust_policy, std::back_inserter(turns)); + + ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2); + TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0, + is_range_first, is_range_last, + false, false, + ti, robust_policy, std::back_inserter(turns)); + + ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3); + TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1, + is_range_first, is_range_last, + false, true, + ti, robust_policy, std::back_inserter(turns)); + + if (InterruptPolicy::enabled) + { + interrupt_policy.apply(turns); + } + + } + +}; + + +template +< + typename Polygon, typename Box, + bool Reverse, bool ReverseBox, + typename TurnPolicy +> +struct get_turns_polygon_cs +{ + template + static inline void apply( + int source_id1, Polygon const& polygon, + int source_id2, Box const& box, + RobustPolicy const& robust_policy, + Turns& turns, InterruptPolicy& interrupt_policy, + signed_size_type multi_index = -1) + { + typedef typename geometry::ring_type::type ring_type; + + typedef detail::get_turns::get_turns_cs + < + ring_type, Box, + Reverse, ReverseBox, + TurnPolicy + > intersector_type; + + intersector_type::apply( + source_id1, geometry::exterior_ring(polygon), + source_id2, box, + robust_policy, + turns, interrupt_policy, + multi_index, -1); + + signed_size_type i = 0; + + typename interior_return_type::type + rings = interior_rings(polygon); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it, ++i) + { + intersector_type::apply( + source_id1, *it, + source_id2, box, + robust_policy, + turns, interrupt_policy, + multi_index, i); + } + + } +}; + + +template +< + typename Multi, typename Box, + bool Reverse, bool ReverseBox, + typename TurnPolicy +> +struct get_turns_multi_polygon_cs +{ + template + static inline void apply( + int source_id1, Multi const& multi, + int source_id2, Box const& box, + RobustPolicy const& robust_policy, + Turns& turns, InterruptPolicy& interrupt_policy) + { + typedef typename boost::range_iterator + < + Multi const + >::type iterator_type; + + signed_size_type i = 0; + for (iterator_type it = boost::begin(multi); + it != boost::end(multi); + ++it, ++i) + { + // Call its single version + get_turns_polygon_cs + < + typename boost::range_value::type, Box, + Reverse, ReverseBox, + TurnPolicy + >::apply(source_id1, *it, source_id2, box, + robust_policy, turns, interrupt_policy, i); + } + } +}; + + +// GET_TURN_INFO_TYPE + +template +struct topological_tag_base +{ + typedef typename tag_cast::type, pointlike_tag, linear_tag, areal_tag>::type type; +}; + +template ::type, typename Tag2 = typename tag::type, + typename TagBase1 = typename topological_tag_base::type, typename TagBase2 = typename topological_tag_base::type> +struct get_turn_info_type + : overlay::get_turn_info +{}; + +template +struct get_turn_info_type + : overlay::get_turn_info_linear_linear +{}; + +template +struct get_turn_info_type + : overlay::get_turn_info_linear_areal +{}; + +template ::type, typename Tag2 = typename tag::type, + typename TagBase1 = typename topological_tag_base::type, typename TagBase2 = typename topological_tag_base::type> +struct turn_operation_type +{ + typedef overlay::turn_operation::type, SegmentRatio> type; +}; + +template +struct turn_operation_type +{ + typedef overlay::turn_operation_linear::type, SegmentRatio> type; +}; + +template +struct turn_operation_type +{ + typedef overlay::turn_operation_linear::type, SegmentRatio> type; +}; + +}} // namespace detail::get_turns +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// Because this is "detail" method, and most implementations will use "generic", +// we take the freedom to derive it from "generic". +template +< + typename GeometryTag1, typename GeometryTag2, + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, + typename TurnPolicy +> +struct get_turns + : detail::get_turns::get_turns_generic + < + Geometry1, Geometry2, + Reverse1, Reverse2, + TurnPolicy + > +{}; + + +template +< + typename Polygon, typename Box, + bool ReversePolygon, bool ReverseBox, + typename TurnPolicy +> +struct get_turns + < + polygon_tag, box_tag, + Polygon, Box, + ReversePolygon, ReverseBox, + TurnPolicy + > : detail::get_turns::get_turns_polygon_cs + < + Polygon, Box, + ReversePolygon, ReverseBox, + TurnPolicy + > +{}; + + +template +< + typename Ring, typename Box, + bool ReverseRing, bool ReverseBox, + typename TurnPolicy +> +struct get_turns + < + ring_tag, box_tag, + Ring, Box, + ReverseRing, ReverseBox, + TurnPolicy + > : detail::get_turns::get_turns_cs + < + Ring, Box, ReverseRing, ReverseBox, + TurnPolicy + > + +{}; + + +template +< + typename MultiPolygon, + typename Box, + bool ReverseMultiPolygon, bool ReverseBox, + typename TurnPolicy +> +struct get_turns + < + multi_polygon_tag, box_tag, + MultiPolygon, Box, + ReverseMultiPolygon, ReverseBox, + TurnPolicy + > + : detail::get_turns::get_turns_multi_polygon_cs + < + MultiPolygon, Box, + ReverseMultiPolygon, ReverseBox, + TurnPolicy + > +{}; + + +template +< + typename GeometryTag1, typename GeometryTag2, + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, + typename TurnPolicy +> +struct get_turns_reversed +{ + template + static inline void apply( + int source_id1, Geometry1 const& g1, + int source_id2, Geometry2 const& g2, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) + { + get_turns + < + GeometryTag2, GeometryTag1, + Geometry2, Geometry1, + Reverse2, Reverse1, + TurnPolicy + >::apply(source_id2, g2, source_id1, g1, robust_policy, + turns, interrupt_policy); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +/*! +\brief \brief_calc2{turn points} +\ingroup overlay +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Turns type of turn-container (e.g. vector of "intersection/turn point"'s) +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param robust_policy policy to handle robustness issues +\param turns container which will contain turn points +\param interrupt_policy policy determining if process is stopped + when intersection is found + */ +template +< + bool Reverse1, bool Reverse2, + typename AssignPolicy, + typename Geometry1, + typename Geometry2, + typename RobustPolicy, + typename Turns, + typename InterruptPolicy +> +inline void get_turns(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) +{ + concepts::check_concepts_and_equal_dimensions(); + + typedef detail::overlay::get_turn_info TurnPolicy; + //typedef detail::get_turns::get_turn_info_type TurnPolicy; + + boost::mpl::if_c + < + reverse_dispatch::type::value, + dispatch::get_turns_reversed + < + typename tag::type, + typename tag::type, + Geometry1, Geometry2, + Reverse1, Reverse2, + TurnPolicy + >, + dispatch::get_turns + < + typename tag::type, + typename tag::type, + Geometry1, Geometry2, + Reverse1, Reverse2, + TurnPolicy + > + >::type::apply( + 0, geometry1, + 1, geometry2, + robust_policy, + turns, interrupt_policy); +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp new file mode 100755 index 0000000000..aa8d1e9ad4 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -0,0 +1,720 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_COLOCATIONS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_COLOCATIONS_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS) +# include +# include +# include +# define BOOST_GEOMETRY_DEBUG_IDENTIFIER +#endif + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +struct segment_fraction +{ + segment_identifier seg_id; + SegmentRatio fraction; + + segment_fraction(segment_identifier const& id, SegmentRatio const& fr) + : seg_id(id) + , fraction(fr) + {} + + segment_fraction() + {} + + bool operator<(segment_fraction const& other) const + { + return seg_id == other.seg_id + ? fraction < other.fraction + : seg_id < other.seg_id; + } + +}; + +struct turn_operation_index +{ + turn_operation_index(signed_size_type ti = -1, + signed_size_type oi = -1) + : turn_index(ti) + , op_index(oi) + {} + + signed_size_type turn_index; + signed_size_type op_index; // only 0,1 +}; + + +template +struct less_by_fraction_and_type +{ + inline less_by_fraction_and_type(Turns const& turns) + : m_turns(turns) + { + } + + inline bool operator()(turn_operation_index const& left, + turn_operation_index const& right) const + { + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + turn_type const& left_turn = m_turns[left.turn_index]; + turn_type const& right_turn = m_turns[right.turn_index]; + turn_operation_type const& left_op + = left_turn.operations[left.op_index]; + + turn_operation_type const& right_op + = right_turn.operations[right.op_index]; + + if (! (left_op.fraction == right_op.fraction)) + { + return left_op.fraction < right_op.fraction; + } + + // Order xx first - used to discard any following colocated turn + bool const left_both_xx = left_turn.both(operation_blocked); + bool const right_both_xx = right_turn.both(operation_blocked); + if (left_both_xx && ! right_both_xx) + { + return true; + } + if (! left_both_xx && right_both_xx) + { + return false; + } + + bool const left_both_uu = left_turn.both(operation_union); + bool const right_both_uu = right_turn.both(operation_union); + if (left_both_uu && ! right_both_uu) + { + return true; + } + if (! left_both_uu && right_both_uu) + { + return false; + } + + turn_operation_type const& left_other_op + = left_turn.operations[1 - left.op_index]; + + turn_operation_type const& right_other_op + = right_turn.operations[1 - right.op_index]; + + // Fraction is the same, now sort on ring id, first outer ring, + // then interior rings + return left_other_op.seg_id < right_other_op.seg_id; + } + +private: + Turns const& m_turns; +}; + +template +inline signed_size_type get_cluster_id(Operation const& op, ClusterPerSegment const& cluster_per_segment) +{ + typedef typename ClusterPerSegment::key_type segment_fraction_type; + + segment_fraction_type seg_frac(op.seg_id, op.fraction); + typename ClusterPerSegment::const_iterator it + = cluster_per_segment.find(seg_frac); + + if (it == cluster_per_segment.end()) + { + return -1; + } + return it->second; +} + +template +inline void add_cluster_id(Operation const& op, + ClusterPerSegment& cluster_per_segment, signed_size_type id) +{ + typedef typename ClusterPerSegment::key_type segment_fraction_type; + + segment_fraction_type seg_frac(op.seg_id, op.fraction); + + cluster_per_segment[seg_frac] = id; +} + +template +inline signed_size_type add_turn_to_cluster(Turn const& turn, + ClusterPerSegment& cluster_per_segment, signed_size_type& cluster_id) +{ + signed_size_type cid0 = get_cluster_id(turn.operations[0], cluster_per_segment); + signed_size_type cid1 = get_cluster_id(turn.operations[1], cluster_per_segment); + + if (cid0 == -1 && cid1 == -1) + { + ++cluster_id; + add_cluster_id(turn.operations[0], cluster_per_segment, cluster_id); + add_cluster_id(turn.operations[1], cluster_per_segment, cluster_id); + return cluster_id; + } + else if (cid0 == -1 && cid1 != -1) + { + add_cluster_id(turn.operations[0], cluster_per_segment, cid1); + return cid1; + } + else if (cid0 != -1 && cid1 == -1) + { + add_cluster_id(turn.operations[1], cluster_per_segment, cid0); + return cid0; + } + else if (cid0 == cid1) + { + // Both already added to same cluster, no action + return cid0; + } + + // Both operations.seg_id/fraction were already part of any cluster, and + // these clusters are not the same. Merge of two clusters is necessary + std::cout << " TODO: merge " << cid0 << " and " << cid1 << std::endl; + return cid0; +} + +template +< + typename Turns, + typename ClusterPerSegment, + typename Operations, + typename Geometry1, + typename Geometry2 +> +inline void handle_colocation_cluster(Turns& turns, + signed_size_type& cluster_id, + ClusterPerSegment& cluster_per_segment, + Operations const& operations, + Geometry1 const& /*geometry1*/, Geometry2 const& /*geometry2*/) +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + std::vector::const_iterator vit = operations.begin(); + + turn_operation_index ref_toi = *vit; + signed_size_type ref_id = -1; + + for (++vit; vit != operations.end(); ++vit) + { + turn_type& ref_turn = turns[ref_toi.turn_index]; + turn_operation_type const& ref_op + = ref_turn.operations[ref_toi.op_index]; + + turn_operation_index const& toi = *vit; + turn_type& turn = turns[toi.turn_index]; + turn_operation_type const& op = turn.operations[toi.op_index]; + + BOOST_ASSERT(ref_op.seg_id == op.seg_id); + + if (ref_op.fraction == op.fraction) + { + turn_operation_type const& other_op = turn.operations[1 - toi.op_index]; + + if (ref_id == -1) + { + ref_id = add_turn_to_cluster(ref_turn, cluster_per_segment, cluster_id); + } + BOOST_ASSERT(ref_id != -1); + + // ref_turn (both operations) are already added to cluster, + // so also "op" is already added to cluster, + // We only need to add other_op + signed_size_type id = get_cluster_id(other_op, cluster_per_segment); + if (id != -1 && id != ref_id) + { + } + else if (id == -1) + { + // Add to same cluster + add_cluster_id(other_op, cluster_per_segment, ref_id); + id = ref_id; + } + + // In case of colocated xx turns, all other turns may NOT be + // followed at all. xx cannot be discarded (otherwise colocated + // turns are followed). + if (ref_turn.both(operation_blocked)) + { + turn.discarded = true; + // We can either set or not set colocated because it is not effective on blocked turns + } + } + else + { + // Not on same fraction on this segment + // assign for next + ref_toi = toi; + ref_id = -1; + } + } +} + +template +< + typename Turns, + typename Clusters, + typename ClusterPerSegment +> +inline void assign_cluster_to_turns(Turns& turns, + Clusters& clusters, + ClusterPerSegment const& cluster_per_segment) +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + typedef typename ClusterPerSegment::key_type segment_fraction_type; + + signed_size_type turn_index = 0; + for (typename boost::range_iterator::type it = turns.begin(); + it != turns.end(); ++it, ++turn_index) + { + turn_type& turn = *it; + + if (turn.discarded) + { + // They were processed (to create proper map) but will not be added + // This might leave a cluster with only 1 turn, which will be fixed + // afterwards + continue; + } + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = turn.operations[i]; + segment_fraction_type seg_frac(op.seg_id, op.fraction); + typename ClusterPerSegment::const_iterator it = cluster_per_segment.find(seg_frac); + if (it != cluster_per_segment.end()) + { + if (turn.cluster_id != -1 + && turn.cluster_id != it->second) + { + std::cout << " CONFLICT " << std::endl; + } + turn.cluster_id = it->second; + clusters[turn.cluster_id].turn_indices.insert(turn_index); + } + } + } +} + +template +< + typename Turns, + typename Clusters +> +inline void remove_clusters(Turns& turns, Clusters& clusters) +{ + typename Clusters::iterator it = clusters.begin(); + while (it != clusters.end()) + { + // Hold iterator and increase. We can erase cit, this keeps the + // iterator valid (cf The standard associative-container erase idiom) + typename Clusters::iterator current_it = it; + ++it; + + std::set const& turn_indices + = current_it->second.turn_indices; + if (turn_indices.size() == 1) + { + signed_size_type turn_index = *turn_indices.begin(); + turns[turn_index].cluster_id = -1; + clusters.erase(current_it); + } + } +} + +template +inline void discard_ie_turn(Turn& turn, IdSet& ids, signed_size_type id) +{ + turn.discarded = true; + turn.cluster_id = -1; + // To remove it later from clusters + ids.insert(id); +} + +template +inline bool is_interior(segment_identifier const& seg_id) +{ + return Reverse ? seg_id.ring_index == -1 : seg_id.ring_index >= 0; +} + +template +inline bool is_ie_turn(segment_identifier const& ext_seg_0, + segment_identifier const& ext_seg_1, + segment_identifier const& int_seg_0, + segment_identifier const& other_seg_1) +{ + // Compares two segment identifiers from two turns (external / one internal) + + // From first turn [0], both are from same polygon (multi_index), + // one is exterior (-1), the other is interior (>= 0), + // and the second turn [1] handles the same ring + + // For difference, where the rings are processed in reversal, all interior + // rings become exterior and vice versa. But also the multi property changes: + // rings originally from the same multi should now be considered as from + // different multi polygons. + // But this is not always the case, and at this point hard to figure out + // (not yet implemented, TODO) + + bool const same_multi0 = ! Reverse0 + && ext_seg_0.multi_index == int_seg_0.multi_index; + + bool const same_multi1 = ! Reverse1 + && ext_seg_1.multi_index == other_seg_1.multi_index; + + return same_multi0 + && same_multi1 + && ! is_interior(ext_seg_0) + && is_interior(int_seg_0) + && ext_seg_1.ring_index == other_seg_1.ring_index; + + // The other way round is tested in another call +} + +template +< + bool Reverse0, bool Reverse1, // Reverse interpretation interior/exterior + typename Turns, + typename Clusters +> +inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters) +{ + typedef std::set::const_iterator set_iterator; + typedef typename boost::range_value::type turn_type; + + std::set ids_to_remove; + + for (typename Clusters::iterator cit = clusters.begin(); + cit != clusters.end(); ++cit) + { + cluster_info& cinfo = cit->second; + std::set& ids = cinfo.turn_indices; + + ids_to_remove.clear(); + + for (set_iterator it = ids.begin(); it != ids.end(); ++it) + { + turn_type& turn = turns[*it]; + segment_identifier const& seg_0 = turn.operations[0].seg_id; + segment_identifier const& seg_1 = turn.operations[1].seg_id; + + if (turn.both(operation_intersection) + && Reverse0 == Reverse1) + { + if ( is_interior(seg_0) + && is_interior(seg_1)) + { + // ii touch with, two interior rings + discard_ie_turn(turn, ids_to_remove, *it); + } + + continue; + } + + if (! (turn.both(operation_union) + || turn.combination(operation_union, operation_blocked))) + { + // Not a uu/ux, so cannot be colocated with a iu turn + continue; + } + + for (set_iterator int_it = ids.begin(); int_it != ids.end(); ++int_it) + { + if (*it == *int_it) + { + continue; + } + + // Turn with, possibly, an interior ring involved + turn_type& int_turn = turns[*int_it]; + segment_identifier const& int_seg_0 = int_turn.operations[0].seg_id; + segment_identifier const& int_seg_1 = int_turn.operations[1].seg_id; + + if (is_ie_turn(seg_0, seg_1, int_seg_0, int_seg_1)) + { + discard_ie_turn(int_turn, ids_to_remove, *int_it); + } + if (is_ie_turn(seg_1, seg_0, int_seg_1, int_seg_0)) + { + discard_ie_turn(int_turn, ids_to_remove, *int_it); + } + } + } + + // Erase from the ids (which cannot be done above) + for (set_iterator sit = ids_to_remove.begin(); + sit != ids_to_remove.end(); ++sit) + { + ids.erase(*sit); + } + } +} + + +// Checks colocated turns and flags combinations of uu/other, possibly a +// combination of a ring touching another geometry's interior ring which is +// tangential to the exterior ring + +// This function can be extended to replace handle_tangencies: at each +// colocation incoming and outgoing vectors should be inspected + +template +< + bool Reverse1, bool Reverse2, + typename Turns, + typename Clusters, + typename Geometry1, + typename Geometry2 +> +inline bool handle_colocations(Turns& turns, Clusters& clusters, + Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + typedef std::map + < + segment_identifier, + std::vector + > map_type; + + // Create and fill map on segment-identifier Map is sorted on seg_id, + // meaning it is sorted on ring_identifier too. This means that exterior + // rings are handled first. If there is a colocation on the exterior ring, + // that information can be used for the interior ring too + map_type map; + + int index = 0; + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it, ++index) + { + map[it->operations[0].seg_id].push_back(turn_operation_index(index, 0)); + map[it->operations[1].seg_id].push_back(turn_operation_index(index, 1)); + } + + // Check if there are multiple turns on one or more segments, + // if not then nothing is to be done + bool colocations = 0; + for (typename map_type::const_iterator it = map.begin(); + it != map.end(); + ++it) + { + if (it->second.size() > 1u) + { + colocations = true; + break; + } + } + + if (! colocations) + { + return false; + } + + // Sort all vectors, per same segment + less_by_fraction_and_type less(turns); + for (typename map_type::iterator it = map.begin(); + it != map.end(); ++it) + { + std::sort(it->second.begin(), it->second.end(), less); + } + + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::segment_ratio_type segment_ratio_type; + + typedef std::map + < + segment_fraction, + signed_size_type + > cluster_per_segment_type; + + cluster_per_segment_type cluster_per_segment; + signed_size_type cluster_id = 0; + + for (typename map_type::const_iterator it = map.begin(); + it != map.end(); ++it) + { + if (it->second.size() > 1u) + { + handle_colocation_cluster(turns, cluster_id, cluster_per_segment, + it->second, geometry1, geometry2); + } + } + + assign_cluster_to_turns(turns, clusters, cluster_per_segment); + discard_interior_exterior_turns + < + do_reverse::value>::value != Reverse1, + do_reverse::value>::value != Reverse2 + >(turns, clusters); + remove_clusters(turns, clusters); + +#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS) + std::cout << "*** Colocations " << map.size() << std::endl; + for (typename map_type::const_iterator it = map.begin(); + it != map.end(); ++it) + { + std::cout << it->first << std::endl; + for (std::vector::const_iterator vit + = it->second.begin(); vit != it->second.end(); ++vit) + { + turn_operation_index const& toi = *vit; + std::cout << geometry::wkt(turns[toi.turn_index].point) + << std::boolalpha + << " discarded=" << turns[toi.turn_index].discarded + << " colocated=" << turns[toi.turn_index].colocated + << " " << operation_char(turns[toi.turn_index].operations[0].operation) + << " " << turns[toi.turn_index].operations[0].seg_id + << " " << turns[toi.turn_index].operations[0].fraction + << " // " << operation_char(turns[toi.turn_index].operations[1].operation) + << " " << turns[toi.turn_index].operations[1].seg_id + << " " << turns[toi.turn_index].operations[1].fraction + << std::endl; + } + } +#endif // DEBUG + + return true; +} + + +struct is_turn_index +{ + is_turn_index(signed_size_type index) + : m_index(index) + {} + + template + inline bool operator()(Indexed const& indexed) const + { + // Indexed is a indexed_turn_operation + return indexed.turn_index == m_index; + } + + std::size_t m_index; +}; + + +template +< + bool Reverse1, bool Reverse2, + typename Turns, + typename Clusters, + typename Geometry1, + typename Geometry2 +> +inline void gather_cluster_properties(Clusters& clusters, Turns& turns, + operation_type for_operation, + Geometry1 const& geometry1, Geometry2 const& geometry2) +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::point_type point_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + // Define sorter, sorting counter-clockwise such that polygons are on the + // right side + typedef sort_by_side::side_sorter + < + Reverse1, Reverse2, point_type, std::less + > sbs_type; + + for (typename Clusters::iterator mit = clusters.begin(); + mit != clusters.end(); ++mit) + { + cluster_info& cinfo = mit->second; + std::set const& ids = cinfo.turn_indices; + if (ids.empty()) + { + continue; + } + + sbs_type sbs; + point_type turn_point; // should be all the same for all turns in cluster + + bool first = true; + for (typename std::set::const_iterator sit = ids.begin(); + sit != ids.end(); ++sit) + { + signed_size_type turn_index = *sit; + turn_type const& turn = turns[turn_index]; + if (first) + { + turn_point = turn.point; + } + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = turn.operations[i]; + sbs.add(op, turn_index, i, geometry1, geometry2, first); + first = false; + } + } + sbs.apply(turn_point); + + sbs.find_open(); + + // Unset the startable flag for all 'closed' zones + for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) + { + const typename sbs_type::rp& ranked = sbs.m_ranked_points[i]; + turn_type& turn = turns[ranked.turn_index]; + turn_operation_type& op = turn.operations[ranked.operation_index]; + + if (ranked.direction != sort_by_side::dir_to) + { + continue; + } + + op.enriched.count_left = ranked.count_left; + op.enriched.count_right = ranked.count_right; + op.enriched.zone = ranked.zone; + + if ((for_operation == operation_union + && ranked.count_left != 0) + || (for_operation == operation_intersection + && ranked.count_right != 2)) + { + op.enriched.startable = false; + } + } + + cinfo.open_count = sbs.open_count(turns); + } +} + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_COLOCATIONS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp new file mode 100755 index 0000000000..acdb3952c2 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/inconsistent_turns_exception.hpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP + +#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW) +#include + +namespace boost { namespace geometry +{ + +class inconsistent_turns_exception : public geometry::exception +{ +public: + + inline inconsistent_turns_exception() {} + + virtual ~inconsistent_turns_exception() throw() + {} + + virtual char const* what() const throw() + { + return "Boost.Geometry Inconsistent Turns exception"; + } +}; + +}} // boost::geometry + +#endif // BOOST_GEOMETRY_OVERLAY_NO_THROW + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INCONSISTENT_TURNS_EXCEPTION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp new file mode 100755 index 0000000000..8ab39b0baf --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp @@ -0,0 +1,96 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_BOX_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_BOX_BOX_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace intersection +{ + +template +struct intersection_box_box +{ + template + < + typename Box1, typename Box2, + typename RobustPolicy, + typename BoxOut, + typename Strategy + > + static inline bool apply(Box1 const& box1, + Box2 const& box2, + RobustPolicy const& robust_policy, + BoxOut& box_out, + Strategy const& strategy) + { + typedef typename coordinate_type::type ct; + + ct max1 = get(box1); + ct min2 = get(box2); + + if (max1 < min2) + { + return false; + } + + ct max2 = get(box2); + ct min1 = get(box1); + + if (max2 < min1) + { + return false; + } + + // Set dimensions of output coordinate + set(box_out, min1 < min2 ? min2 : min1); + set(box_out, max1 > max2 ? max2 : max1); + + return intersection_box_box + ::apply(box1, box2, robust_policy, box_out, strategy); + } +}; + +template +struct intersection_box_box +{ + template + < + typename Box1, typename Box2, + typename RobustPolicy, + typename BoxOut, + typename Strategy + > + static inline bool apply(Box1 const&, Box2 const&, + RobustPolicy const&, BoxOut&, Strategy const&) + { + return true; + } +}; + + +}} // namespace detail::intersection +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_BOX_BOX_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp new file mode 100755 index 0000000000..a2d9e6f54d --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -0,0 +1,1066 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP + + +#include + +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) +#include +#include +#endif + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace intersection +{ + +template +struct intersection_segment_segment_point +{ + template + < + typename Segment1, typename Segment2, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Segment1 const& segment1, + Segment2 const& segment2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& ) + { + typedef typename point_type::type point_type; + + typedef typename geometry::robust_point_type + < + typename geometry::point_type::type, + RobustPolicy + >::type robust_point_type; + + // TODO: rescale segment -> robust points + robust_point_type pi_rob, pj_rob, qi_rob, qj_rob; + { + // Workaround: + point_type pi, pj, qi, qj; + assign_point_from_index<0>(segment1, pi); + assign_point_from_index<1>(segment1, pj); + assign_point_from_index<0>(segment2, qi); + assign_point_from_index<1>(segment2, qj); + geometry::recalculate(pi_rob, pi, robust_policy); + geometry::recalculate(pj_rob, pj, robust_policy); + geometry::recalculate(qi_rob, qi, robust_policy); + geometry::recalculate(qj_rob, qj, robust_policy); + } + + // Get the intersection point (or two points) + typedef segment_intersection_points + < + point_type, + typename segment_ratio_type + < + point_type, RobustPolicy + >::type + > intersection_return_type; + + typedef strategy::intersection::relate_cartesian_segments + < + policies::relate::segments_intersection_points + < + intersection_return_type + > + > policy; + + intersection_return_type is = policy::apply(segment1, segment2, + robust_policy, pi_rob, pj_rob, qi_rob, qj_rob); + + for (std::size_t i = 0; i < is.count; i++) + { + PointOut p; + geometry::convert(is.intersections[i], p); + *out++ = p; + } + return out; + } +}; + +template +struct intersection_linestring_linestring_point +{ + template + < + typename Linestring1, typename Linestring2, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Linestring1 const& linestring1, + Linestring2 const& linestring2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& ) + { + typedef typename point_type::type point_type; + + typedef detail::overlay::turn_info + < + point_type, + typename segment_ratio_type::type + > turn_info; + std::deque turns; + + geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns); + + for (typename boost::range_iterator const>::type + it = boost::begin(turns); it != boost::end(turns); ++it) + { + PointOut p; + geometry::convert(it->point, p); + *out++ = p; + } + return out; + } +}; + +/*! +\brief Version of linestring with an areal feature (polygon or multipolygon) +*/ +template +< + bool ReverseAreal, + typename LineStringOut, + overlay_type OverlayType +> +struct intersection_of_linestring_with_areal +{ +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) + template + static inline void debug_follow(Turn const& turn, Operation op, + int index) + { + std::cout << index + << " at " << op.seg_id + << " meth: " << method_char(turn.method) + << " op: " << operation_char(op.operation) + << " vis: " << visited_char(op.visited) + << " of: " << operation_char(turn.operations[0].operation) + << operation_char(turn.operations[1].operation) + << " " << geometry::wkt(turn.point) + << std::endl; + } + + template + static inline void debug_turn(Turn const& t, bool non_crossing) + { + std::cout << "checking turn @" + << geometry::wkt(t.point) + << "; " << method_char(t.method) + << ":" << operation_char(t.operations[0].operation) + << "/" << operation_char(t.operations[1].operation) + << "; non-crossing? " + << std::boolalpha << non_crossing << std::noboolalpha + << std::endl; + } +#endif + + class is_crossing_turn + { + // return true is the operation is intersection or blocked + template + static inline bool has_op_i_or_b(Turn const& t) + { + return + t.operations[Index].operation == overlay::operation_intersection + || + t.operations[Index].operation == overlay::operation_blocked; + } + + template + static inline bool has_method_crosses(Turn const& t) + { + return t.method == overlay::method_crosses; + } + + template + static inline bool is_cc(Turn const& t) + { + return + (t.method == overlay::method_touch_interior + || + t.method == overlay::method_equal + || + t.method == overlay::method_collinear) + && + t.operations[0].operation == t.operations[1].operation + && + t.operations[0].operation == overlay::operation_continue + ; + } + + template + static inline bool has_i_or_b_ops(Turn const& t) + { + return + (t.method == overlay::method_touch + || + t.method == overlay::method_touch_interior + || + t.method == overlay::method_collinear) + && + t.operations[1].operation != t.operations[0].operation + && + (has_op_i_or_b<0>(t) || has_op_i_or_b<1>(t)); + } + + public: + template + static inline bool apply(Turn const& t) + { + bool const is_crossing + = has_method_crosses(t) || is_cc(t) || has_i_or_b_ops(t); +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) + debug_turn(t, ! is_crossing); +#endif + return is_crossing; + } + }; + + struct is_non_crossing_turn + { + template + static inline bool apply(Turn const& t) + { + return ! is_crossing_turn::apply(t); + } + }; + + template + static inline bool no_crossing_turns_or_empty(Turns const& turns) + { + return detail::check_iterator_range + < + is_non_crossing_turn, + true // allow an empty turns range + >::apply(boost::begin(turns), boost::end(turns)); + } + + template + < + typename LineString, typename Areal, + typename RobustPolicy, + typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(LineString const& linestring, Areal const& areal, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& ) + { + if (boost::size(linestring) == 0) + { + return out; + } + + typedef detail::overlay::follow + < + LineStringOut, + LineString, + Areal, + OverlayType, + false // do not remove spikes for linear geometries + > follower; + + typedef typename point_type::type point_type; + typedef detail::overlay::traversal_turn_info + < + point_type, + typename geometry::segment_ratio_type::type + > turn_info; + std::deque turns; + + detail::get_turns::no_interrupt_policy policy; + geometry::get_turns + < + false, + (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal), + detail::overlay::assign_null_policy + >(linestring, areal, robust_policy, turns, policy); + + if (no_crossing_turns_or_empty(turns)) + { + // No intersection points, it is either completely + // inside (interior + borders) + // or completely outside + + // Use border point (on a segment) to check this + // (because turn points might skip some cases) + point_type border_point; + if (! geometry::point_on_border(border_point, linestring, true)) + { + return out; + } + + if (follower::included(border_point, areal, robust_policy)) + { + LineStringOut copy; + geometry::convert(linestring, copy); + *out++ = copy; + } + return out; + } + +#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) + int index = 0; + for(typename std::deque::const_iterator + it = turns.begin(); it != turns.end(); ++it) + { + debug_follow(*it, it->operations[0], index++); + } +#endif + + return follower::apply + ( + linestring, areal, + geometry::detail::overlay::operation_intersection, + turns, robust_policy, out + ); + } +}; + + +}} // namespace detail::intersection +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + // real types + typename Geometry1, + typename Geometry2, + typename GeometryOut, + overlay_type OverlayType, + // orientation + bool Reverse1 = detail::overlay::do_reverse::value>::value, + bool Reverse2 = detail::overlay::do_reverse::value>::value, + bool ReverseOut = detail::overlay::do_reverse::value>::value, + // tag dispatching: + typename TagIn1 = typename geometry::tag::type, + typename TagIn2 = typename geometry::tag::type, + typename TagOut = typename geometry::tag::type, + // metafunction finetuning helpers: + bool Areal1 = geometry::is_areal::value, + bool Areal2 = geometry::is_areal::value, + bool ArealOut = geometry::is_areal::value +> +struct intersection_insert +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS + , (types) + ); +}; + + +template +< + typename Geometry1, typename Geometry2, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename TagIn1, typename TagIn2, typename TagOut +> +struct intersection_insert + < + Geometry1, Geometry2, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + TagIn1, TagIn2, TagOut, + true, true, true + > : detail::overlay::overlay + +{}; + + +// Any areal type with box: +template +< + typename Geometry, typename Box, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename TagIn, typename TagOut +> +struct intersection_insert + < + Geometry, Box, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + TagIn, box_tag, TagOut, + true, true, true + > : detail::overlay::overlay + +{}; + + +template +< + typename Segment1, typename Segment2, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Segment1, Segment2, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + segment_tag, segment_tag, point_tag, + false, false, false + > : detail::intersection::intersection_segment_segment_point +{}; + + +template +< + typename Linestring1, typename Linestring2, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Linestring1, Linestring2, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + linestring_tag, linestring_tag, point_tag, + false, false, false + > : detail::intersection::intersection_linestring_linestring_point +{}; + + +template +< + typename Linestring, typename Box, + typename GeometryOut, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Linestring, Box, + GeometryOut, + overlay_intersection, + Reverse1, Reverse2, ReverseOut, + linestring_tag, box_tag, linestring_tag, + false, true, false + > +{ + template + static inline OutputIterator apply(Linestring const& linestring, + Box const& box, + RobustPolicy const& robust_policy, + OutputIterator out, Strategy const& ) + { + typedef typename point_type::type point_type; + strategy::intersection::liang_barsky lb_strategy; + return detail::intersection::clip_range_with_box + (box, linestring, robust_policy, out, lb_strategy); + } +}; + + +template +< + typename Linestring, typename Polygon, + typename GeometryOut, + overlay_type OverlayType, + bool ReverseLinestring, bool ReversePolygon, bool ReverseOut +> +struct intersection_insert + < + Linestring, Polygon, + GeometryOut, + OverlayType, + ReverseLinestring, ReversePolygon, ReverseOut, + linestring_tag, polygon_tag, linestring_tag, + false, true, false + > : detail::intersection::intersection_of_linestring_with_areal + < + ReversePolygon, + GeometryOut, + OverlayType + > +{}; + + +template +< + typename Linestring, typename Ring, + typename GeometryOut, + overlay_type OverlayType, + bool ReverseLinestring, bool ReverseRing, bool ReverseOut +> +struct intersection_insert + < + Linestring, Ring, + GeometryOut, + OverlayType, + ReverseLinestring, ReverseRing, ReverseOut, + linestring_tag, ring_tag, linestring_tag, + false, true, false + > : detail::intersection::intersection_of_linestring_with_areal + < + ReverseRing, + GeometryOut, + OverlayType + > +{}; + +template +< + typename Segment, typename Box, + typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Segment, Box, + GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + segment_tag, box_tag, linestring_tag, + false, true, false + > +{ + template + static inline OutputIterator apply(Segment const& segment, + Box const& box, + RobustPolicy const& robust_policy, + OutputIterator out, Strategy const& ) + { + geometry::segment_view range(segment); + + typedef typename point_type::type point_type; + strategy::intersection::liang_barsky lb_strategy; + return detail::intersection::clip_range_with_box + (box, range, robust_policy, out, lb_strategy); + } +}; + +template +< + typename Geometry1, typename Geometry2, + typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag1, typename Tag2, + bool Areal1, bool Areal2 +> +struct intersection_insert + < + Geometry1, Geometry2, + PointOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + Tag1, Tag2, point_tag, + Areal1, Areal2, false + > +{ + template + static inline OutputIterator apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator out, Strategy const& ) + { + + typedef detail::overlay::turn_info + < + PointOut, + typename segment_ratio_type::type + > turn_info; + std::vector turns; + + detail::get_turns::no_interrupt_policy policy; + geometry::get_turns + < + false, false, detail::overlay::assign_null_policy + >(geometry1, geometry2, robust_policy, turns, policy); + for (typename std::vector::const_iterator it + = turns.begin(); it != turns.end(); ++it) + { + *out++ = it->point; + } + + return out; + } +}; + + +template +< + typename Geometry1, typename Geometry2, typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert_reversed +{ + template + static inline OutputIterator apply(Geometry1 const& g1, + Geometry2 const& g2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + return intersection_insert + < + Geometry2, Geometry1, GeometryOut, + OverlayType, + Reverse2, Reverse1, ReverseOut + >::apply(g2, g1, robust_policy, out, strategy); + } +}; + + +// dispatch for intersection(areal, areal, linear) +template +< + typename Geometry1, typename Geometry2, + typename LinestringOut, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag1, typename Tag2 +> +struct intersection_insert + < + Geometry1, Geometry2, + LinestringOut, + overlay_intersection, + Reverse1, Reverse2, ReverseOut, + Tag1, Tag2, linestring_tag, + true, true, false + > +{ + template + < + typename RobustPolicy, typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + detail::boundary_view view1(geometry1); + detail::boundary_view view2(geometry2); + + return detail::overlay::linear_linear_linestring + < + detail::boundary_view, + detail::boundary_view, + LinestringOut, + overlay_intersection + >::apply(view1, view2, robust_policy, oit, strategy); + } +}; + +// dispatch for non-areal geometries +template +< + typename Geometry1, typename Geometry2, typename GeometryOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename TagIn1, typename TagIn2 +> +struct intersection_insert + < + Geometry1, Geometry2, GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + TagIn1, TagIn2, linestring_tag, + false, false, false + > : intersection_insert + < + Geometry1, Geometry2, GeometryOut, + OverlayType, + Reverse1, Reverse2, ReverseOut, + typename tag_cast::type, + typename tag_cast::type, + linestring_tag, + false, false, false + > +{}; + + +// dispatch for difference/intersection of linear geometries +template +< + typename Linear1, typename Linear2, typename LineStringOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Linear1, Linear2, LineStringOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + linear_tag, linear_tag, linestring_tag, + false, false, false + > : detail::overlay::linear_linear_linestring + < + Linear1, Linear2, LineStringOut, OverlayType + > +{}; + + +// dispatch for difference/intersection of point-like geometries + +template +< + typename Point1, typename Point2, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Point1, Point2, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + point_tag, point_tag, point_tag, + false, false, false + > : detail::overlay::point_point_point + < + Point1, Point2, PointOut, OverlayType + > +{}; + + +template +< + typename MultiPoint, typename Point, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + MultiPoint, Point, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + multi_point_tag, point_tag, point_tag, + false, false, false + > : detail::overlay::multipoint_point_point + < + MultiPoint, Point, PointOut, OverlayType + > +{}; + + +template +< + typename Point, typename MultiPoint, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Point, MultiPoint, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + point_tag, multi_point_tag, point_tag, + false, false, false + > : detail::overlay::point_multipoint_point + < + Point, MultiPoint, PointOut, OverlayType + > +{}; + + +template +< + typename MultiPoint1, typename MultiPoint2, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + MultiPoint1, MultiPoint2, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + multi_point_tag, multi_point_tag, point_tag, + false, false, false + > : detail::overlay::multipoint_multipoint_point + < + MultiPoint1, MultiPoint2, PointOut, OverlayType + > +{}; + + +// dispatch for difference/intersection of pointlike-linear geometries +template +< + typename Point, typename Linear, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag +> +struct intersection_insert + < + Point, Linear, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + point_tag, Tag, point_tag, + false, false, false + > : detail_dispatch::overlay::pointlike_linear_point + < + Point, Linear, PointOut, OverlayType, + point_tag, typename tag_cast::type + > +{}; + + +template +< + typename MultiPoint, typename Linear, typename PointOut, + overlay_type OverlayType, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename Tag +> +struct intersection_insert + < + MultiPoint, Linear, PointOut, OverlayType, + Reverse1, Reverse2, ReverseOut, + multi_point_tag, Tag, point_tag, + false, false, false + > : detail_dispatch::overlay::pointlike_linear_point + < + MultiPoint, Linear, PointOut, OverlayType, + multi_point_tag, + typename tag_cast::type + > +{}; + + +template +< + typename Linestring, typename MultiPoint, typename PointOut, + bool Reverse1, bool Reverse2, bool ReverseOut +> +struct intersection_insert + < + Linestring, MultiPoint, PointOut, overlay_intersection, + Reverse1, Reverse2, ReverseOut, + linestring_tag, multi_point_tag, point_tag, + false, false, false + > +{ + template + static inline OutputIterator apply(Linestring const& linestring, + MultiPoint const& multipoint, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + return detail_dispatch::overlay::pointlike_linear_point + < + MultiPoint, Linestring, PointOut, overlay_intersection, + multi_point_tag, linear_tag + >::apply(multipoint, linestring, robust_policy, out, strategy); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace intersection +{ + + +template +< + typename GeometryOut, + bool ReverseSecond, + overlay_type OverlayType, + typename Geometry1, typename Geometry2, + typename RobustPolicy, + typename OutputIterator, + typename Strategy +> +inline OutputIterator insert(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy robust_policy, + OutputIterator out, + Strategy const& strategy) +{ + return boost::mpl::if_c + < + geometry::reverse_dispatch::type::value, + geometry::dispatch::intersection_insert_reversed + < + Geometry1, Geometry2, + GeometryOut, + OverlayType, + overlay::do_reverse::value>::value, + overlay::do_reverse::value, ReverseSecond>::value, + overlay::do_reverse::value>::value + >, + geometry::dispatch::intersection_insert + < + Geometry1, Geometry2, + GeometryOut, + OverlayType, + geometry::detail::overlay::do_reverse::value>::value, + geometry::detail::overlay::do_reverse::value, ReverseSecond>::value + > + >::type::apply(geometry1, geometry2, robust_policy, out, strategy); +} + + +/*! +\brief \brief_calc2{intersection} \brief_strategy +\ingroup intersection +\details \details_calc2{intersection_insert, spatial set theoretic intersection} + \brief_strategy. \details_insert{intersection} +\tparam GeometryOut \tparam_geometry{\p_l_or_c} +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam OutputIterator \tparam_out{\p_l_or_c} +\tparam Strategy \tparam_strategy_overlay +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param out \param_out{intersection} +\param strategy \param_strategy{intersection} +\return \return_out + +\qbk{distinguish,with strategy} +\qbk{[include reference/algorithms/intersection.qbk]} +*/ +template +< + typename GeometryOut, + typename Geometry1, + typename Geometry2, + typename OutputIterator, + typename Strategy +> +inline OutputIterator intersection_insert(Geometry1 const& geometry1, + Geometry2 const& geometry2, + OutputIterator out, + Strategy const& strategy) +{ + concepts::check(); + concepts::check(); + + typedef typename Strategy::rescale_policy_type rescale_policy_type; + rescale_policy_type robust_policy + = geometry::get_rescale_policy(geometry1, geometry2); + + return detail::intersection::insert + < + GeometryOut, false, overlay_intersection + >(geometry1, geometry2, robust_policy, out, strategy); +} + + +/*! +\brief \brief_calc2{intersection} +\ingroup intersection +\details \details_calc2{intersection_insert, spatial set theoretic intersection}. + \details_insert{intersection} +\tparam GeometryOut \tparam_geometry{\p_l_or_c} +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam OutputIterator \tparam_out{\p_l_or_c} +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param out \param_out{intersection} +\return \return_out + +\qbk{[include reference/algorithms/intersection.qbk]} +*/ +template +< + typename GeometryOut, + typename Geometry1, + typename Geometry2, + typename OutputIterator +> +inline OutputIterator intersection_insert(Geometry1 const& geometry1, + Geometry2 const& geometry2, + OutputIterator out) +{ + concepts::check(); + concepts::check(); + + typedef typename geometry::rescale_policy_type + < + typename geometry::point_type::type // TODO from both + >::type rescale_policy_type; + + typedef intersection_strategies + < + typename cs_tag::type, + Geometry1, + Geometry2, + typename geometry::point_type::type, + rescale_policy_type + > strategy; + + return intersection_insert(geometry1, geometry2, out, + strategy()); +} + +}} // namespace detail::intersection +#endif // DOXYGEN_NO_DETAIL + + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp new file mode 100755 index 0000000000..945d737d89 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp @@ -0,0 +1,203 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +// Wraps "turn_operation" from turn_info.hpp, +// giving it extra information, necessary for sorting +template +struct indexed_turn_operation +{ + typedef TurnOperation type; + + std::size_t turn_index; + std::size_t operation_index; + bool skip; + // use pointers to avoid copies, const& is not possible because of usage in vector + segment_identifier const* other_seg_id; // segment id of other segment of intersection of two segments + TurnOperation const* subject; + + inline indexed_turn_operation(std::size_t ti, std::size_t oi, + TurnOperation const& sub, + segment_identifier const& oid) + : turn_index(ti) + , operation_index(oi) + , skip(false) + , other_seg_id(&oid) + , subject(boost::addressof(sub)) + {} + +}; + +template +< + typename Turns, + typename Indexed, + typename Geometry1, typename Geometry2, + typename RobustPolicy, + bool Reverse1, bool Reverse2 +> +struct less_by_segment_ratio +{ + inline less_by_segment_ratio(Turns const& turns + , operation_type for_operation + , Geometry1 const& geometry1 + , Geometry2 const& geometry2 + , RobustPolicy const& robust_policy) + : m_turns(turns) + , m_for_operation(for_operation) + , m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_robust_policy(robust_policy) + { + } + +private : + + Turns const& m_turns; + operation_type m_for_operation; + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + RobustPolicy const& m_robust_policy; + + typedef typename geometry::point_type::type point_type; + + inline bool default_order(Indexed const& left, Indexed const& right) const + { + // We've nothing to sort on. Take the indexes + return left.turn_index < right.turn_index; + } + + inline bool consider_relative_order(Indexed const& left, + Indexed const& right) const + { + point_type pi, pj, ri, rj, si, sj; + + geometry::copy_segment_points(m_geometry1, m_geometry2, + left.subject->seg_id, + pi, pj); + geometry::copy_segment_points(m_geometry1, m_geometry2, + *left.other_seg_id, + ri, rj); + geometry::copy_segment_points(m_geometry1, m_geometry2, + *right.other_seg_id, + si, sj); + + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type strategy; + + int const side_rj_p = strategy::apply(pi, pj, rj); + int const side_sj_p = strategy::apply(pi, pj, sj); + + // Put the one turning left (1; right == -1) as last + if (side_rj_p != side_sj_p) + { + return side_rj_p < side_sj_p; + } + + int const side_sj_r = strategy::apply(ri, rj, sj); + int const side_rj_s = strategy::apply(si, sj, rj); + + // If they both turn left: the most left as last + // If they both turn right: this is not relevant, but take also here most left + if (side_rj_s != side_sj_r) + { + return side_rj_s < side_sj_r; + } + + return default_order(left, right); + } + + +public : + + // Note that left/right do NOT correspond to m_geometry1/m_geometry2 + // but to the "indexed_turn_operation" + inline bool operator()(Indexed const& left, Indexed const& right) const + { + if (! (left.subject->seg_id == right.subject->seg_id)) + { + return left.subject->seg_id < right.subject->seg_id; + } + + // Both left and right are located on the SAME segment. + + if (! (left.subject->fraction == right.subject->fraction)) + { + return left.subject->fraction < right.subject->fraction; + } + + + typedef typename boost::range_value::type turn_type; + turn_type const& left_turn = m_turns[left.turn_index]; + turn_type const& right_turn = m_turns[right.turn_index]; + + // First check "real" intersection (crosses) + // -> distance zero due to precision, solve it by sorting + if (left_turn.method == method_crosses + && right_turn.method == method_crosses) + { + return consider_relative_order(left, right); + } + + bool const left_both_xx = left_turn.both(operation_blocked); + bool const right_both_xx = right_turn.both(operation_blocked); + if (left_both_xx && ! right_both_xx) + { + return true; + } + if (! left_both_xx && right_both_xx) + { + return false; + } + + bool const left_both_uu = left_turn.both(operation_union); + bool const right_both_uu = right_turn.both(operation_union); + if (left_both_uu && ! right_both_uu) + { + return true; + } + if (! left_both_uu && right_both_uu) + { + return false; + } + + return default_order(left, right); + } +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_ON_SEGMENT_RATIO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp new file mode 100755 index 0000000000..063e1e9125 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/linear_linear.hpp @@ -0,0 +1,339 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP + +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include + + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +< + typename LineStringOut, + overlay_type OverlayType, + typename Geometry, + typename GeometryTag +> +struct linear_linear_no_intersections; + + +template +struct linear_linear_no_intersections + < + LineStringOut, overlay_difference, LineString, linestring_tag + > +{ + template + static inline OutputIterator apply(LineString const& linestring, + OutputIterator oit) + { + LineStringOut ls_out; + geometry::convert(linestring, ls_out); + *oit++ = ls_out; + return oit; + } +}; + + +template +struct linear_linear_no_intersections + < + LineStringOut, + overlay_difference, + MultiLineString, + multi_linestring_tag + > +{ + template + static inline OutputIterator apply(MultiLineString const& multilinestring, + OutputIterator oit) + { + for (typename boost::range_iterator::type + it = boost::begin(multilinestring); + it != boost::end(multilinestring); ++it) + { + LineStringOut ls_out; + geometry::convert(*it, ls_out); + *oit++ = ls_out; + } + return oit; + } +}; + + +template +struct linear_linear_no_intersections + < + LineStringOut, overlay_intersection, Geometry, GeometryTag + > +{ + template + static inline OutputIterator apply(Geometry const&, + OutputIterator oit) + { + return oit; + } +}; + + + + + + + +template +< + typename Linear1, + typename Linear2, + typename LinestringOut, + overlay_type OverlayType, + bool EnableFilterContinueTurns = false, + bool EnableRemoveDuplicateTurns = false, + bool EnableDegenerateTurns = true, +#ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS + bool EnableFollowIsolatedPoints = false +#else + bool EnableFollowIsolatedPoints = true +#endif +> +class linear_linear_linestring +{ +protected: + struct assign_policy + { + static bool const include_no_turn = false; + static bool const include_degenerate = EnableDegenerateTurns; + static bool const include_opposite = false; + + template + < + typename Info, + typename Point1, + typename Point2, + typename IntersectionInfo + > + static inline void apply(Info& , Point1 const& , Point2 const& , + IntersectionInfo const& ) + { + } + }; + + + template + < + typename Turns, + typename LinearGeometry1, + typename LinearGeometry2, + typename RobustPolicy + > + static inline void compute_turns(Turns& turns, + LinearGeometry1 const& linear1, + LinearGeometry2 const& linear2, + RobustPolicy const& robust_policy) + { + turns.clear(); + + detail::get_turns::no_interrupt_policy interrupt_policy; + + geometry::detail::relate::turns::get_turns + < + LinearGeometry1, + LinearGeometry2, + detail::get_turns::get_turn_info_type + < + LinearGeometry1, + LinearGeometry2, + assign_policy + >, + RobustPolicy + >::apply(turns, linear1, linear2, interrupt_policy, robust_policy); + } + + + template + < + overlay_type OverlayTypeForFollow, + bool FollowIsolatedPoints, + typename Turns, + typename LinearGeometry1, + typename LinearGeometry2, + typename OutputIterator + > + static inline OutputIterator + sort_and_follow_turns(Turns& turns, + LinearGeometry1 const& linear1, + LinearGeometry2 const& linear2, + OutputIterator oit) + { + // remove turns that have no added value + turns::filter_continue_turns + < + Turns, + EnableFilterContinueTurns && OverlayType != overlay_intersection + >::apply(turns); + + // sort by seg_id, distance, and operation + std::sort(boost::begin(turns), boost::end(turns), + detail::turns::less_seg_fraction_other_op<>()); + + // remove duplicate turns + turns::remove_duplicate_turns + < + Turns, EnableRemoveDuplicateTurns + >::apply(turns); + + return detail::overlay::following::linear::follow + < + LinestringOut, + LinearGeometry1, + LinearGeometry2, + OverlayTypeForFollow, + FollowIsolatedPoints, + !EnableFilterContinueTurns || OverlayType == overlay_intersection + >::apply(linear1, linear2, boost::begin(turns), boost::end(turns), + oit); + } + +public: + template + < + typename RobustPolicy, typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Linear1 const& linear1, + Linear2 const& linear2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& ) + { + typedef typename detail::relate::turns::get_turns + < + Linear1, + Linear2, + detail::get_turns::get_turn_info_type + < + Linear1, + Linear2, + assign_policy + >, + RobustPolicy + >::turn_info turn_info; + + typedef std::vector turns_container; + + turns_container turns; + compute_turns(turns, linear1, linear2, robust_policy); + + if ( turns.empty() ) + { + // the two linear geometries are disjoint + return linear_linear_no_intersections + < + LinestringOut, + OverlayType, + Linear1, + typename tag::type + >::apply(linear1, oit); + } + + return sort_and_follow_turns + < + OverlayType, + EnableFollowIsolatedPoints + && OverlayType == overlay_intersection + >(turns, linear1, linear2, oit); + } +}; + + + + +template +< + typename Linear1, + typename Linear2, + typename LinestringOut, + bool EnableFilterContinueTurns, + bool EnableRemoveDuplicateTurns, + bool EnableDegenerateTurns, + bool EnableFollowIsolatedPoints +> +struct linear_linear_linestring + < + Linear1, Linear2, LinestringOut, overlay_union, + EnableFilterContinueTurns, EnableRemoveDuplicateTurns, + EnableDegenerateTurns, EnableFollowIsolatedPoints + > +{ + template + < + typename RobustPolicy, typename OutputIterator, typename Strategy + > + static inline OutputIterator apply(Linear1 const& linear1, + Linear2 const& linear2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + oit = linear_linear_no_intersections + < + LinestringOut, + overlay_difference, + Linear1, + typename tag::type + >::apply(linear1, oit); + + return linear_linear_linestring + < + Linear2, Linear1, LinestringOut, overlay_difference, + EnableFilterContinueTurns, EnableRemoveDuplicateTurns, + EnableDegenerateTurns, EnableFollowIsolatedPoints + >::apply(linear2, linear1, robust_policy, oit, strategy); + } +}; + + + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/overlay.hpp new file mode 100755 index 0000000000..bb6dc4d252 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -0,0 +1,323 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP + + +#include +#include + +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + + +#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE +# include +#endif + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +//! Default visitor for overlay, doing nothing +struct overlay_null_visitor +{ + void print(char const* ) {} + + template + void print(char const* , Turns const& , int) {} + + template + void print(char const* , Turns const& , int , int ) {} + + template + void visit_turns(int , Turns const& ) {} + + template + void visit_clusters(Clusters const& , Turns const& ) {} + + template + void visit_traverse(Turns const& , Turn const& , Operation const& , char const*) + {} + + template + void visit_traverse_reject(Turns const& , Turn const& , Operation const& , traverse_error_type ) + {} +}; + +template +inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns) +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::container_type container_type; + + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + typename boost::range_value::type const& turn_info = *it; + + if (turn_info.discarded + && ! turn_info.any_blocked() + && ! turn_info.colocated) + { + continue; + } + + for (typename boost::range_iterator::type + op_it = boost::begin(turn_info.operations); + op_it != boost::end(turn_info.operations); + ++op_it) + { + ring_identifier const ring_id + ( + op_it->seg_id.source_index, + op_it->seg_id.multi_index, + op_it->seg_id.ring_index + ); + turn_info_map[ring_id].has_normal_turn = true; + } + } +} + + +template +< + typename GeometryOut, overlay_type OverlayType, bool ReverseOut, + typename Geometry1, typename Geometry2, + typename OutputIterator +> +inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, + Geometry2 const& geometry2, + OutputIterator out) +{ + typedef std::deque + < + typename geometry::ring_type::type + > ring_container_type; + + typedef ring_properties::type> properties; + +// Silence warning C4127: conditional expression is constant +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + + // Union: return either of them + // Intersection: return nothing + // Difference: return first of them + if (OverlayType == overlay_intersection + || (OverlayType == overlay_difference && geometry::is_empty(geometry1))) + { + return out; + } + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + + std::map empty; + std::map all_of_one_of_them; + + select_rings(geometry1, geometry2, empty, all_of_one_of_them); + ring_container_type rings; + assign_parents(geometry1, geometry2, rings, all_of_one_of_them); + return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out); +} + + +template +< + typename Geometry1, typename Geometry2, + bool Reverse1, bool Reverse2, bool ReverseOut, + typename GeometryOut, + overlay_type OverlayType +> +struct overlay +{ + template + static inline OutputIterator apply( + Geometry1 const& geometry1, Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& , + Visitor& visitor) + { + bool const is_empty1 = geometry::is_empty(geometry1); + bool const is_empty2 = geometry::is_empty(geometry2); + + if (is_empty1 && is_empty2) + { + return out; + } + + if (is_empty1 || is_empty2) + { + return return_if_one_input_is_empty + < + GeometryOut, OverlayType, ReverseOut + >(geometry1, geometry2, out); + } + + typedef typename geometry::point_type::type point_type; + typedef detail::overlay::traversal_turn_info + < + point_type, + typename geometry::segment_ratio_type::type + > turn_info; + typedef std::deque turn_container_type; + + typedef std::deque + < + typename geometry::ring_type::type + > ring_container_type; + + // Define the clusters, mapping cluster_id -> turns + typedef std::map + < + signed_size_type, + cluster_info + > cluster_type; + + turn_container_type turns; + +#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE +std::cout << "get turns" << std::endl; +#endif + detail::get_turns::no_interrupt_policy policy; + geometry::get_turns + < + Reverse1, Reverse2, + detail::overlay::assign_null_policy + >(geometry1, geometry2, robust_policy, turns, policy); + + visitor.visit_turns(1, turns); + +#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE +std::cout << "enrich" << std::endl; +#endif + typename Strategy::side_strategy_type side_strategy; + cluster_type clusters; + + geometry::enrich_intersection_points(turns, + clusters, geometry1, geometry2, + robust_policy, + side_strategy); + + visitor.visit_turns(2, turns); + + visitor.visit_clusters(clusters, turns); + +#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE +std::cout << "traverse" << std::endl; +#endif + // Traverse through intersection/turn points and create rings of them. + // Note that these rings are always in clockwise order, even in CCW polygons, + // and are marked as "to be reversed" below + ring_container_type rings; + traverse::apply + ( + geometry1, geometry2, + robust_policy, + turns, rings, + clusters, + visitor + ); + + std::map turn_info_per_ring; + get_ring_turn_info(turn_info_per_ring, turns); + + typedef ring_properties + < + typename geometry::point_type::type + > properties; + + // Select all rings which are NOT touched by any intersection point + std::map selected_ring_properties; + select_rings(geometry1, geometry2, turn_info_per_ring, + selected_ring_properties); + + // Add rings created during traversal + { + ring_identifier id(2, 0, -1); + for (typename boost::range_iterator::type + it = boost::begin(rings); + it != boost::end(rings); + ++it) + { + selected_ring_properties[id] = properties(*it); + selected_ring_properties[id].reversed = ReverseOut; + id.multi_index++; + } + } + + assign_parents(geometry1, geometry2, rings, selected_ring_properties); + + return add_rings(selected_ring_properties, geometry1, geometry2, rings, out); + } + + template + static inline OutputIterator apply( + Geometry1 const& geometry1, Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + OutputIterator out, + Strategy const& strategy) + { + overlay_null_visitor visitor; + return apply(geometry1, geometry2, robust_policy, out, strategy, visitor); + } +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp new file mode 100755 index 0000000000..61f1c75a9a --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp @@ -0,0 +1,67 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP + + + +namespace boost { namespace geometry +{ + +// TODO: move to detail +enum overlay_type +{ + overlay_union, + overlay_intersection, + overlay_difference, + overlay_buffer, + overlay_dissolve +}; + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +enum operation_type +{ + operation_none, + operation_union, + operation_intersection, + operation_blocked, + operation_continue, + operation_opposite +}; + + +template +struct operation_from_overlay +{ + static const operation_type value = operation_union; +}; + +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_intersection; +}; + +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_intersection; +}; + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp new file mode 100755 index 0000000000..1abba40dd6 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp @@ -0,0 +1,343 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP + +#include +#include + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +// action struct for pointlike-linear difference/intersection +// it works the same as its pointlike-pointlike counterpart, hence the +// derivation +template +struct action_selector_pl_l + : action_selector_pl_pl +{}; + +// difference/intersection of point-linear +template +< + typename Point, + typename Linear, + typename PointOut, + overlay_type OverlayType, + typename Policy +> +struct point_linear_point +{ + template + static inline OutputIterator apply(Point const& point, + Linear const& linear, + RobustPolicy const&, + OutputIterator oit, + Strategy const&) + { + action_selector_pl_l + < + PointOut, OverlayType + >::apply(point, Policy::apply(point, linear), oit); + return oit; + } +}; + +// difference/intersection of multipoint-segment +template +< + typename MultiPoint, + typename Segment, + typename PointOut, + overlay_type OverlayType, + typename Policy +> +struct multipoint_segment_point +{ + template + static inline OutputIterator apply(MultiPoint const& multipoint, + Segment const& segment, + RobustPolicy const&, + OutputIterator oit, + Strategy const&) + { + for (typename boost::range_iterator::type + it = boost::begin(multipoint); + it != boost::end(multipoint); + ++it) + { + action_selector_pl_l + < + PointOut, OverlayType + >::apply(*it, Policy::apply(*it, segment), oit); + } + + return oit; + } +}; + + +// difference/intersection of multipoint-linear +template +< + typename MultiPoint, + typename Linear, + typename PointOut, + overlay_type OverlayType, + typename Policy +> +class multipoint_linear_point +{ +private: + // structs for partition -- start + struct expand_box + { + template + static inline void apply(Box& total, Geometry const& geometry) + { + geometry::expand(total, geometry::return_envelope(geometry)); + } + + }; + + struct overlaps_box + { + template + static inline bool apply(Box const& box, Geometry const& geometry) + { + return ! geometry::disjoint(geometry, box); + } + }; + + template + class item_visitor_type + { + public: + item_visitor_type(OutputIterator& oit) : m_oit(oit) {} + + template + inline void apply(Item1 const& item1, Item2 const& item2) + { + action_selector_pl_l + < + PointOut, overlay_intersection + >::apply(item1, Policy::apply(item1, item2), m_oit); + } + + private: + OutputIterator& m_oit; + }; + // structs for partition -- end + + class segment_range + { + public: + typedef geometry::segment_iterator const_iterator; + typedef const_iterator iterator; + + segment_range(Linear const& linear) + : m_linear(linear) + {} + + const_iterator begin() const + { + return geometry::segments_begin(m_linear); + } + + const_iterator end() const + { + return geometry::segments_end(m_linear); + } + + private: + Linear const& m_linear; + }; + + template + static inline OutputIterator get_common_points(MultiPoint const& multipoint, + Linear const& linear, + OutputIterator oit) + { + item_visitor_type item_visitor(oit); + + segment_range rng(linear); + + geometry::partition + < + geometry::model::box + < + typename boost::range_value::type + >, + expand_box, + overlaps_box + >::apply(multipoint, rng, item_visitor); + + return oit; + } + +public: + template + static inline OutputIterator apply(MultiPoint const& multipoint, + Linear const& linear, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + typedef std::vector + < + typename boost::range_value::type + > point_vector_type; + + point_vector_type common_points; + + // compute the common points + get_common_points(multipoint, linear, + std::back_inserter(common_points)); + + return multipoint_multipoint_point + < + MultiPoint, point_vector_type, PointOut, OverlayType + >::apply(multipoint, common_points, robust_policy, oit, strategy); + } +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch { namespace overlay +{ + +// dispatch struct for pointlike-linear difference/intersection computation +template +< + typename PointLike, + typename Linear, + typename PointOut, + overlay_type OverlayType, + typename Tag1, + typename Tag2 +> +struct pointlike_linear_point + : not_implemented +{}; + + +template +< + typename Point, + typename Linear, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + Point, Linear, PointOut, OverlayType, point_tag, linear_tag + > : detail::overlay::point_linear_point + < + Point, Linear, PointOut, OverlayType, + detail::not_ + > +{}; + + +template +< + typename Point, + typename Segment, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + Point, Segment, PointOut, OverlayType, point_tag, segment_tag + > : detail::overlay::point_linear_point + < + Point, Segment, PointOut, OverlayType, + detail::not_ + > +{}; + + +template +< + typename MultiPoint, + typename Linear, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag + > : detail::overlay::multipoint_linear_point + < + MultiPoint, Linear, PointOut, OverlayType, + detail::not_ + > +{}; + + +template +< + typename MultiPoint, + typename Segment, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_linear_point + < + MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag + > : detail::overlay::multipoint_segment_point + < + MultiPoint, Segment, PointOut, OverlayType, + detail::not_ + > +{}; + + +}} // namespace detail_dispatch::overlay +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp new file mode 100755 index 0000000000..9faa1e84dd --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp @@ -0,0 +1,435 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014-2015, Oracle and/or its affiliates. + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +// struct for copying points of the pointlike geometries to output +template +< + typename PointOut, + typename GeometryIn, + typename TagIn = typename tag::type +> +struct copy_points + : not_implemented +{}; + +template +struct copy_points +{ + template + static inline void apply(PointIn const& point_in, + OutputIterator& oit) + { + PointOut point_out; + geometry::convert(point_in, point_out); + *oit++ = point_out; + } +}; + + +template +struct copy_points +{ + template + static inline void apply(MultiPointIn const& multi_point_in, + OutputIterator& oit) + { + for (typename boost::range_iterator::type + it = boost::begin(multi_point_in); + it != boost::end(multi_point_in); ++it) + { + PointOut point_out; + geometry::convert(*it, point_out); + *oit++ = point_out; + } + } +}; + + + +// action struct for difference/intersection +template +struct action_selector_pl_pl +{}; + +template +struct action_selector_pl_pl +{ + template + < + typename Point, + typename OutputIterator + > + static inline void apply(Point const& point, + bool is_common, + OutputIterator& oit) + { + if ( is_common ) + { + copy_points::apply(point, oit); + } + } +}; + + + +template +struct action_selector_pl_pl +{ + template + < + typename Point, + typename OutputIterator + > + static inline void apply(Point const& point, + bool is_common, + OutputIterator& oit) + { + if ( !is_common ) + { + copy_points::apply(point, oit); + } + } +}; + + +//=========================================================================== + +// difference/intersection of point-point +template +< + typename Point1, + typename Point2, + typename PointOut, + overlay_type OverlayType +> +struct point_point_point +{ + template + static inline OutputIterator apply(Point1 const& point1, + Point2 const& point2, + RobustPolicy const& , + OutputIterator oit, + Strategy const&) + { + action_selector_pl_pl + < + PointOut, OverlayType + >::apply(point1, + detail::equals::equals_point_point(point1, point2), + oit); + + return oit; + } +}; + + + +// difference of multipoint-point +// +// the apply method in the following struct is called only for +// difference; for intersection the reversal will +// always call the point-multipoint version +template +< + typename MultiPoint, + typename Point, + typename PointOut, + overlay_type OverlayType +> +struct multipoint_point_point +{ + template + static inline OutputIterator apply(MultiPoint const& multipoint, + Point const& point, + RobustPolicy const& , + OutputIterator oit, + Strategy const&) + { + BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference ); + + for (typename boost::range_iterator::type + it = boost::begin(multipoint); + it != boost::end(multipoint); ++it) + { + action_selector_pl_pl + < + PointOut, OverlayType + >::apply(*it, + detail::equals::equals_point_point(*it, point), + oit); + } + + return oit; + } +}; + + +// difference/intersection of point-multipoint +template +< + typename Point, + typename MultiPoint, + typename PointOut, + overlay_type OverlayType +> +struct point_multipoint_point +{ + template + static inline OutputIterator apply(Point const& point, + MultiPoint const& multipoint, + RobustPolicy const& , + OutputIterator oit, + Strategy const&) + { + typedef action_selector_pl_pl action; + + for (typename boost::range_iterator::type + it = boost::begin(multipoint); + it != boost::end(multipoint); ++it) + { + if ( detail::equals::equals_point_point(*it, point) ) + { + action::apply(point, true, oit); + return oit; + } + } + + action::apply(point, false, oit); + return oit; + } +}; + + + +// difference/intersection of multipoint-multipoint +template +< + typename MultiPoint1, + typename MultiPoint2, + typename PointOut, + overlay_type OverlayType +> +struct multipoint_multipoint_point +{ + template + static inline OutputIterator apply(MultiPoint1 const& multipoint1, + MultiPoint2 const& multipoint2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + if ( OverlayType != overlay_difference + && boost::size(multipoint1) > boost::size(multipoint2) ) + { + return multipoint_multipoint_point + < + MultiPoint2, MultiPoint1, PointOut, OverlayType + >::apply(multipoint2, multipoint1, robust_policy, oit, strategy); + } + + std::vector::type> + points2(boost::begin(multipoint2), boost::end(multipoint2)); + + std::sort(points2.begin(), points2.end(), detail::relate::less()); + + for (typename boost::range_iterator::type + it1 = boost::begin(multipoint1); + it1 != boost::end(multipoint1); ++it1) + { + bool found = std::binary_search(points2.begin(), points2.end(), + *it1, detail::relate::less()); + + action_selector_pl_pl + < + PointOut, OverlayType + >::apply(*it1, found, oit); + } + return oit; + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +//=========================================================================== + + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch { namespace overlay +{ + +// dispatch struct for pointlike-pointlike difference/intersection +// computation +template +< + typename PointLike1, + typename PointLike2, + typename PointOut, + overlay_type OverlayType, + typename Tag1, + typename Tag2 +> +struct pointlike_pointlike_point + : not_implemented +{}; + + +template +< + typename Point1, + typename Point2, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_pointlike_point + < + Point1, Point2, PointOut, OverlayType, + point_tag, point_tag + > : detail::overlay::point_point_point + < + Point1, Point2, PointOut, OverlayType + > +{}; + + +template +< + typename Point, + typename MultiPoint, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_pointlike_point + < + Point, MultiPoint, PointOut, OverlayType, + point_tag, multi_point_tag + > : detail::overlay::point_multipoint_point + < + Point, MultiPoint, PointOut, OverlayType + > +{}; + + +template +< + typename MultiPoint, + typename Point, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_pointlike_point + < + MultiPoint, Point, PointOut, OverlayType, + multi_point_tag, point_tag + > : detail::overlay::multipoint_point_point + < + MultiPoint, Point, PointOut, OverlayType + > +{}; + + +template +< + typename MultiPoint1, + typename MultiPoint2, + typename PointOut, + overlay_type OverlayType +> +struct pointlike_pointlike_point + < + MultiPoint1, MultiPoint2, PointOut, OverlayType, + multi_point_tag, multi_point_tag + > : detail::overlay::multipoint_multipoint_point + < + MultiPoint1, MultiPoint2, PointOut, OverlayType + > +{}; + + +}} // namespace detail_dispatch::overlay +#endif // DOXYGEN_NO_DISPATCH + + +//=========================================================================== + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +// generic pointlike-pointlike union implementation +template +< + typename PointLike1, + typename PointLike2, + typename PointOut +> +struct union_pointlike_pointlike_point +{ + template + static inline OutputIterator apply(PointLike1 const& pointlike1, + PointLike2 const& pointlike2, + RobustPolicy const& robust_policy, + OutputIterator oit, + Strategy const& strategy) + { + copy_points::apply(pointlike1, oit); + + return detail_dispatch::overlay::pointlike_pointlike_point + < + PointLike2, PointLike1, PointOut, overlay_difference, + typename tag::type, + typename tag::type + >::apply(pointlike2, pointlike1, robust_policy, oit, strategy); + } + +}; + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp new file mode 100755 index 0000000000..b701cbadf4 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/ring_properties.hpp @@ -0,0 +1,81 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP + + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +struct ring_properties +{ + typedef Point point_type; + typedef typename default_area_result::type area_type; + + bool valid; + + // Filled by "select_rings" + Point point; + area_type area; + + // Filled by "update_ring_selection" + bool reversed; + + // Filled/used by "assign_rings" + bool discarded; + ring_identifier parent; + area_type parent_area; + std::vector children; + + inline ring_properties() + : valid(false) + , area(area_type()) + , reversed(false) + , discarded(false) + , parent_area(-1) + {} + + template + inline ring_properties(RingOrBox const& ring_or_box) + : reversed(false) + , discarded(false) + , parent_area(-1) + { + this->area = geometry::area(ring_or_box); + // We should take a point somewhere in the middle of the ring, + // to avoid taking a point on a (self)tangency, + // in cases where multiple points come together + valid = geometry::point_on_border(this->point, ring_or_box, true); + } + + inline area_type get_area() const + { + return reversed ? -area : area; + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp new file mode 100755 index 0000000000..5be32f5754 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp @@ -0,0 +1,99 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP + + +#if defined(BOOST_GEOMETRY_DEBUG_OVERLAY) +# define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER +#endif + +#if defined(BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER) +#include +#endif + + +#include + + +namespace boost { namespace geometry +{ + + + +// Internal struct to uniquely identify a segment +// on a linestring,ring +// or polygon (needs ring_index) +// or multi-geometry (needs multi_index) +struct segment_identifier +{ + inline segment_identifier() + : source_index(-1) + , multi_index(-1) + , ring_index(-1) + , segment_index(-1) + , piece_index(-1) + {} + + inline segment_identifier(signed_size_type src, + signed_size_type mul, + signed_size_type rin, + signed_size_type seg) + : source_index(src) + , multi_index(mul) + , ring_index(rin) + , segment_index(seg) + , piece_index(-1) + {} + + inline bool operator<(segment_identifier const& other) const + { + return source_index != other.source_index ? source_index < other.source_index + : multi_index !=other.multi_index ? multi_index < other.multi_index + : ring_index != other.ring_index ? ring_index < other.ring_index + : segment_index < other.segment_index + ; + } + + inline bool operator==(segment_identifier const& other) const + { + return source_index == other.source_index + && segment_index == other.segment_index + && ring_index == other.ring_index + && multi_index == other.multi_index + ; + } + +#if defined(BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER) + friend std::ostream& operator<<(std::ostream &os, segment_identifier const& seg_id) + { + os + << "s:" << seg_id.source_index + << ", v:" << seg_id.segment_index // v:vertex because s is used for source + ; + if (seg_id.ring_index >= 0) os << ", r:" << seg_id.ring_index; + if (seg_id.multi_index >= 0) os << ", m:" << seg_id.multi_index; + return os; + } +#endif + + signed_size_type source_index; + signed_size_type multi_index; + signed_size_type ring_index; + signed_size_type segment_index; + + // For buffer - todo: move this to buffer-only + signed_size_type piece_index; +}; + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp new file mode 100755 index 0000000000..ed45e73a4a --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -0,0 +1,341 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP + + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +struct ring_turn_info +{ + bool has_normal_turn; + bool within_other; + + ring_turn_info() + : has_normal_turn(false) + , within_other(false) + {} +}; + +namespace dispatch +{ + + template + struct select_rings + {}; + + template + struct select_rings + { + template + static inline void apply(Box const& box, Geometry const& , + ring_identifier const& id, RingPropertyMap& ring_properties) + { + ring_properties[id] = typename RingPropertyMap::mapped_type(box); + } + + template + static inline void apply(Box const& box, + ring_identifier const& id, RingPropertyMap& ring_properties) + { + ring_properties[id] = typename RingPropertyMap::mapped_type(box); + } + }; + + template + struct select_rings + { + template + static inline void apply(Ring const& ring, Geometry const& , + ring_identifier const& id, RingPropertyMap& ring_properties) + { + if (boost::size(ring) > 0) + { + ring_properties[id] = typename RingPropertyMap::mapped_type(ring); + } + } + + template + static inline void apply(Ring const& ring, + ring_identifier const& id, RingPropertyMap& ring_properties) + { + if (boost::size(ring) > 0) + { + ring_properties[id] = typename RingPropertyMap::mapped_type(ring); + } + } + }; + + + template + struct select_rings + { + template + static inline void apply(Polygon const& polygon, Geometry const& geometry, + ring_identifier id, RingPropertyMap& ring_properties) + { + typedef typename geometry::ring_type::type ring_type; + typedef select_rings per_ring; + + per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties); + + typename interior_return_type::type + rings = interior_rings(polygon); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + id.ring_index++; + per_ring::apply(*it, geometry, id, ring_properties); + } + } + + template + static inline void apply(Polygon const& polygon, + ring_identifier id, RingPropertyMap& ring_properties) + { + typedef typename geometry::ring_type::type ring_type; + typedef select_rings per_ring; + + per_ring::apply(exterior_ring(polygon), id, ring_properties); + + typename interior_return_type::type + rings = interior_rings(polygon); + for (typename detail::interior_iterator::type + it = boost::begin(rings); it != boost::end(rings); ++it) + { + id.ring_index++; + per_ring::apply(*it, id, ring_properties); + } + } + }; + + template + struct select_rings + { + template + static inline void apply(Multi const& multi, Geometry const& geometry, + ring_identifier id, RingPropertyMap& ring_properties) + { + typedef typename boost::range_iterator + < + Multi const + >::type iterator_type; + + typedef select_rings::type> per_polygon; + + id.multi_index = 0; + for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it) + { + id.ring_index = -1; + per_polygon::apply(*it, geometry, id, ring_properties); + id.multi_index++; + } + } + }; + +} // namespace dispatch + + +template +struct decide +{ + // Default implementation (union, inflate, deflate, dissolve) + static bool include(ring_identifier const& , ring_turn_info const& info) + { + return ! info.within_other; + } + + static bool reversed(ring_identifier const& , ring_turn_info const& ) + { + return false; + } + +}; + +template<> +struct decide +{ + static bool include(ring_identifier const& id, ring_turn_info const& info) + { + // Difference: A - B + + // If this is A (source_index=0), then the ring is inside B + // If this is B (source_index=1), then the ring is NOT inside A + + // If this is A and the ring is within the other geometry, + // then we should NOT include it. + // If this is B then we SHOULD include it. + + return id.source_index == 0 + ? ! info.within_other + : info.within_other; + } + + static bool reversed(ring_identifier const& id, ring_turn_info const& info) + { + // Difference: A - B + // If this is B, and the ring is included, it should be reversed afterwards + + return id.source_index == 1 && include(id, info); + } +}; + +template<> +struct decide +{ + static bool include(ring_identifier const& , ring_turn_info const& info) + { + return info.within_other; + } + + static bool reversed(ring_identifier const& , ring_turn_info const& ) + { + return false; + } +}; + + +template +< + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename TurnInfoMap, + typename RingPropertyMap +> +inline void update_ring_selection(Geometry1 const& geometry1, + Geometry2 const& geometry2, + TurnInfoMap const& turn_info_map, + RingPropertyMap const& all_ring_properties, + RingPropertyMap& selected_ring_properties) +{ + selected_ring_properties.clear(); + + for (typename RingPropertyMap::const_iterator it = boost::begin(all_ring_properties); + it != boost::end(all_ring_properties); + ++it) + { + ring_identifier const& id = it->first; + + ring_turn_info info; + + typename TurnInfoMap::const_iterator tcit = turn_info_map.find(id); + if (tcit != turn_info_map.end()) + { + info = tcit->second; // Copy by value + } + + if (info.has_normal_turn) + { + // There are normal turns on this ring. It should be traversed, we + // don't include the original ring + continue; + } + + // Check if the ring is within the other geometry, by taking + // a point lying on the ring + switch(id.source_index) + { + case 0 : + info.within_other = geometry::within(it->second.point, geometry2); + break; + case 1 : + info.within_other = geometry::within(it->second.point, geometry1); + break; + } + + if (decide::include(id, info)) + { + typename RingPropertyMap::mapped_type properties = it->second; // Copy by value + properties.reversed = decide::reversed(id, info); + selected_ring_properties[id] = properties; + } + } +} + + +/*! +\brief The function select_rings select rings based on the overlay-type (union,intersection) +*/ +template +< + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename RingTurnInfoMap, + typename RingPropertyMap +> +inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2, + RingTurnInfoMap const& turn_info_per_ring, + RingPropertyMap& selected_ring_properties) +{ + typedef typename geometry::tag::type tag1; + typedef typename geometry::tag::type tag2; + + RingPropertyMap all_ring_properties; + dispatch::select_rings::apply(geometry1, geometry2, + ring_identifier(0, -1, -1), all_ring_properties); + dispatch::select_rings::apply(geometry2, geometry1, + ring_identifier(1, -1, -1), all_ring_properties); + + update_ring_selection(geometry1, geometry2, turn_info_per_ring, + all_ring_properties, selected_ring_properties); +} + +template +< + overlay_type OverlayType, + typename Geometry, + typename RingTurnInfoMap, + typename RingPropertyMap +> +inline void select_rings(Geometry const& geometry, + RingTurnInfoMap const& turn_info_per_ring, + RingPropertyMap& selected_ring_properties) +{ + typedef typename geometry::tag::type tag; + + RingPropertyMap all_ring_properties; + dispatch::select_rings::apply(geometry, + ring_identifier(0, -1, -1), all_ring_properties); + + update_ring_selection(geometry, geometry, turn_info_per_ring, + all_ring_properties, selected_ring_properties); +} + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp new file mode 100755 index 0000000000..90b6cac764 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -0,0 +1,295 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP + + +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace self_get_turn_points +{ + +struct no_interrupt_policy +{ + static bool const enabled = false; + static bool const has_intersections = false; + + + template + static inline bool apply(Range const&) + { + return false; + } +}; + + + + +class self_ip_exception : public geometry::exception {}; + +template +< + typename Geometry, + typename Turns, + typename TurnPolicy, + typename RobustPolicy, + typename InterruptPolicy +> +struct self_section_visitor +{ + Geometry const& m_geometry; + RobustPolicy const& m_rescale_policy; + Turns& m_turns; + InterruptPolicy& m_interrupt_policy; + + inline self_section_visitor(Geometry const& g, + RobustPolicy const& rp, + Turns& turns, InterruptPolicy& ip) + : m_geometry(g) + , m_rescale_policy(rp) + , m_turns(turns) + , m_interrupt_policy(ip) + {} + + template + inline bool apply(Section const& sec1, Section const& sec2) + { + if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box) + && ! sec1.duplicate + && ! sec2.duplicate) + { + detail::get_turns::get_turns_in_sections + < + Geometry, Geometry, + false, false, + Section, Section, + TurnPolicy + >::apply( + 0, m_geometry, sec1, + 0, m_geometry, sec2, + false, + m_rescale_policy, + m_turns, m_interrupt_policy); + } + if (BOOST_GEOMETRY_CONDITION(m_interrupt_policy.has_intersections)) + { + // TODO: we should give partition an interrupt policy. + // Now we throw, and catch below, to stop the partition loop. + throw self_ip_exception(); + } + return true; + } + +}; + + + +template +struct get_turns +{ + template + static inline bool apply( + Geometry const& geometry, + RobustPolicy const& robust_policy, + Turns& turns, + InterruptPolicy& interrupt_policy) + { + typedef model::box + < + typename geometry::robust_point_type + < + typename geometry::point_type::type, + RobustPolicy + >::type + > box_type; + + typedef geometry::sections sections_type; + + typedef boost::mpl::vector_c dimensions; + + sections_type sec; + geometry::sectionalize(geometry, robust_policy, sec); + + self_section_visitor + < + Geometry, + Turns, TurnPolicy, RobustPolicy, InterruptPolicy + > visitor(geometry, robust_policy, turns, interrupt_policy); + + try + { + geometry::partition + < + box_type, + detail::section::get_section_box, + detail::section::overlaps_section_box + >::apply(sec, visitor); + } + catch(self_ip_exception const& ) + { + return false; + } + + return true; + } +}; + + +}} // namespace detail::self_get_turn_points +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename GeometryTag, + typename Geometry, + typename TurnPolicy +> +struct self_get_turn_points +{ +}; + + +template +< + typename Ring, + typename TurnPolicy +> +struct self_get_turn_points + < + ring_tag, Ring, + TurnPolicy + > + : detail::self_get_turn_points::get_turns +{}; + + +template +< + typename Box, + typename TurnPolicy +> +struct self_get_turn_points + < + box_tag, Box, + TurnPolicy + > +{ + template + static inline bool apply( + Box const& , + RobustPolicy const& , + Turns& , + InterruptPolicy& ) + { + return true; + } +}; + + +template +< + typename Polygon, + typename TurnPolicy +> +struct self_get_turn_points + < + polygon_tag, Polygon, + TurnPolicy + > + : detail::self_get_turn_points::get_turns +{}; + + +template +< + typename MultiPolygon, + typename TurnPolicy +> +struct self_get_turn_points + < + multi_polygon_tag, MultiPolygon, + TurnPolicy + > + : detail::self_get_turn_points::get_turns +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! + \brief Calculate self intersections of a geometry + \ingroup overlay + \tparam Geometry geometry type + \tparam Turns type of intersection container + (e.g. vector of "intersection/turn point"'s) + \param geometry geometry + \param robust_policy policy to handle robustness issues + \param turns container which will contain intersection points + \param interrupt_policy policy determining if process is stopped + when intersection is found + */ +template +< + typename AssignPolicy, + typename Geometry, + typename RobustPolicy, + typename Turns, + typename InterruptPolicy +> +inline void self_turns(Geometry const& geometry, + RobustPolicy const& robust_policy, + Turns& turns, InterruptPolicy& interrupt_policy) +{ + concepts::check(); + + typedef detail::overlay::get_turn_info turn_policy; + + dispatch::self_get_turn_points + < + typename tag::type, + Geometry, + turn_policy + >::apply(geometry, robust_policy, turns, interrupt_policy); +} + + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp new file mode 100755 index 0000000000..0685e013b9 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -0,0 +1,540 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP + +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay { namespace sort_by_side +{ + +enum direction_type { dir_unknown = -1, dir_from = 0, dir_to = 1 }; + +// Point-wrapper, adding some properties +template +struct ranked_point +{ + ranked_point() + : rank(0) + , turn_index(-1) + , operation_index(-1) + , direction(dir_unknown) + , count_left(0) + , count_right(0) + , operation(operation_none) + {} + + ranked_point(const Point& p, signed_size_type ti, signed_size_type oi, + direction_type d, operation_type op, segment_identifier sid) + : point(p) + , rank(0) + , zone(-1) + , turn_index(ti) + , operation_index(oi) + , direction(d) + , count_left(0) + , count_right(0) + , operation(op) + , seg_id(sid) + {} + + Point point; + std::size_t rank; + signed_size_type zone; // index of closed zone, in uu turn there would be 2 zones + signed_size_type turn_index; + signed_size_type operation_index; + direction_type direction; + std::size_t count_left; + std::size_t count_right; + operation_type operation; + segment_identifier seg_id; +}; + +struct less_by_turn_index +{ + template + inline bool operator()(const T& first, const T& second) const + { + return first.turn_index == second.turn_index + ? first.index < second.index + : first.turn_index < second.turn_index + ; + } +}; + +struct less_by_index +{ + template + inline bool operator()(const T& first, const T& second) const + { + // First order by from/to + if (first.direction != second.direction) + { + return first.direction < second.direction; + } + // All the same, order by turn index (we might consider length too) + return first.turn_index < second.turn_index; + } +}; + +struct less_false +{ + template + inline bool operator()(const T&, const T& ) const + { + return false; + } +}; + +template +struct less_by_side +{ + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side; + + less_by_side(const Point& p1, const Point& p2) + : m_p1(p1) + , m_p2(p2) + {} + + template + inline bool operator()(const T& first, const T& second) const + { + LessOnSame on_same; + Compare compare; + + int const side_first = side::apply(m_p1, m_p2, first.point); + int const side_second = side::apply(m_p1, m_p2, second.point); + + if (side_first == 0 && side_second == 0) + { + // Both collinear. They might point into different directions: <------*------> + // If so, order the one going backwards as the very first. + + int const first_code = direction_code(m_p1, m_p2, first.point); + int const second_code = direction_code(m_p1, m_p2, second.point); + + // Order by code, backwards first, then forward. + return first_code != second_code + ? first_code < second_code + : on_same(first, second) + ; + } + else if (side_first == 0 + && direction_code(m_p1, m_p2, first.point) == -1) + { + // First collinear and going backwards. + // Order as the very first, so return always true + return true; + } + else if (side_second == 0 + && direction_code(m_p1, m_p2, second.point) == -1) + { + // Second is collinear and going backwards + // Order as very last, so return always false + return false; + } + + // They are not both collinear + + if (side_first != side_second) + { + return compare(side_first, side_second); + } + + // They are both left, both right, and/or both collinear (with each other and/or with p1,p2) + // Check mutual side + int const side_second_wrt_first = side::apply(m_p2, first.point, second.point); + + if (side_second_wrt_first == 0) + { + return on_same(first, second); + } + + int const side_first_wrt_second = -side_second_wrt_first; + + // Both are on same side, and not collinear + // Union: return true if second is right w.r.t. first, so -1, + // so other is 1. union has greater as compare functor + // Intersection: v.v. + return compare(side_first_wrt_second, side_second_wrt_first); + } + +private : + Point m_p1, m_p2; +}; + +template +struct side_sorter +{ + typedef ranked_point rp; + + inline void set_origin(Point const& origin) + { + m_origin = origin; + } + + template + void add(Operation const& op, signed_size_type turn_index, signed_size_type op_index, + Geometry1 const& geometry1, + Geometry2 const& geometry2, + bool is_origin) + { + Point point1, point2, point3; + geometry::copy_segment_points(geometry1, geometry2, + op.seg_id, point1, point2, point3); + Point const& point_to = op.fraction.is_one() ? point3 : point2; + + m_ranked_points.push_back(rp(point1, turn_index, op_index, dir_from, op.operation, op.seg_id)); + m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op.operation, op.seg_id)); + + if (is_origin) + { + m_origin = point1; + } + } + + void apply(Point const& turn_point) + { + // We need three compare functors: + // 1) to order clockwise (union) or counter clockwise (intersection) + // 2) to order by side, resulting in unique ranks for all points + // 3) to order by side, resulting in non-unique ranks + // to give colinear points + + // Sort by side and assign rank + less_by_side less_unique(m_origin, turn_point); + less_by_side less_non_unique(m_origin, turn_point); + + std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique); + + std::size_t colinear_rank = 0; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + if (i > 0 + && less_non_unique(m_ranked_points[i - 1], m_ranked_points[i])) + { + // It is not collinear + colinear_rank++; + } + + m_ranked_points[i].rank = colinear_rank; + } + } + + template + void find_open_generic(Map& handled) + { + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + const rp& ranked = m_ranked_points[i]; + if (ranked.direction != dir_from) + { + continue; + } + + signed_size_type const& index = ranked.seg_id.*Member; + if (! handled[index]) + { + find_polygons_for_source(index, i); + handled[index] = true; + } + } + } + + void find_open() + { + // TODO: we might pass Buffer as overlay_type, instead on the fly below + bool one_source = true; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + const rp& ranked = m_ranked_points[i]; + signed_size_type const& src = ranked.seg_id.source_index; + if (src != 0) + { + one_source = false; + break; + } + } + + if (one_source) + { + // by multi index + std::map handled; + find_open_generic + < + &segment_identifier::piece_index + >(handled); + } + else + { + // by source (there should only source 0,1) TODO assert this + bool handled[2] = {false, false}; + find_open_generic + < + &segment_identifier::source_index + >(handled); + } + + assign_zones(); + } + + void reverse() + { + if (m_ranked_points.empty()) + { + return; + } + + int const last = 1 + m_ranked_points.back().rank; + + // Move iterator after rank==0 + bool has_first = false; + typename container_type::iterator it = m_ranked_points.begin() + 1; + for (; it != m_ranked_points.end() && it->rank == 0; ++it) + { + has_first = true; + } + + if (has_first) + { + // Reverse first part (having rank == 0), if any, + // but skip the very first row + std::reverse(m_ranked_points.begin() + 1, it); + for (typename container_type::iterator fit = m_ranked_points.begin(); + fit != it; ++fit) + { + BOOST_ASSERT(fit->rank == 0); + } + } + + // Reverse the rest (main rank > 0) + std::reverse(it, m_ranked_points.end()); + for (; it != m_ranked_points.end(); ++it) + { + BOOST_ASSERT(it->rank > 0); + it->rank = last - it->rank; + } + } + + //! Check how many open spaces there are + template + std::size_t open_count(Turns const& turns) const + { + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + std::size_t result = 0; + std::size_t last_rank = 0; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp const& ranked_point = m_ranked_points[i]; + + if (ranked_point.rank > last_rank + && ranked_point.direction == sort_by_side::dir_to) + { + // TODO: take count-left / count_right from rank itself + turn_type const& ranked_turn = turns[ranked_point.turn_index]; + turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index]; + if (ranked_op.enriched.count_left == 0 + && ranked_op.enriched.count_right > 0) + { + result++; + last_rank = ranked_point.rank; + } + } + } + return result; + } + +//protected : + + typedef std::vector container_type; + container_type m_ranked_points; + Point m_origin; + +private : + + + std::size_t move(std::size_t index) const + { + std::size_t const result = index + 1; + return result >= m_ranked_points.size() ? 0 : result; + } + + //! member is pointer to member (source_index or multi_index) + template + std::size_t move(signed_size_type member_index, std::size_t index) const + { + std::size_t result = move(index); + while (m_ranked_points[result].seg_id.*Member != member_index) + { + result = move(result); + } + return result; + } + + void assign_ranks(std::size_t min_rank, std::size_t max_rank, int side_index) + { + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp& ranked = m_ranked_points[i]; + // Suppose there are 8 ranks, if min=4,max=6: assign 4,5,6 + // if min=5,max=2: assign from 5,6,7,1,2 + bool const in_range + = max_rank >= min_rank + ? ranked.rank >= min_rank && ranked.rank <= max_rank + : ranked.rank >= min_rank || ranked.rank <= max_rank + ; + + if (in_range) + { + if (side_index == 1) + { + ranked.count_left++; + } + else if (side_index == 2) + { + ranked.count_right++; + } + } + } + } + + template + void find_polygons_for_source(signed_size_type the_index, + std::size_t start_index) + { + int state = 1; // 'closed', because start_index is "from", arrives at the turn + std::size_t last_from_rank = m_ranked_points[start_index].rank; + std::size_t previous_rank = m_ranked_points[start_index].rank; + + for (std::size_t index = move(the_index, start_index); + ; + index = move(the_index, index)) + { + rp& ranked = m_ranked_points[index]; + + if (ranked.rank != previous_rank && state == 0) + { + assign_ranks(last_from_rank, previous_rank - 1, 1); + assign_ranks(last_from_rank + 1, previous_rank, 2); + } + + if (index == start_index) + { + return; + } + + if (ranked.direction == dir_from) + { + last_from_rank = ranked.rank; + state++; + } + else if (ranked.direction == dir_to) + { + state--; + } + + previous_rank = ranked.rank; + } + } + + //! Find closed zones and assign it + void assign_zones() + { + // Find a starting point (the first rank after an outgoing rank + // with no polygons on the left side) + std::size_t start_rank = m_ranked_points.size() + 1; + std::size_t start_index = 0; + std::size_t max_rank = 0; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp const& ranked_point = m_ranked_points[i]; + if (ranked_point.rank > max_rank) + { + max_rank = ranked_point.rank; + } + if (ranked_point.direction == sort_by_side::dir_to + && ranked_point.count_left == 0 + && ranked_point.count_right > 0) + { + start_rank = ranked_point.rank + 1; + } + if (ranked_point.rank == start_rank && start_index == 0) + { + start_index = i; + } + } + + // Assign the zones + std::size_t const undefined_rank = max_rank + 1; + std::size_t zone_id = 0; + std::size_t last_rank = 0; + std::size_t rank_at_next_zone = undefined_rank; + std::size_t index = start_index; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp& ranked_point = m_ranked_points[index]; + + // Implement cyclic behavior + index++; + if (index == m_ranked_points.size()) + { + index = 0; + } + + if (ranked_point.rank != last_rank) + { + if (ranked_point.rank == rank_at_next_zone) + { + zone_id++; + rank_at_next_zone = undefined_rank; + } + + if (ranked_point.direction == sort_by_side::dir_to + && ranked_point.count_left == 0 + && ranked_point.count_right > 0) + { + rank_at_next_zone = ranked_point.rank + 1; + if (rank_at_next_zone > max_rank) + { + rank_at_next_zone = 0; + } + } + + last_rank = ranked_point.rank; + } + + ranked_point.zone = zone_id; + } + } + + +}; + + +}}} // namespace detail::overlay::sort_by_side +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SORT_BY_SIDE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/stream_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/stream_info.hpp new file mode 100755 index 0000000000..0a6c84b7f5 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/stream_info.hpp @@ -0,0 +1,74 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP + + +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + + static inline std::string dir(int d) + { + return d == 0 ? "-" : (d == 1 ? "L" : d == -1 ? "R" : "#"); + } + static inline std::string how_str(int h) + { + return h == 0 ? "-" : (h == 1 ? "A" : "D"); + } + + template + std::ostream& operator<<(std::ostream &os, turn_info

const& info) + { + os << "\t" + << " src " << info.seg_id.source_index + << " seg " << info.seg_id.segment_index + << " (// " << info.other_id.source_index + << "." << info.other_id.segment_index << ")" + << " how " << info.how + << "[" << how_str(info.arrival) + << " " << dir(info.direction) + << (info.opposite ? " o" : "") + << "]" + << " sd " + << dir(info.sides.get<0,0>()) + << dir(info.sides.get<0,1>()) + << dir(info.sides.get<1,0>()) + << dir(info.sides.get<1,1>()) + << " nxt seg " << info.travels_to_vertex_index + << " , ip " << info.travels_to_ip_index + << " , or " << info.next_ip_index + << " frac " << info.fraction + << info.visit_state; + if (info.flagged) + { + os << " FLAGGED"; + } + return os; + } + + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal.hpp new file mode 100755 index 0000000000..46e2e19214 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -0,0 +1,672 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP + +#include + +#include + +#include +#include +#include +#include + +#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \ + || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \ + || defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) +# include +# include +# include +#endif + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE +inline void debug_traverse(Turn const& turn, Operation op, + std::string const& header) +{ + std::cout << header + << " at " << op.seg_id + << " meth: " << method_char(turn.method) + << " op: " << operation_char(op.operation) + << " vis: " << visited_char(op.visited) + << " of: " << operation_char(turn.operations[0].operation) + << operation_char(turn.operations[1].operation) + << " " << geometry::wkt(turn.point) + << std::endl; + + if (boost::contains(header, "Finished")) + { + std::cout << std::endl; + } +} +#else +inline void debug_traverse(Turn const& , Operation, const char*) +{ +} +#endif + + +//! Metafunction to define side_order (clockwise, ccw) by operation_type +template +struct side_compare {}; + +template <> +struct side_compare +{ + typedef std::greater type; +}; + +template <> +struct side_compare +{ + typedef std::less type; +}; + + +template +< + bool Reverse1, + bool Reverse2, + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename Turns, + typename Clusters, + typename RobustPolicy, + typename Visitor +> +struct traversal +{ + static const operation_type target_operation = operation_from_overlay::value; + + typedef typename side_compare::type side_compare_type; + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + typedef typename geometry::point_type::type point_type; + typedef sort_by_side::side_sorter + < + Reverse1, Reverse2, + point_type, side_compare_type + > sbs_type; + + inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2, + Turns& turns, Clusters const& clusters, + RobustPolicy const& robust_policy, Visitor& visitor) + : m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_turns(turns) + , m_clusters(clusters) + , m_robust_policy(robust_policy) + , m_visitor(visitor) + { + } + + inline void finalize_visit_info() + { + for (typename boost::range_iterator::type + it = boost::begin(m_turns); + it != boost::end(m_turns); + ++it) + { + turn_type& turn = *it; + for (int i = 0; i < 2; i++) + { + turn_operation_type& op = turn.operations[i]; + op.visited.finalize(); + } + } + } + + inline void set_visited(turn_type& turn, turn_operation_type& op) + { + // On "continue", set "visited" for ALL directions in this turn + if (op.operation == detail::overlay::operation_continue) + { + for (int i = 0; i < 2; i++) + { + turn_operation_type& op = turn.operations[i]; + if (op.visited.none()) + { + op.visited.set_visited(); + } + } + } + else + { + op.visited.set_visited(); + } + } + + inline bool is_visited(turn_type const& turn, turn_operation_type const& op, + signed_size_type turn_index, int op_index) const + { + return op.visited.visited(); + } + + inline bool select_source(signed_size_type turn_index, + segment_identifier const& seg_id1, + segment_identifier const& seg_id2) const + { + if (target_operation == operation_intersection) + { + // For intersections always switch sources + return seg_id1.source_index != seg_id2.source_index; + } + else if (target_operation == operation_union) + { + // For uu, only switch sources if indicated + turn_type const& turn = m_turns[turn_index]; + + if (OverlayType == overlay_buffer) + { + // Buffer does not use source_index (always 0) + return turn.switch_source + ? seg_id1.multi_index != seg_id2.multi_index + : seg_id1.multi_index == seg_id2.multi_index; + } + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + if (turn.switch_source == 1) + { + std::cout << "Switch source at " << turn_index << std::endl; + } + else + { + std::cout << "DON'T SWITCH SOURCES at " << turn_index << std::endl; + } +#endif + return turn.switch_source + ? seg_id1.source_index != seg_id2.source_index + : seg_id1.source_index == seg_id2.source_index; + } + return false; + } + + inline + signed_size_type get_next_turn_index(turn_operation_type const& op) const + { + return op.enriched.next_ip_index == -1 + ? op.enriched.travels_to_ip_index + : op.enriched.next_ip_index; + } + + inline bool traverse_possible(signed_size_type turn_index) const + { + if (turn_index == -1) + { + return false; + } + + turn_type const& turn = m_turns[turn_index]; + + // It is not a dead end if there is an operation to continue, or of + // there is a cluster (assuming for now we can get out of the cluster) + return turn.cluster_id >= 0 + || turn.has(target_operation) + || turn.has(operation_continue); + } + + inline + bool select_cc_operation(turn_type const& turn, + signed_size_type start_turn_index, + int& selected_op_index) const + { + // For "cc", take either one, but if there is a starting one, + // take that one. If next is dead end, skip that one. + + bool result = false; + + typename turn_operation_type::comparable_distance_type + max_remaining_distance = 0; + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = turn.operations[i]; + + signed_size_type const next_turn_index = get_next_turn_index(op); + + if (! result && traverse_possible(next_turn_index)) + { + max_remaining_distance = op.remaining_distance; + selected_op_index = i; + debug_traverse(turn, op, " Candidate"); + result = true; + } + + if (result) + { + if (next_turn_index == start_turn_index) + { + selected_op_index = i; + debug_traverse(turn, op, " Candidate cc override (start)"); + } + else if (op.remaining_distance > max_remaining_distance) + { + max_remaining_distance = op.remaining_distance; + selected_op_index = i; + debug_traverse(turn, op, " Candidate cc override (remaining)"); + } + } + } + + return result; + } + + inline + bool select_noncc_operation(turn_type const& turn, + signed_size_type turn_index, + segment_identifier const& seg_id, + int& selected_op_index) const + { + // For "ii", take the other one (alternate) + // UNLESS the other one is already visited + // For "uu", take the same one (see above); + + bool result = false; + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = turn.operations[i]; + + if (op.operation == target_operation + && ! op.visited.finished() + && (! result || select_source(turn_index, op.seg_id, seg_id))) + { + selected_op_index = i; + debug_traverse(turn, op, " Candidate"); + result = true; + } + } + + return result; + } + + inline + bool select_operation(const turn_type& turn, + signed_size_type turn_index, + signed_size_type start_turn_index, + segment_identifier const& previous_seg_id, + int& selected_op_index) const + { + bool result = false; + selected_op_index = -1; + if (turn.both(operation_continue)) + { + result = select_cc_operation(turn, start_turn_index, + selected_op_index); + } + else + { + result = select_noncc_operation(turn, turn_index, + previous_seg_id, selected_op_index); + } + if (result) + { + debug_traverse(turn, turn.operations[selected_op_index], " Accepted"); + } + + return result; + } + + inline int starting_operation_index(const turn_type& turn) const + { + for (int i = 0; i < 2; i++) + { + if (turn.operations[i].visited.started()) + { + return i; + } + } + return -1; + } + + inline bool both_finished(const turn_type& turn) const + { + for (int i = 0; i < 2; i++) + { + if (! turn.operations[i].visited.finished()) + { + return false; + } + } + return true; + } + + inline bool select_from_cluster(signed_size_type& turn_index, + int& op_index, signed_size_type start_turn_index, + sbs_type const& sbs, bool is_touching) const + { + bool const is_union = target_operation == operation_union; + bool const is_intersection = target_operation == operation_intersection; + + std::size_t selected_rank = 0; + std::size_t min_rank = 0; + bool result = false; + for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) + { + typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i]; + if (result && ranked_point.rank > selected_rank) + { + return result; + } + + turn_type const& ranked_turn = m_turns[ranked_point.turn_index]; + turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index]; + + if (result && ranked_op.visited.finalized()) + { + // One of the arcs in the same direction as the selected result + // is already traversed. + return false; + } + + if (! is_touching && ranked_op.visited.finalized()) + { + // Skip this one, go to next + min_rank = ranked_point.rank; + continue; + } + + if (ranked_point.direction == sort_by_side::dir_to + && (ranked_point.rank > min_rank + || ranked_turn.both(operation_continue))) + { + if ((is_union + && ranked_op.enriched.count_left == 0 + && ranked_op.enriched.count_right > 0) + || (is_intersection + && ranked_op.enriched.count_right == 2)) + { + if (result && ranked_point.turn_index != start_turn_index) + { + // Don't override - only override if arrive at start + continue; + } + + turn_index = ranked_point.turn_index; + op_index = ranked_point.operation_index; + + if (is_intersection + && ranked_turn.both(operation_intersection) + && ranked_op.visited.finalized()) + { + // Override: + // For a ii turn, even though one operation might be selected, + // it should take the other one if the first one is used in a completed ring + op_index = 1 - ranked_point.operation_index; + } + + result = true; + selected_rank = ranked_point.rank; + } + else if (! is_touching) + { + return result; + } + } + } + return result; + } + + inline bool select_turn_from_cluster(signed_size_type& turn_index, + int& op_index, bool& is_touching, + signed_size_type start_turn_index, + segment_identifier const& previous_seg_id) const + { + bool const is_union = target_operation == operation_union; + + turn_type const& turn = m_turns[turn_index]; + BOOST_ASSERT(turn.cluster_id >= 0); + + typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id); + BOOST_ASSERT(mit != m_clusters.end()); + + cluster_info const& cinfo = mit->second; + std::set const& ids = cinfo.turn_indices; + + sbs_type sbs; + + bool has_origin = false; + + for (typename std::set::const_iterator sit = ids.begin(); + sit != ids.end(); ++sit) + { + signed_size_type cluster_turn_index = *sit; + turn_type const& cluster_turn = m_turns[cluster_turn_index]; + if (cluster_turn.discarded) + { + // Defensive check, discarded turns should not be in cluster + continue; + } + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = cluster_turn.operations[i]; + bool is_origin = false; + if (cluster_turn_index == turn_index) + { + // Check if this is the origin + if (OverlayType == overlay_buffer) + { + is_origin = op.seg_id.multi_index == previous_seg_id.multi_index; + } + else + { + is_origin = op.seg_id.source_index + == previous_seg_id.source_index; + } + if (is_origin) + { + has_origin = true; + } + } + + sbs.add(op, cluster_turn_index, i, m_geometry1, m_geometry2, + is_origin); + } + } + + if (! has_origin) + { + return false; + } + + sbs.apply(turn.point); + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + is_touching = is_union && cinfo.open_count > 1; + if (is_touching) + { + if (cinfo.switch_source) + { + is_touching = false; + std::cout << "CLUSTER: SWITCH SOURCES at " << turn_index << std::endl; + } + else + { + std::cout << "CLUSTER: CONTINUE at " << turn_index << std::endl; + } + } +#else + is_touching = is_union && cinfo.open_count > 1 && ! cinfo.switch_source; +#endif + if (is_touching) + { + sbs.reverse(); + } + + return select_from_cluster(turn_index, op_index, start_turn_index, sbs, + is_touching); + } + + inline void change_index_for_self_turn(signed_size_type& to_vertex_index, + turn_type const& start_turn, + turn_operation_type const& start_op, + int start_op_index) const + { + if (OverlayType != overlay_buffer) + { + return; + } + + // It travels to itself, can happen. If this is a buffer, it can + // sometimes travel to itself in the following configuration: + // + // +---->--+ + // | | + // | +---*----+ *: one turn, with segment index 2/7 + // | | | | + // | +---C | C: closing point (start/end) + // | | + // +------------+ + // + // If it starts on segment 2 and travels to itself on segment 2, that + // should be corrected to 7 because that is the shortest path + // + // Also a uu turn (touching with another buffered ring) might have this + // apparent configuration, but there it should + // always travel the whole ring + + turn_operation_type const& other_op + = start_turn.operations[1 - start_op_index]; + + bool const correct + = ! start_turn.both(operation_union) + && start_op.seg_id.segment_index == to_vertex_index; + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) + std::cout << " WARNING: self-buffer " + << " correct=" << correct + << " turn=" << operation_char(start_turn.operations[0].operation) + << operation_char(start_turn.operations[1].operation) + << " start=" << start_op.seg_id.segment_index + << " from=" << to_vertex_index + << " to=" << other_op.enriched.travels_to_vertex_index + << std::endl; +#endif + + if (correct) + { + to_vertex_index = other_op.enriched.travels_to_vertex_index; + } + } + + bool select_turn_from_enriched(signed_size_type& turn_index, + segment_identifier& previous_seg_id, + signed_size_type& to_vertex_index, + signed_size_type start_turn_index, + int start_op_index, + turn_type const& previous_turn, + turn_operation_type const& previous_op, + bool is_start) const + { + to_vertex_index = -1; + + if (previous_op.enriched.next_ip_index < 0) + { + // There is no next IP on this segment + if (previous_op.enriched.travels_to_vertex_index < 0 + || previous_op.enriched.travels_to_ip_index < 0) + { + return false; + } + + to_vertex_index = previous_op.enriched.travels_to_vertex_index; + + if (is_start && + previous_op.enriched.travels_to_ip_index == start_turn_index) + { + change_index_for_self_turn(to_vertex_index, previous_turn, + previous_op, start_op_index); + } + + turn_index = previous_op.enriched.travels_to_ip_index; + previous_seg_id = previous_op.seg_id; + } + else + { + // Take the next IP on this segment + turn_index = previous_op.enriched.next_ip_index; + previous_seg_id = previous_op.seg_id; + } + return true; + } + + bool select_turn(signed_size_type start_turn_index, + signed_size_type& turn_index, + int& op_index, + bool& is_touching, + int previous_op_index, + signed_size_type previous_turn_index, + segment_identifier const& previous_seg_id, + bool is_start) + { + if (m_turns[turn_index].cluster_id >= 0) + { + if (! select_turn_from_cluster(turn_index, op_index, is_touching, + start_turn_index, previous_seg_id)) + { + return false; + } + + if (is_start && turn_index == previous_turn_index) + { + op_index = previous_op_index; + } + } + else + { + turn_type const& current_turn = m_turns[turn_index]; + + op_index = starting_operation_index(current_turn); + if (op_index == -1) + { + if (both_finished(current_turn)) + { + return false; + } + + if (! select_operation(current_turn, turn_index, + start_turn_index, + previous_seg_id, + op_index)) + { + return false; + } + } + } + return true; + } + +private : + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Turns& m_turns; + Clusters const& m_clusters; + RobustPolicy const& m_robust_policy; + Visitor& m_visitor; +}; + + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp new file mode 100755 index 0000000000..3124e7bd7c --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_info.hpp @@ -0,0 +1,53 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP + + +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +struct traversal_turn_operation : public turn_operation +{ + enrichment_info enriched; + visit_info visited; +}; + +template +struct traversal_turn_info + : public turn_info + < + Point, + SegmentRatio, + traversal_turn_operation + > +{}; + + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp new file mode 100755 index 0000000000..15ad9a3d84 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -0,0 +1,347 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +< + bool Reverse1, + bool Reverse2, + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename Turns, + typename Clusters, + typename RobustPolicy, + typename Visitor, + typename Backtrack +> +struct traversal_ring_creator +{ + typedef traversal + traversal_type; + + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + static const operation_type target_operation + = operation_from_overlay::value; + + inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2, + Turns& turns, Clusters const& clusters, + RobustPolicy const& robust_policy, Visitor& visitor) + : m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor) + , m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_turns(turns) + , m_clusters(clusters) + , m_robust_policy(robust_policy) + , m_visitor(visitor) + , m_has_uu(false) + { + + } + + template + inline traverse_error_type travel_to_next_turn(signed_size_type start_turn_index, + int start_op_index, + signed_size_type& turn_index, + int& op_index, + Ring& current_ring, + bool is_start) + { + int const previous_op_index = op_index; + signed_size_type const previous_turn_index = turn_index; + turn_type& previous_turn = m_turns[turn_index]; + turn_operation_type& previous_op = previous_turn.operations[op_index]; + segment_identifier previous_seg_id; + + signed_size_type to_vertex_index = -1; + if (! m_trav.select_turn_from_enriched(turn_index, previous_seg_id, + to_vertex_index, start_turn_index, start_op_index, + previous_turn, previous_op, is_start)) + { + return is_start + ? traverse_error_no_next_ip_at_start + : traverse_error_no_next_ip; + } + if (to_vertex_index >= 0) + { + if (previous_op.seg_id.source_index == 0) + { + geometry::copy_segments(m_geometry1, + previous_op.seg_id, to_vertex_index, + m_robust_policy, current_ring); + } + else + { + geometry::copy_segments(m_geometry2, + previous_op.seg_id, to_vertex_index, + m_robust_policy, current_ring); + } + } + + if (m_turns[turn_index].discarded) + { + return is_start + ? traverse_error_dead_end_at_start + : traverse_error_dead_end; + } + + if (is_start) + { + // Register the start + previous_op.visited.set_started(); + m_visitor.visit_traverse(m_turns, previous_turn, previous_op, "Start"); + } + + bool is_touching = false; + if (! m_trav.select_turn(start_turn_index, turn_index, op_index, + is_touching, + previous_op_index, previous_turn_index, previous_seg_id, + is_start)) + { + return is_start + ? traverse_error_no_next_ip_at_start + : traverse_error_no_next_ip; + } + + { + // Check operation (TODO: this might be redundant or should be catched before) + const turn_type& current_turn = m_turns[turn_index]; + const turn_operation_type& op = current_turn.operations[op_index]; + if (op.visited.finalized() + || m_trav.is_visited(current_turn, op, turn_index, op_index)) + { + return traverse_error_visit_again; + } + } + + // Update registration and append point + turn_type& current_turn = m_turns[turn_index]; + turn_operation_type& op = current_turn.operations[op_index]; + detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point, + m_robust_policy); + + // Register the visit + m_trav.set_visited(current_turn, op); + m_visitor.visit_traverse(m_turns, current_turn, op, "Visit"); + + return traverse_error_none; + } + + template + inline traverse_error_type traverse(Ring& ring, + signed_size_type start_turn_index, int start_op_index) + { + turn_type const& start_turn = m_turns[start_turn_index]; + turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; + + detail::overlay::append_no_dups_or_spikes(ring, start_turn.point, + m_robust_policy); + + signed_size_type current_turn_index = start_turn_index; + int current_op_index = start_op_index; + + traverse_error_type error = travel_to_next_turn(start_turn_index, + start_op_index, + current_turn_index, current_op_index, + ring, true); + + if (error != traverse_error_none) + { + // This is not necessarily a problem, it happens for clustered turns + // which are "build in" or otherwise point inwards + return error; + } + + if (current_turn_index == start_turn_index) + { + start_op.visited.set_finished(); + m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish"); + return traverse_error_none; + } + + std::size_t const max_iterations = 2 + 2 * m_turns.size(); + for (std::size_t i = 0; i <= max_iterations; i++) + { + // We assume clockwise polygons only, non self-intersecting, closed. + // However, the input might be different, and checking validity + // is up to the library user. + + // Therefore we make here some sanity checks. If the input + // violates the assumptions, the output polygon will not be correct + // but the routine will stop and output the current polygon, and + // will continue with the next one. + + // Below three reasons to stop. + error = travel_to_next_turn(start_turn_index, start_op_index, + current_turn_index, current_op_index, + ring, false); + + if (error != traverse_error_none) + { + return error; + } + + if (current_turn_index == start_turn_index + && current_op_index == start_op_index) + { + start_op.visited.set_finished(); + m_visitor.visit_traverse(m_turns, start_turn, start_op, "Finish"); + return traverse_error_none; + } + } + + return traverse_error_endless_loop; + } + + template + void traverse_with_operation(turn_type const& start_turn, + std::size_t turn_index, int op_index, + Rings& rings, std::size_t& finalized_ring_size, + typename Backtrack::state_type& state) + { + typedef typename boost::range_value::type ring_type; + + turn_operation_type const& start_op = start_turn.operations[op_index]; + + if (! start_op.visited.none() + || ! start_op.enriched.startable + || start_op.visited.rejected() + || ! (start_op.operation == target_operation + || start_op.operation == detail::overlay::operation_continue)) + { + return; + } + + ring_type ring; + traverse_error_type traverse_error = traverse(ring, turn_index, op_index); + + if (traverse_error == traverse_error_none) + { + std::size_t const min_num_points + = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + + if (geometry::num_points(ring) >= min_num_points) + { + clean_closing_dups_and_spikes(ring, m_robust_policy); + rings.push_back(ring); + + m_trav.finalize_visit_info(); + finalized_ring_size++; + } + } + else + { + Backtrack::apply( + finalized_ring_size, + rings, ring, m_turns, start_turn, + m_turns[turn_index].operations[op_index], + traverse_error, + m_geometry1, m_geometry2, m_robust_policy, + state, m_visitor); + } + } + + template + void iterate(Rings& rings, std::size_t& finalized_ring_size, + typename Backtrack::state_type& state, + int pass) + { + if (pass == 1) + { + if (target_operation == operation_intersection) + { + // Second pass currently only used for uu + return; + } + if (! m_has_uu) + { + // There is no uu found in first pass + return; + } + } + + // Iterate through all unvisited points + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type const& start_turn = m_turns[turn_index]; + + if (start_turn.discarded || start_turn.blocked()) + { + // Skip discarded and blocked turns + continue; + } + if (target_operation == operation_union) + { + if (start_turn.both(operation_union)) + { + // Start with a uu-turn only in the second pass + m_has_uu = true; + if (pass == 0) + { + continue; + } + } + } + + for (int op_index = 0; op_index < 2; op_index++) + { + traverse_with_operation(start_turn, turn_index, op_index, + rings, finalized_ring_size, state); + } + } + } + +private: + traversal_type m_trav; + + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Turns& m_turns; + Clusters const& m_clusters; + RobustPolicy const& m_robust_policy; + Visitor& m_visitor; + + // Next member is only used for operation union + bool m_has_uu; + +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp new file mode 100755 index 0000000000..b541150da1 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp @@ -0,0 +1,291 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015-2016 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +// Generic function (is this used somewhere else too?) +inline ring_identifier ring_id_by_seg_id(segment_identifier const& seg_id) +{ + return ring_identifier(seg_id.source_index, seg_id.multi_index, seg_id.ring_index); +} + +template +< + bool Reverse1, + bool Reverse2, + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename Turns, + typename Clusters, + typename RobustPolicy, + typename Visitor +> +struct traversal_switch_detector +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + // For convenience + typedef std::set::const_iterator set_iterator; + + inline traversal_switch_detector(Geometry1 const& geometry1, Geometry2 const& geometry2, + Turns& turns, Clusters& clusters, + RobustPolicy const& robust_policy, Visitor& visitor) + : m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_turns(turns) + , m_clusters(clusters) + , m_robust_policy(robust_policy) + , m_visitor(visitor) + , m_region_id(0) + { + + } + + static inline bool connects_same_zone(turn_type const& turn) + { + if (turn.cluster_id == -1) + { + // If it is a uu-turn (non clustered), it is never same zone + return ! turn.both(operation_union); + } + + // It is a cluster, check zones of both operations + return turn.operations[0].enriched.zone + == turn.operations[1].enriched.zone; + } + + inline int get_region_id(turn_operation_type const& op) const + { + std::map::const_iterator it + = m_regions.find(ring_id_by_seg_id(op.seg_id)); + return it == m_regions.end() ? -1 : it->second; + } + + void create_region(ring_identifier const& ring_id, std::set const& ring_turn_indices, int region_id = -1) + { + std::map::const_iterator it = m_regions.find(ring_id); + if (it != m_regions.end()) + { + // The ring is already gathered in a region, quit + return; + } + if (region_id == -1) + { + region_id = m_region_id++; + } + + // Assign this ring to specified region + m_regions[ring_id] = region_id; +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << " ADD " << ring_id << " TO REGION " << region_id << std::endl; +#endif + + // Find connecting rings, recursively + for (set_iterator sit = ring_turn_indices.begin(); + sit != ring_turn_indices.end(); ++sit) + { + int const turn_index = *sit; + turn_type const& turn = m_turns[turn_index]; + if (! connects_same_zone(turn)) + { + // This is a non clustered uu-turn, or a cluster connecting different 'zones' + continue; + } + + // This turn connects two rings (interior connected), create the + // same region + for (int op_index = 0; op_index < 2; op_index++) + { + turn_operation_type const& op = turn.operations[op_index]; + ring_identifier connected_ring_id = ring_id_by_seg_id(op.seg_id); + if (connected_ring_id != ring_id) + { + propagate_region(connected_ring_id, region_id); + } + } + } + } + + void propagate_region(ring_identifier const& ring_id, int region_id) + { + std::map >::const_iterator it = m_turns_per_ring.find(ring_id); + if (it != m_turns_per_ring.end()) + { + create_region(ring_id, it->second, region_id); + } + } + + void iterate() + { +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "SWITCH BEGIN ITERATION" << std::endl; +#endif + + // Collect turns per ring + m_turns_per_ring.clear(); + m_regions.clear(); + m_region_id = 1; + + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type const& turn = m_turns[turn_index]; + + for (int op_index = 0; op_index < 2; op_index++) + { + turn_operation_type const& op = turn.operations[op_index]; + m_turns_per_ring[ring_id_by_seg_id(op.seg_id)].insert(turn_index); + } + } + + // All rings having turns are in the map. Now iterate them + for (std::map >::const_iterator it + = m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it) + { + create_region(it->first, it->second); + } + + // Now that all regions are filled, assign switch_source property + // Iterate through all clusters + for (typename Clusters::iterator it = m_clusters.begin(); it != m_clusters.end(); ++it) + { + cluster_info& cinfo = it->second; + if (cinfo.open_count <= 1) + { + // Not a touching cluster + continue; + } + + // A touching cluster, gather regions + std::set regions; + + std::set const& ids = cinfo.turn_indices; + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "SWITCH EXAMINE CLUSTER " << it->first << std::endl; +#endif + + for (set_iterator sit = ids.begin(); sit != ids.end(); ++sit) + { + signed_size_type turn_index = *sit; + turn_type const& turn = m_turns[turn_index]; + for (int oi = 0; oi < 2; oi++) + { + int const region = get_region_id(turn.operations[oi]); + regions.insert(region); + } + } + // Switch source if this cluster connects the same region + cinfo.switch_source = regions.size() == 1; + } + + // Iterate through all uu turns (non-clustered) + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type& turn = m_turns[turn_index]; + + if (turn.discarded + || turn.blocked() + || turn.cluster_id >= 0 + || ! turn.both(operation_union)) + { + // Skip discarded, blocked, non-uu and clustered turns + continue; + } + + if (OverlayType == overlay_buffer) + { + // For deflate, the region approach does not work because many + // pieces are outside the real polygons + // TODO: implement this in another way for buffer + // (because now buffer might output invalid geometries) + continue; + } + + int const region0 = get_region_id(turn.operations[0]); + int const region1 = get_region_id(turn.operations[1]); + + // Switch sources for same region + turn.switch_source = region0 == region1; + } + + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "SWITCH END ITERATION" << std::endl; + + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type const& turn = m_turns[turn_index]; + + if (turn.both(operation_union) && turn.cluster_id < 0) + { + std::cout << "UU SWITCH RESULT " + << turn_index << " -> " + << turn.switch_source << std::endl; + } + } + + for (typename Clusters::const_iterator it = m_clusters.begin(); it != m_clusters.end(); ++it) + { + cluster_info const& cinfo = it->second; + if (cinfo.open_count > 1) + { + std::cout << "CL SWITCH RESULT " << it->first + << " -> " << cinfo.switch_source << std::endl; + } + else + { + std::cout << "CL SWITCH RESULT " << it->first + << " is not registered as open" << std::endl; + } + } +#endif + + } + +private: + + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Turns& m_turns; + Clusters& m_clusters; + RobustPolicy const& m_robust_policy; + Visitor& m_visitor; + + std::map m_regions; + std::map > m_turns_per_ring; + int m_region_id; + +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traverse.hpp new file mode 100755 index 0000000000..b7ba60e998 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -0,0 +1,112 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +/*! + \brief Traverses through intersection points / geometries + \ingroup overlay + */ +template +< + bool Reverse1, bool Reverse2, + typename Geometry1, + typename Geometry2, + overlay_type OverlayType, + typename Backtrack = backtrack_check_self_intersections +> +class traverse +{ + + template + static void reset_visits(Turns& turns) + { + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + for (int i = 0; i < 2; i++) + { + it->operations[i].visited.reset(); + } + } + } + + +public : + template + < + typename RobustPolicy, + typename Turns, + typename Rings, + typename Visitor, + typename Clusters + > + static inline void apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + RobustPolicy const& robust_policy, + Turns& turns, Rings& rings, + Clusters& clusters, + Visitor& visitor) + { + traversal_switch_detector + < + Reverse1, Reverse2, OverlayType, + Geometry1, Geometry2, + Turns, Clusters, + RobustPolicy, Visitor + > switch_detector(geometry1, geometry2, turns, clusters, + robust_policy, visitor); + + switch_detector.iterate(); + reset_visits(turns); + + traversal_ring_creator + < + Reverse1, Reverse2, OverlayType, + Geometry1, Geometry2, + Turns, Clusters, + RobustPolicy, Visitor, + Backtrack + > trav(geometry1, geometry2, turns, clusters, + robust_policy, visitor); + + std::size_t finalized_ring_size = boost::size(rings); + + typename Backtrack::state_type state; + + for (int pass = 0; pass < 2; pass++) + { + trav.iterate(rings, finalized_ring_size, state, pass); + } + } +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp new file mode 100755 index 0000000000..3ee1945de1 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp @@ -0,0 +1,154 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP + + +#include + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +enum method_type +{ + method_none, + method_disjoint, + method_crosses, + method_touch, + method_touch_interior, + method_collinear, + method_equal, + method_error +}; + + +/*! + \brief Turn operation: operation + \details Information necessary for traversal phase (a phase + of the overlay process). The information is gathered during the + get_turns (segment intersection) phase. + The class is to be included in the turn_info class, either direct + or a derived or similar class with more (e.g. enrichment) information. + */ +template +struct turn_operation +{ + typedef SegmentRatio segment_ratio_type; + + operation_type operation; + segment_identifier seg_id; + SegmentRatio fraction; + + typedef typename coordinate_type::type comparable_distance_type; + comparable_distance_type remaining_distance; + + inline turn_operation() + : operation(operation_none) + , remaining_distance(0) + {} +}; + + +/*! + \brief Turn information: intersection point, method, and turn information + \details Information necessary for traversal phase (a phase + of the overlay process). The information is gathered during the + get_turns (segment intersection) phase. + \tparam Point point type of intersection point + \tparam Operation gives classes opportunity to add additional info + \tparam Container gives classes opportunity to define how operations are stored + */ +template +< + typename Point, + typename SegmentRatio, + typename Operation = turn_operation, + typename Container = boost::array +> +struct turn_info +{ + typedef Point point_type; + typedef SegmentRatio segment_ratio_type; + typedef Operation turn_operation_type; + typedef Container container_type; + + Point point; + method_type method; + int cluster_id; + bool discarded; + bool colocated; + bool switch_source; // For u/u turns which can either switch or not + + Container operations; + + inline turn_info() + : method(method_none) + , cluster_id(-1) + , discarded(false) + , colocated(false) + , switch_source(false) + {} + + inline bool both(operation_type type) const + { + return has12(type, type); + } + + inline bool has(operation_type type) const + { + return this->operations[0].operation == type + || this->operations[1].operation == type; + } + + inline bool combination(operation_type type1, operation_type type2) const + { + return has12(type1, type2) || has12(type2, type1); + } + + inline bool blocked() const + { + return both(operation_blocked); + } + inline bool opposite() const + { + return both(operation_opposite); + } + inline bool any_blocked() const + { + return has(operation_blocked); + } + + +private : + inline bool has12(operation_type type1, operation_type type2) const + { + return this->operations[0].operation == type1 + && this->operations[1].operation == type2 + ; + } + +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp new file mode 100755 index 0000000000..e462705e19 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp @@ -0,0 +1,98 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +class visit_info +{ +private : + static const int NONE = 0; + static const int STARTED = 1; + static const int VISITED = 2; + static const int FINISHED = 3; + static const int REJECTED = 4; + + int m_visit_code; + bool m_rejected; + bool m_final; + +public: + inline visit_info() + : m_visit_code(0) + , m_rejected(false) + , m_final(false) + {} + + inline void set_visited() { m_visit_code = VISITED; } + inline void set_started() { m_visit_code = STARTED; } + inline void set_finished() { m_visit_code = FINISHED; } + inline void set_rejected() + { + m_visit_code = REJECTED; + m_rejected = true; + } + + inline bool none() const { return m_visit_code == NONE; } + inline bool visited() const { return m_visit_code == VISITED; } + inline bool started() const { return m_visit_code == STARTED; } + inline bool finished() const { return m_visit_code == FINISHED; } + inline bool rejected() const { return m_rejected; } + inline bool finalized() const { return m_final; } + + inline void clear() + { + if (! m_rejected && ! m_final) + { + m_visit_code = NONE; + } + } + + inline void reset() + { + *this = visit_info(); + } + + inline void finalize() + { + if (visited() || started() || finished() ) + { + m_final = true; + } + } + +#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION + friend std::ostream& operator<<(std::ostream &os, visit_info const& v) + { + if (v.m_visit_code != 0) + { + os << " VIS: " << int(v.m_visit_code); + } + return os; + } +#endif + +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/partition.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/partition.hpp new file mode 100755 index 0000000000..991f0e2c20 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/partition.hpp @@ -0,0 +1,637 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP + +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry +{ + +namespace detail { namespace partition +{ + +template +inline void divide_box(Box const& box, Box& lower_box, Box& upper_box) +{ + typedef typename coordinate_type::type ctype; + + // Divide input box into two parts, e.g. left/right + ctype two = 2; + ctype mid = (geometry::get(box) + + geometry::get(box)) / two; + + lower_box = box; + upper_box = box; + geometry::set(lower_box, mid); + geometry::set(upper_box, mid); +} + +// Divide forward_range into three subsets: lower, upper and oversized +// (not-fitting) +// (lower == left or bottom, upper == right or top) +template +inline void divide_into_subsets(Box const& lower_box, + Box const& upper_box, + IteratorVector const& input, + IteratorVector& lower, + IteratorVector& upper, + IteratorVector& exceeding) +{ + typedef typename boost::range_iterator + < + IteratorVector const + >::type it_type; + + for(it_type it = boost::begin(input); it != boost::end(input); ++it) + { + bool const lower_overlapping = OverlapsPolicy::apply(lower_box, **it); + bool const upper_overlapping = OverlapsPolicy::apply(upper_box, **it); + + if (lower_overlapping && upper_overlapping) + { + exceeding.push_back(*it); + } + else if (lower_overlapping) + { + lower.push_back(*it); + } + else if (upper_overlapping) + { + upper.push_back(*it); + } + else + { + // Is nowhere. That is (since 1.58) possible, it might be + // skipped by the OverlapsPolicy to enhance performance + } + } +} + +template +< + typename ExpandPolicy, + typename Box, + typename IteratorVector +> +inline void expand_with_elements(Box& total, IteratorVector const& input) +{ + typedef typename boost::range_iterator::type it_type; + for(it_type it = boost::begin(input); it != boost::end(input); ++it) + { + ExpandPolicy::apply(total, **it); + } +} + + +// Match forward_range with itself +template +inline void handle_one(IteratorVector const& input, Policy& policy) +{ + if (boost::size(input) == 0) + { + return; + } + + typedef typename boost::range_iterator::type it_type; + + // Quadratic behaviour at lowest level (lowest quad, or all exceeding) + for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1) + { + it_type it2 = it1; + for (++it2; it2 != boost::end(input); ++it2) + { + policy.apply(**it1, **it2); + } + } +} + +// Match forward range 1 with forward range 2 +template +< + typename Policy, + typename IteratorVector1, + typename IteratorVector2 +> +inline void handle_two(IteratorVector1 const& input1, + IteratorVector2 const& input2, + Policy& policy) +{ + typedef typename boost::range_iterator + < + IteratorVector1 const + >::type iterator_type1; + + typedef typename boost::range_iterator + < + IteratorVector2 const + >::type iterator_type2; + + if (boost::size(input1) == 0 || boost::size(input2) == 0) + { + return; + } + + for(iterator_type1 it1 = boost::begin(input1); + it1 != boost::end(input1); + ++it1) + { + for(iterator_type2 it2 = boost::begin(input2); + it2 != boost::end(input2); + ++it2) + { + policy.apply(**it1, **it2); + } + } +} + +template +inline bool recurse_ok(IteratorVector const& input, + std::size_t min_elements, std::size_t level) +{ + return boost::size(input) >= min_elements + && level < 100; +} + +template +inline bool recurse_ok(IteratorVector1 const& input1, + IteratorVector2 const& input2, + std::size_t min_elements, std::size_t level) +{ + return boost::size(input1) >= min_elements + && recurse_ok(input2, min_elements, level); +} + +template +< + typename IteratorVector1, + typename IteratorVector2, + typename IteratorVector3 +> +inline bool recurse_ok(IteratorVector1 const& input1, + IteratorVector2 const& input2, + IteratorVector3 const& input3, + std::size_t min_elements, std::size_t level) +{ + return boost::size(input1) >= min_elements + && recurse_ok(input2, input3, min_elements, level); +} + +template +< + int Dimension, + typename Box, + typename OverlapsPolicy1, + typename OverlapsPolicy2, + typename ExpandPolicy1, + typename ExpandPolicy2, + typename VisitBoxPolicy +> +class partition_two_ranges; + + +template +< + int Dimension, + typename Box, + typename OverlapsPolicy, + typename ExpandPolicy, + typename VisitBoxPolicy +> +class partition_one_range +{ + template + static inline Box get_new_box(IteratorVector const& input) + { + Box box; + geometry::assign_inverse(box); + expand_with_elements(box, input); + return box; + } + + template + static inline void next_level(Box const& box, + IteratorVector const& input, + std::size_t level, std::size_t min_elements, + Policy& policy, VisitBoxPolicy& box_policy) + { + if (recurse_ok(input, min_elements, level)) + { + partition_one_range + < + 1 - Dimension, + Box, + OverlapsPolicy, + ExpandPolicy, + VisitBoxPolicy + >::apply(box, input, level + 1, min_elements, policy, box_policy); + } + else + { + handle_one(input, policy); + } + } + + // Function to switch to two forward ranges if there are + // geometries exceeding the separation line + template + static inline void next_level2(Box const& box, + IteratorVector const& input1, + IteratorVector const& input2, + std::size_t level, std::size_t min_elements, + Policy& policy, VisitBoxPolicy& box_policy) + { + if (recurse_ok(input1, input2, min_elements, level)) + { + partition_two_ranges + < + 1 - Dimension, + Box, + OverlapsPolicy, OverlapsPolicy, + ExpandPolicy, ExpandPolicy, + VisitBoxPolicy + >::apply(box, input1, input2, level + 1, min_elements, + policy, box_policy); + } + else + { + handle_two(input1, input2, policy); + } + } + +public : + template + static inline void apply(Box const& box, + IteratorVector const& input, + std::size_t level, + std::size_t min_elements, + Policy& policy, VisitBoxPolicy& box_policy) + { + box_policy.apply(box, level); + + Box lower_box, upper_box; + divide_box(box, lower_box, upper_box); + + IteratorVector lower, upper, exceeding; + divide_into_subsets(lower_box, upper_box, + input, lower, upper, exceeding); + + if (boost::size(exceeding) > 0) + { + // Get the box of exceeding-only + Box exceeding_box = get_new_box(exceeding); + + // Recursively do exceeding elements only, in next dimension they + // will probably be less exceeding within the new box + next_level(exceeding_box, exceeding, level, min_elements, + policy, box_policy); + + // Switch to two forward ranges, combine exceeding with + // lower resp upper, but not lower/lower, upper/upper + next_level2(exceeding_box, exceeding, lower, level, min_elements, + policy, box_policy); + next_level2(exceeding_box, exceeding, upper, level, min_elements, + policy, box_policy); + } + + // Recursively call operation both parts + next_level(lower_box, lower, level, min_elements, policy, box_policy); + next_level(upper_box, upper, level, min_elements, policy, box_policy); + } +}; + +template +< + int Dimension, + typename Box, + typename OverlapsPolicy1, + typename OverlapsPolicy2, + typename ExpandPolicy1, + typename ExpandPolicy2, + typename VisitBoxPolicy +> +class partition_two_ranges +{ + template + < + typename Policy, + typename IteratorVector1, + typename IteratorVector2 + > + static inline void next_level(Box const& box, + IteratorVector1 const& input1, + IteratorVector2 const& input2, + std::size_t level, std::size_t min_elements, + Policy& policy, VisitBoxPolicy& box_policy) + { + partition_two_ranges + < + 1 - Dimension, + Box, + OverlapsPolicy1, + OverlapsPolicy2, + ExpandPolicy1, + ExpandPolicy2, + VisitBoxPolicy + >::apply(box, input1, input2, level + 1, min_elements, + policy, box_policy); + } + + template + static inline Box get_new_box(IteratorVector const& input) + { + Box box; + geometry::assign_inverse(box); + expand_with_elements(box, input); + return box; + } + + template + static inline Box get_new_box(IteratorVector1 const& input1, + IteratorVector2 const& input2) + { + Box box = get_new_box(input1); + expand_with_elements(box, input2); + return box; + } + +public : + template + < + typename Policy, + typename IteratorVector1, + typename IteratorVector2 + > + static inline void apply(Box const& box, + IteratorVector1 const& input1, + IteratorVector2 const& input2, + std::size_t level, + std::size_t min_elements, + Policy& policy, VisitBoxPolicy& box_policy) + { + box_policy.apply(box, level); + + Box lower_box, upper_box; + divide_box(box, lower_box, upper_box); + + IteratorVector1 lower1, upper1, exceeding1; + IteratorVector2 lower2, upper2, exceeding2; + divide_into_subsets(lower_box, upper_box, + input1, lower1, upper1, exceeding1); + divide_into_subsets(lower_box, upper_box, + input2, lower2, upper2, exceeding2); + + if (boost::size(exceeding1) > 0) + { + // All exceeding from 1 with 2: + + if (recurse_ok(exceeding1, exceeding2, min_elements, level)) + { + Box exceeding_box = get_new_box(exceeding1, exceeding2); + next_level(exceeding_box, exceeding1, exceeding2, level, + min_elements, policy, box_policy); + } + else + { + handle_two(exceeding1, exceeding2, policy); + } + + // All exceeding from 1 with lower and upper of 2: + + // (Check sizes of all three forward ranges to avoid recurse into + // the same combinations again and again) + if (recurse_ok(lower2, upper2, exceeding1, min_elements, level)) + { + Box exceeding_box = get_new_box(exceeding1); + next_level(exceeding_box, exceeding1, lower2, level, + min_elements, policy, box_policy); + next_level(exceeding_box, exceeding1, upper2, level, + min_elements, policy, box_policy); + } + else + { + handle_two(exceeding1, lower2, policy); + handle_two(exceeding1, upper2, policy); + } + } + + if (boost::size(exceeding2) > 0) + { + // All exceeding from 2 with lower and upper of 1: + if (recurse_ok(lower1, upper1, exceeding2, min_elements, level)) + { + Box exceeding_box = get_new_box(exceeding2); + next_level(exceeding_box, lower1, exceeding2, level, + min_elements, policy, box_policy); + next_level(exceeding_box, upper1, exceeding2, level, + min_elements, policy, box_policy); + } + else + { + handle_two(lower1, exceeding2, policy); + handle_two(upper1, exceeding2, policy); + } + } + + if (recurse_ok(lower1, lower2, min_elements, level)) + { + next_level(lower_box, lower1, lower2, level, + min_elements, policy, box_policy); + } + else + { + handle_two(lower1, lower2, policy); + } + if (recurse_ok(upper1, upper2, min_elements, level)) + { + next_level(upper_box, upper1, upper2, level, + min_elements, policy, box_policy); + } + else + { + handle_two(upper1, upper2, policy); + } + } +}; + +struct visit_no_policy +{ + template + static inline void apply(Box const&, std::size_t ) + {} +}; + +struct include_all_policy +{ + template + static inline bool apply(Item const&) + { + return true; + } +}; + + +}} // namespace detail::partition + +template +< + typename Box, + typename ExpandPolicy1, + typename OverlapsPolicy1, + typename ExpandPolicy2 = ExpandPolicy1, + typename OverlapsPolicy2 = OverlapsPolicy1, + typename IncludePolicy1 = detail::partition::include_all_policy, + typename IncludePolicy2 = detail::partition::include_all_policy, + typename VisitBoxPolicy = detail::partition::visit_no_policy +> +class partition +{ + template + < + typename ExpandPolicy, + typename IncludePolicy, + typename ForwardRange, + typename IteratorVector + > + static inline void expand_to_range(ForwardRange const& forward_range, + Box& total, IteratorVector& iterator_vector) + { + for(typename boost::range_iterator::type it + = boost::begin(forward_range); + it != boost::end(forward_range); + ++it) + { + if (IncludePolicy::apply(*it)) + { + ExpandPolicy::apply(total, *it); + iterator_vector.push_back(it); + } + } + } + +public : + template + static inline void apply(ForwardRange const& forward_range, + VisitPolicy& visitor, + std::size_t min_elements = 16, + VisitBoxPolicy box_visitor = detail::partition::visit_no_policy() + ) + { + typedef typename boost::range_iterator + < + ForwardRange const + >::type iterator_type; + + if (std::size_t(boost::size(forward_range)) > min_elements) + { + std::vector iterator_vector; + Box total; + assign_inverse(total); + expand_to_range(forward_range, + total, iterator_vector); + + detail::partition::partition_one_range + < + 0, Box, + OverlapsPolicy1, + ExpandPolicy1, + VisitBoxPolicy + >::apply(total, iterator_vector, 0, min_elements, + visitor, box_visitor); + } + else + { + for(iterator_type it1 = boost::begin(forward_range); + it1 != boost::end(forward_range); + ++it1) + { + iterator_type it2 = it1; + for(++it2; it2 != boost::end(forward_range); ++it2) + { + visitor.apply(*it1, *it2); + } + } + } + } + + template + < + typename ForwardRange1, + typename ForwardRange2, + typename VisitPolicy + > + static inline void apply(ForwardRange1 const& forward_range1, + ForwardRange2 const& forward_range2, + VisitPolicy& visitor, + std::size_t min_elements = 16, + VisitBoxPolicy box_visitor + = detail::partition::visit_no_policy() + ) + { + typedef typename boost::range_iterator + < + ForwardRange1 const + >::type iterator_type1; + + typedef typename boost::range_iterator + < + ForwardRange2 const + >::type iterator_type2; + + if (std::size_t(boost::size(forward_range1)) > min_elements + && std::size_t(boost::size(forward_range2)) > min_elements) + { + std::vector iterator_vector1; + std::vector iterator_vector2; + Box total; + assign_inverse(total); + expand_to_range(forward_range1, + total, iterator_vector1); + expand_to_range(forward_range2, + total, iterator_vector2); + + detail::partition::partition_two_ranges + < + 0, Box, OverlapsPolicy1, OverlapsPolicy2, + ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy + >::apply(total, iterator_vector1, iterator_vector2, + 0, min_elements, visitor, box_visitor); + } + else + { + for(iterator_type1 it1 = boost::begin(forward_range1); + it1 != boost::end(forward_range1); + ++it1) + { + for(iterator_type2 it2 = boost::begin(forward_range2); + it2 != boost::end(forward_range2); + ++it2) + { + visitor.apply(*it1, *it2); + } + } + } + } +}; + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp new file mode 100755 index 0000000000..1e6fa01869 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp @@ -0,0 +1,125 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2015. +// Modifications copyright (c) 2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +// Checks if a point ("last_point") causes a spike w.r.t. +// the specified two other points (segment_a, segment_b) +// +// x-------x------x +// a lp b +// +// Above, lp generates a spike w.r.t. segment(a,b) +// So specify last point first, then (a,b) +// The segment's orientation does matter: if lp is to the right of b +// no spike is reported +template +static inline bool point_is_spike_or_equal(Point1 const& last_point, + Point2 const& segment_a, + Point3 const& segment_b) +{ + typedef typename strategy::side::services::default_strategy + < + typename cs_tag::type + >::type side_strategy; + + int const side = side_strategy::apply(last_point, segment_a, segment_b); + if (side == 0) + { + // Last point is collinear w.r.t previous segment. + // Check if it is equal + int const sgn_x1 = sign_of_difference<0>(last_point, segment_b); + int const sgn_y1 = sign_of_difference<1>(last_point, segment_b); + if (sgn_x1 == 0 && sgn_y1 == 0) + { + return true; + } + + // Check if it moves forward + int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a); + int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a); + + return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2; + } + return false; +} + +template +< + typename Point1, + typename Point2, + typename Point3, + typename RobustPolicy +> +static inline bool point_is_spike_or_equal(Point1 const& last_point, + Point2 const& segment_a, + Point3 const& segment_b, + RobustPolicy const& robust_policy) +{ + if (point_is_spike_or_equal(last_point, segment_a, segment_b)) + { + return true; + } + + if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled)) + { + return false; + } + + // Try using specified robust policy + typedef typename geometry::robust_point_type + < + Point1, + RobustPolicy + >::type robust_point_type; + + robust_point_type last_point_rob, segment_a_rob, segment_b_rob; + geometry::recalculate(last_point_rob, last_point, robust_policy); + geometry::recalculate(segment_a_rob, segment_a, robust_policy); + geometry::recalculate(segment_b_rob, segment_b, robust_policy); + + return point_is_spike_or_equal + ( + last_point_rob, + segment_a_rob, + segment_b_rob + ); +} + + +} // namespace detail +#endif + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_IS_EQUAL_OR_SPIKE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/point_on_border.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/point_on_border.hpp new file mode 100755 index 0000000000..e3d6af5612 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/point_on_border.hpp @@ -0,0 +1,304 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP + + +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace point_on_border +{ + + +template +struct get_point +{ + static inline bool apply(Point& destination, Point const& source, bool) + { + destination = source; + return true; + } +}; + +template +struct midpoint_helper +{ + template + static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2) + { + typename coordinate_type::type const two = 2; + set(p, + (get(p1) + get(p2)) / two); + return midpoint_helper::apply(p, p1, p2); + } +}; + + +template +struct midpoint_helper +{ + template + static inline bool apply(Point& , InputPoint const& , InputPoint const& ) + { + return true; + } +}; + + +template +struct point_on_range +{ + static inline bool apply(Point& point, Range const& range, bool midpoint) + { + const std::size_t n = boost::size(range); + if (midpoint && n > 1) + { + typedef typename boost::range_iterator + < + Range const + >::type iterator; + + iterator it = boost::begin(range); + iterator prev = it++; + while (it != boost::end(range) + && detail::equals::equals_point_point(*it, *prev)) + { + prev = it++; + } + if (it != boost::end(range)) + { + return midpoint_helper + < + Point, + 0, dimension::value + >::apply(point, *prev, *it); + } + } + + if (n > 0) + { + geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point); + return true; + } + return false; + } +}; + + +template +struct point_on_polygon +{ + static inline bool apply(Point& point, Polygon const& polygon, bool midpoint) + { + return point_on_range + < + Point, + typename ring_type::type + >::apply(point, exterior_ring(polygon), midpoint); + } +}; + + +template +struct point_on_box +{ + static inline bool apply(Point& point, Box const& box, bool midpoint) + { + if (midpoint) + { + Point p1, p2; + detail::assign::assign_box_2d_corner(box, p1); + detail::assign::assign_box_2d_corner(box, p2); + midpoint_helper + < + Point, + 0, dimension::value + >::apply(point, p1, p2); + } + else + { + detail::assign::assign_box_2d_corner(box, point); + } + + return true; + } +}; + + +template +< + typename Point, + typename MultiGeometry, + typename Policy +> +struct point_on_multi +{ + static inline bool apply(Point& point, MultiGeometry const& multi, bool midpoint) + { + // Take a point on the first multi-geometry + // (i.e. the first that is not empty) + for (typename boost::range_iterator + < + MultiGeometry const + >::type it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + if (Policy::apply(point, *it, midpoint)) + { + return true; + } + } + return false; + } +}; + + +}} // namespace detail::point_on_border +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +< + typename GeometryTag, + typename Point, + typename Geometry + +> +struct point_on_border +{}; + + +template +struct point_on_border + : detail::point_on_border::get_point +{}; + + +template +struct point_on_border + : detail::point_on_border::point_on_range +{}; + + +template +struct point_on_border + : detail::point_on_border::point_on_range +{}; + + +template +struct point_on_border + : detail::point_on_border::point_on_polygon +{}; + + +template +struct point_on_border + : detail::point_on_border::point_on_box +{}; + + +template +struct point_on_border + : detail::point_on_border::point_on_multi + < + Point, + Multi, + detail::point_on_border::point_on_polygon + < + Point, + typename boost::range_value::type + > + > +{}; + + +template +struct point_on_border + : detail::point_on_border::point_on_multi + < + Point, + Multi, + detail::point_on_border::point_on_range + < + Point, + typename boost::range_value::type + > + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! +\brief Take point on a border +\ingroup overlay +\tparam Geometry geometry type. This also defines the type of the output point +\param point to assign +\param geometry geometry to take point from +\param midpoint boolean flag, true if the point should not be a vertex, but some point + in between of two vertices +\return TRUE if successful, else false. + It is only false if polygon/line have no points +\note for a polygon, it is always a point on the exterior ring +\note for take_midpoint, it is not taken from two consecutive duplicate vertices, + (unless there are no other). + */ +template +inline bool point_on_border(Point& point, + Geometry const& geometry, + bool midpoint = false) +{ + concepts::check(); + concepts::check(); + + return dispatch::point_on_border + < + typename tag::type, + Point, + Geometry + >::apply(point, geometry, midpoint); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/recalculate.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/recalculate.hpp new file mode 100755 index 0000000000..4feae419e7 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/recalculate.hpp @@ -0,0 +1,234 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013 Bruno Lalande, Paris, France. +// Copyright (c) 2013 Mateusz Loskot, London, UK. +// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace recalculate +{ + +template +struct recalculate_point +{ + template + static inline void apply(Point1& point1, Point2 const& point2, Strategy const& strategy) + { + std::size_t const dim = Dimension - 1; + geometry::set(point1, strategy.template apply(geometry::get(point2))); + recalculate_point::apply(point1, point2, strategy); + } +}; + +template <> +struct recalculate_point<0> +{ + template + static inline void apply(Point1&, Point2 const&, Strategy const&) + { + } +}; + + +template +struct recalculate_indexed +{ + template + static inline void apply(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy) + { + // Do it for both indices in one dimension + static std::size_t const dim = Dimension - 1; + geometry::set<0, dim>(geometry1, strategy.template apply(geometry::get<0, dim>(geometry2))); + geometry::set<1, dim>(geometry1, strategy.template apply(geometry::get<1, dim>(geometry2))); + recalculate_indexed::apply(geometry1, geometry2, strategy); + } +}; + +template <> +struct recalculate_indexed<0> +{ + + template + static inline void apply(Geometry1& , Geometry2 const& , Strategy const& ) + { + } +}; + +struct range_to_range +{ + template + < + typename Range1, + typename Range2, + typename Strategy + > + static inline void apply(Range1& destination, Range2 const& source, + Strategy const& strategy) + { + typedef typename geometry::point_type::type point_type; + typedef recalculate_point::value> per_point; + geometry::clear(destination); + + for (typename boost::range_iterator::type it + = boost::begin(source); + it != boost::end(source); + ++it) + { + point_type p; + per_point::apply(p, *it, strategy); + geometry::append(destination, p); + } + } +}; + +struct polygon_to_polygon +{ +private: + template + < + typename IteratorIn, + typename IteratorOut, + typename Strategy + > + static inline void iterate(IteratorIn begin, IteratorIn end, + IteratorOut it_out, + Strategy const& strategy) + { + for (IteratorIn it_in = begin; it_in != end; ++it_in, ++it_out) + { + range_to_range::apply(*it_out, *it_in, strategy); + } + } + + template + < + typename InteriorRingsOut, + typename InteriorRingsIn, + typename Strategy + > + static inline void apply_interior_rings( + InteriorRingsOut& interior_rings_out, + InteriorRingsIn const& interior_rings_in, + Strategy const& strategy) + { + traits::resize::apply(interior_rings_out, + boost::size(interior_rings_in)); + + iterate( + boost::begin(interior_rings_in), boost::end(interior_rings_in), + boost::begin(interior_rings_out), + strategy); + } + +public: + template + < + typename Polygon1, + typename Polygon2, + typename Strategy + > + static inline void apply(Polygon1& destination, Polygon2 const& source, + Strategy const& strategy) + { + range_to_range::apply(geometry::exterior_ring(destination), + geometry::exterior_ring(source), strategy); + + apply_interior_rings(geometry::interior_rings(destination), + geometry::interior_rings(source), strategy); + } +}; + +}} // namespace detail::recalculate +#endif // DOXYGEN_NO_DETAIL + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template +< + typename Geometry1, + typename Geometry2, + typename Tag1 = typename geometry::tag::type, + typename Tag2 = typename geometry::tag::type +> +struct recalculate : not_implemented +{}; + +template +struct recalculate + : detail::recalculate::recalculate_point::value> +{}; + +template +struct recalculate + : detail::recalculate::recalculate_indexed::value> +{}; + +template +struct recalculate + : detail::recalculate::recalculate_indexed::value> +{}; + +template +struct recalculate + : detail::recalculate::polygon_to_polygon +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +template +inline void recalculate(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy) +{ + concepts::check(); + concepts::check(); + + // static assert dimensions (/types) are the same + + dispatch::recalculate::apply(geometry1, geometry2, strategy); +} + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RECALCULATE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp new file mode 100755 index 0000000000..9e466fe487 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -0,0 +1,827 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +// WARNING! +// TODO: In the worst case calling this Pred in a loop for MultiPolygon/MultiPolygon may take O(NM) +// Use the rtree in this case! + +// may be used to set EI and EB for an Areal geometry for which no turns were generated +template +class no_turns_aa_pred +{ +public: + no_turns_aa_pred(OtherAreal const& other_areal, Result & res) + : m_result(res) + , m_other_areal(other_areal) + , m_flags(0) + { + // check which relations must be analysed + + if ( ! may_update(m_result) + && ! may_update(m_result) + && ! may_update(m_result) ) + { + m_flags |= 1; + } + + if ( ! may_update(m_result) + && ! may_update(m_result) ) + { + m_flags |= 2; + } + } + + template + bool operator()(Areal const& areal) + { + // if those flags are set nothing will change + if ( m_flags == 3 ) + { + return false; + } + + typedef typename geometry::point_type::type point_type; + point_type pt; + bool const ok = boost::geometry::point_on_border(pt, areal); + + // TODO: for now ignore, later throw an exception? + if ( !ok ) + { + return true; + } + + // check if the areal is inside the other_areal + // TODO: This is O(N) + // Run in a loop O(NM) - optimize! + int const pig = detail::within::point_in_geometry(pt, m_other_areal); + //BOOST_GEOMETRY_ASSERT( pig != 0 ); + + // inside + if ( pig > 0 ) + { + update(m_result); + update(m_result); + update(m_result); + m_flags |= 1; + + // TODO: OPTIMIZE! + // Only the interior rings of other ONE single geometry must be checked + // NOT all geometries + + // Check if any interior ring is outside + ring_identifier ring_id(0, -1, 0); + std::size_t const irings_count = geometry::num_interior_rings(areal); + for ( ; static_cast(ring_id.ring_index) < irings_count ; + ++ring_id.ring_index ) + { + typename detail::sub_range_return_type::type + range_ref = detail::sub_range(areal, ring_id); + + if ( boost::empty(range_ref) ) + { + // TODO: throw exception? + continue; // ignore + } + + // TODO: O(N) + // Optimize! + int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal); + + // hole outside + if ( hpig < 0 ) + { + update(m_result); + update(m_result); + m_flags |= 2; + break; + } + } + } + // outside + else + { + update(m_result); + update(m_result); + m_flags |= 2; + + // Check if any interior ring is inside + ring_identifier ring_id(0, -1, 0); + std::size_t const irings_count = geometry::num_interior_rings(areal); + for ( ; static_cast(ring_id.ring_index) < irings_count ; + ++ring_id.ring_index ) + { + typename detail::sub_range_return_type::type + range_ref = detail::sub_range(areal, ring_id); + + if ( boost::empty(range_ref) ) + { + // TODO: throw exception? + continue; // ignore + } + + // TODO: O(N) + // Optimize! + int const hpig = detail::within::point_in_geometry(range::front(range_ref), m_other_areal); + + // hole inside + if ( hpig > 0 ) + { + update(m_result); + update(m_result); + update(m_result); + m_flags |= 1; + break; + } + } + } + + return m_flags != 3 && !m_result.interrupt; + } + +private: + Result & m_result; + OtherAreal const& m_other_areal; + int m_flags; +}; + +// The implementation of an algorithm calculating relate() for A/A +template +struct areal_areal +{ + // check Linear / Areal + BOOST_STATIC_ASSERT(topological_dimension::value == 2 + && topological_dimension::value == 2); + + static const bool interruption_enabled = true; + + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; + + template + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + { +// TODO: If Areal geometry may have infinite size, change the following line: + + // The result should be FFFFFFFFF + relate::set::value>(result);// FFFFFFFFd, d in [1,9] or T + + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + + // get and analyse turns + typedef typename turns::get_turns::turn_info turn_type; + std::vector turns; + + interrupt_policy_areal_areal interrupt_policy(geometry1, geometry2, result); + + turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy); + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + + no_turns_aa_pred pred1(geometry2, result); + for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + + no_turns_aa_pred pred2(geometry1, result); + for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + + if ( turns.empty() ) + return; + + if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) ) + { + // sort turns + typedef turns::less<0, turns::less_op_areal_areal<0> > less; + std::sort(turns.begin(), turns.end(), less()); + + /*if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) )*/ + { + // analyse sorted turns + turns_analyser analyser; + analyse_each_turn(result, analyser, turns.begin(), turns.end()); + + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + } + + if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) ) + { + // analyse rings for which turns were not generated + // or only i/i or u/u was generated + uncertain_rings_analyser<0, Result, Geometry1, Geometry2> rings_analyser(result, geometry1, geometry2); + analyse_uncertain_rings<0>::apply(rings_analyser, turns.begin(), turns.end()); + + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + } + } + + if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) ) + { + // sort turns + typedef turns::less<1, turns::less_op_areal_areal<1> > less; + std::sort(turns.begin(), turns.end(), less()); + + /*if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) )*/ + { + // analyse sorted turns + turns_analyser analyser; + analyse_each_turn(result, analyser, turns.begin(), turns.end()); + + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + } + + if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) ) + { + // analyse rings for which turns were not generated + // or only i/i or u/u was generated + uncertain_rings_analyser<1, Result, Geometry2, Geometry1> rings_analyser(result, geometry2, geometry1); + analyse_uncertain_rings<1>::apply(rings_analyser, turns.begin(), turns.end()); + + //if ( result.interrupt ) + // return; + } + } + } + + // interrupt policy which may be passed to get_turns to interrupt the analysis + // based on the info in the passed result/mask + template + class interrupt_policy_areal_areal + { + public: + static bool const enabled = true; + + interrupt_policy_areal_areal(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Result & result) + : m_result(result) + , m_geometry1(geometry1) + , m_geometry2(geometry2) + {} + + template + inline bool apply(Range const& turns) + { + typedef typename boost::range_iterator::type iterator; + + for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it) + { + per_turn<0>(*it); + per_turn<1>(*it); + } + + return m_result.interrupt; + } + + private: + template + inline void per_turn(Turn const& turn) + { + //static const std::size_t other_op_id = (OpId + 1) % 2; + static const bool transpose_result = OpId != 0; + + overlay::operation_type const op = turn.operations[OpId].operation; + + if ( op == overlay::operation_union ) + { + // ignore u/u + /*if ( turn.operations[other_op_id].operation != overlay::operation_union ) + { + update(m_result); + update(m_result); + }*/ + + update(m_result); + } + else if ( op == overlay::operation_intersection ) + { + // ignore i/i + /*if ( turn.operations[other_op_id].operation != overlay::operation_intersection ) + { + // not correct e.g. for G1 touching G2 in a point where a hole is touching the exterior ring + // in this case 2 turns i/... and u/u will be generated for this IP + //update(m_result); + + //update(m_result); + }*/ + + update(m_result); + } + else if ( op == overlay::operation_continue ) + { + update(m_result); + update(m_result); + } + else if ( op == overlay::operation_blocked ) + { + update(m_result); + update(m_result); + } + } + + Result & m_result; + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + }; + + // This analyser should be used like Input or SinglePass Iterator + // IMPORTANT! It should be called also for the end iterator - last + template + class turns_analyser + { + typedef typename TurnInfo::point_type turn_point_type; + + static const std::size_t op_id = OpId; + static const std::size_t other_op_id = (OpId + 1) % 2; + static const bool transpose_result = OpId != 0; + + public: + turns_analyser() + : m_previous_turn_ptr(0) + , m_previous_operation(overlay::operation_none) + , m_enter_detected(false) + , m_exit_detected(false) + {} + + template + void apply(Result & result, TurnIt it) + { + //BOOST_GEOMETRY_ASSERT( it != last ); + + overlay::operation_type const op = it->operations[op_id].operation; + + if ( op != overlay::operation_union + && op != overlay::operation_intersection + && op != overlay::operation_blocked + && op != overlay::operation_continue ) + { + return; + } + + segment_identifier const& seg_id = it->operations[op_id].seg_id; + //segment_identifier const& other_id = it->operations[other_op_id].seg_id; + + const bool first_in_range = m_seg_watcher.update(seg_id); + + if ( m_previous_turn_ptr ) + { + if ( m_exit_detected /*m_previous_operation == overlay::operation_union*/ ) + { + // real exit point - may be multiple + if ( first_in_range + || ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + { + update_exit(result); + m_exit_detected = false; + } + // fake exit point, reset state + else if ( op != overlay::operation_union ) + { + m_exit_detected = false; + } + } + /*else*/ + if ( m_enter_detected /*m_previous_operation == overlay::operation_intersection*/ ) + { + // real entry point + if ( first_in_range + || ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + { + update_enter(result); + m_enter_detected = false; + } + // fake entry point, reset state + else if ( op != overlay::operation_intersection ) + { + m_enter_detected = false; + } + } + } + + if ( op == overlay::operation_union ) + { + // already set in interrupt policy + //update(m_result); + + // ignore u/u + //if ( it->operations[other_op_id].operation != overlay::operation_union ) + { + m_exit_detected = true; + } + } + else if ( op == overlay::operation_intersection ) + { + // ignore i/i + if ( it->operations[other_op_id].operation != overlay::operation_intersection ) + { + // this was set in the interrupt policy but it was wrong + // also here it's wrong since it may be a fake entry point + //update(result); + + // already set in interrupt policy + //update(result); + m_enter_detected = true; + } + } + else if ( op == overlay::operation_blocked ) + { + // already set in interrupt policy + } + else // if ( op == overlay::operation_continue ) + { + // already set in interrupt policy + } + + // store ref to previously analysed (valid) turn + m_previous_turn_ptr = boost::addressof(*it); + // and previously analysed (valid) operation + m_previous_operation = op; + } + + // it == last + template + void apply(Result & result) + { + //BOOST_GEOMETRY_ASSERT( first != last ); + + if ( m_exit_detected /*m_previous_operation == overlay::operation_union*/ ) + { + update_exit(result); + m_exit_detected = false; + } + + if ( m_enter_detected /*m_previous_operation == overlay::operation_intersection*/ ) + { + update_enter(result); + m_enter_detected = false; + } + } + + template + static inline void update_exit(Result & result) + { + update(result); + update(result); + } + + template + static inline void update_enter(Result & result) + { + update(result); + update(result); + update(result); + } + + private: + segment_watcher m_seg_watcher; + TurnInfo * m_previous_turn_ptr; + overlay::operation_type m_previous_operation; + bool m_enter_detected; + bool m_exit_detected; + }; + + // call analyser.apply() for each turn in range + // IMPORTANT! The analyser is also called for the end iterator - last + template + static inline void analyse_each_turn(Result & res, + Analyser & analyser, + TurnIt first, TurnIt last) + { + if ( first == last ) + return; + + for ( TurnIt it = first ; it != last ; ++it ) + { + analyser.apply(res, it); + + if ( BOOST_GEOMETRY_CONDITION(res.interrupt) ) + return; + } + + analyser.apply(res); + } + + template + class uncertain_rings_analyser + { + static const bool transpose_result = OpId != 0; + static const int other_id = (OpId + 1) % 2; + + public: + inline uncertain_rings_analyser(Result & result, + Geometry const& geom, + OtherGeometry const& other_geom) + : geometry(geom), other_geometry(other_geom) + , interrupt(result.interrupt) // just in case, could be false as well + , m_result(result) + , m_flags(0) + { + // check which relations must be analysed + // NOTE: 1 and 4 could probably be connected + + if ( ! may_update(m_result) ) + { + m_flags |= 1; + } + + if ( ! may_update(m_result) + && ! may_update(m_result) ) + { + m_flags |= 2; + } + + if ( ! may_update(m_result) + && ! may_update(m_result) ) + { + m_flags |= 4; + } + } + + inline void no_turns(segment_identifier const& seg_id) + { + // if those flags are set nothing will change + if ( m_flags == 7 ) + { + return; + } + + typename detail::sub_range_return_type::type + range_ref = detail::sub_range(geometry, seg_id); + + if ( boost::empty(range_ref) ) + { + // TODO: throw an exception? + return; // ignore + } + + // TODO: possible optimization + // if the range is an interior ring we may use other IPs generated for this single geometry + // to know which other single geometries should be checked + + // TODO: optimize! e.g. use spatial index + // O(N) - running it in a loop gives O(NM) + int const pig = detail::within::point_in_geometry(range::front(range_ref), other_geometry); + + //BOOST_GEOMETRY_ASSERT(pig != 0); + if ( pig > 0 ) + { + update(m_result); + m_flags |= 1; + + update(m_result); + update(m_result); + m_flags |= 4; + } + else + { + update(m_result); + update(m_result); + m_flags |= 2; + } + +// TODO: break if all things are set +// also some of them could be checked outside, before the analysis +// In this case we shouldn't relay just on dummy flags +// Flags should be initialized with proper values +// or the result should be checked directly +// THIS IS ALSO TRUE FOR OTHER ANALYSERS! in L/L and L/A + + interrupt = m_flags == 7 || m_result.interrupt; + } + + template + inline void turns(TurnIt first, TurnIt last) + { + // if those flags are set nothing will change + if ( (m_flags & 6) == 6 ) + { + return; + } + + bool found_ii = false; + bool found_uu = false; + + for ( TurnIt it = first ; it != last ; ++it ) + { + if ( it->operations[0].operation == overlay::operation_intersection + && it->operations[1].operation == overlay::operation_intersection ) + { + found_ii = true; + } + else if ( it->operations[0].operation == overlay::operation_union + && it->operations[1].operation == overlay::operation_union ) + { + found_uu = true; + } + else // ignore + { + return; // don't interrupt + } + } + + // only i/i was generated for this ring + if ( found_ii ) + { + update(m_result); + m_flags |= 1; + + //update(m_result); + + update(m_result); + update(m_result); + m_flags |= 4; + } + + // only u/u was generated for this ring + if ( found_uu ) + { + update(m_result); + update(m_result); + m_flags |= 2; + } + + interrupt = m_flags == 7 || m_result.interrupt; // interrupt if the result won't be changed in the future + } + + Geometry const& geometry; + OtherGeometry const& other_geometry; + bool interrupt; + + private: + Result & m_result; + int m_flags; + }; + + template + class analyse_uncertain_rings + { + public: + template + static inline void apply(Analyser & analyser, TurnIt first, TurnIt last) + { + if ( first == last ) + return; + + for_preceding_rings(analyser, *first); + //analyser.per_turn(*first); + + TurnIt prev = first; + for ( ++first ; first != last ; ++first, ++prev ) + { + // same multi + if ( prev->operations[OpId].seg_id.multi_index + == first->operations[OpId].seg_id.multi_index ) + { + // same ring + if ( prev->operations[OpId].seg_id.ring_index + == first->operations[OpId].seg_id.ring_index ) + { + //analyser.per_turn(*first); + } + // same multi, next ring + else + { + //analyser.end_ring(*prev); + analyser.turns(prev, first); + + //if ( prev->operations[OpId].seg_id.ring_index + 1 + // < first->operations[OpId].seg_id.ring_index) + { + for_no_turns_rings(analyser, + *first, + prev->operations[OpId].seg_id.ring_index + 1, + first->operations[OpId].seg_id.ring_index); + } + + //analyser.per_turn(*first); + } + } + // next multi + else + { + //analyser.end_ring(*prev); + analyser.turns(prev, first); + for_following_rings(analyser, *prev); + for_preceding_rings(analyser, *first); + //analyser.per_turn(*first); + } + + if ( analyser.interrupt ) + { + return; + } + } + + //analyser.end_ring(*prev); + analyser.turns(prev, first); // first == last + for_following_rings(analyser, *prev); + } + + private: + template + static inline void for_preceding_rings(Analyser & analyser, Turn const& turn) + { + segment_identifier const& seg_id = turn.operations[OpId].seg_id; + + for_no_turns_rings(analyser, turn, -1, seg_id.ring_index); + } + + template + static inline void for_following_rings(Analyser & analyser, Turn const& turn) + { + segment_identifier const& seg_id = turn.operations[OpId].seg_id; + + signed_size_type + count = boost::numeric_cast( + geometry::num_interior_rings( + detail::single_geometry(analyser.geometry, seg_id))); + + for_no_turns_rings(analyser, turn, seg_id.ring_index + 1, count); + } + + template + static inline void for_no_turns_rings(Analyser & analyser, + Turn const& turn, + signed_size_type first, + signed_size_type last) + { + segment_identifier seg_id = turn.operations[OpId].seg_id; + + for ( seg_id.ring_index = first ; seg_id.ring_index < last ; ++seg_id.ring_index ) + { + analyser.no_turns(seg_id); + } + } + }; +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_AREAL_AREAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp new file mode 100755 index 0000000000..479a1c1199 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/boundary_checker.hpp @@ -0,0 +1,160 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP + +#include +#include +#include + +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +enum boundary_query { boundary_front, boundary_back, boundary_any }; + +template ::type> +class boundary_checker {}; + +template +class boundary_checker +{ + typedef typename point_type::type point_type; + +public: + boundary_checker(Geometry const& g) + : has_boundary( boost::size(g) >= 2 + && !detail::equals::equals_point_point(range::front(g), range::back(g)) ) + , geometry(g) + {} + + template + bool is_endpoint_boundary(point_type const& pt) const + { + boost::ignore_unused_variable_warning(pt); +#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER + // may give false positives for INT + BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) + && detail::equals::equals_point_point(pt, range::front(geometry)) + || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) + && detail::equals::equals_point_point(pt, range::back(geometry)) ); +#endif + return has_boundary; + } + +private: + bool has_boundary; + Geometry const& geometry; +}; + +template +class boundary_checker +{ + typedef typename point_type::type point_type; + +public: + boundary_checker(Geometry const& g) + : is_filled(false), geometry(g) + {} + + // First call O(NlogN) + // Each next call O(logN) + template + bool is_endpoint_boundary(point_type const& pt) const + { + typedef typename boost::range_size::type size_type; + size_type multi_count = boost::size(geometry); + + if ( multi_count < 1 ) + return false; + + if ( ! is_filled ) + { + //boundary_points.clear(); + boundary_points.reserve(multi_count * 2); + + typedef typename boost::range_iterator::type multi_iterator; + for ( multi_iterator it = boost::begin(geometry) ; + it != boost::end(geometry) ; ++ it ) + { + typename boost::range_reference::type + ls = *it; + + // empty or point - no boundary + if (boost::size(ls) < 2) + { + continue; + } + + typedef typename boost::range_reference + < + typename boost::range_value::type const + >::type point_reference; + + point_reference front_pt = range::front(ls); + point_reference back_pt = range::back(ls); + + // linear ring or point - no boundary + if (! equals::equals_point_point(front_pt, back_pt)) + { + // do not add points containing NaN coordinates + // because they cannot be reasonably compared, e.g. with MSVC + // an assertion failure is reported in std::equal_range() + if (! geometry::has_nan_coordinate(front_pt)) + { + boundary_points.push_back(front_pt); + } + if (! geometry::has_nan_coordinate(back_pt)) + { + boundary_points.push_back(back_pt); + } + } + } + + std::sort(boundary_points.begin(), + boundary_points.end(), + geometry::less()); + + is_filled = true; + } + + std::size_t equal_points_count + = boost::size( + std::equal_range(boundary_points.begin(), + boundary_points.end(), + pt, + geometry::less()) + ); + + return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0 + } + +private: + mutable bool is_filled; + // TODO: store references/pointers instead of points? + mutable std::vector boundary_points; + + Geometry const& geometry; +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOUNDARY_CHECKER_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/de9im.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/de9im.hpp new file mode 100755 index 0000000000..75fa7bc901 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/de9im.hpp @@ -0,0 +1,439 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// TEMP - move this header to geometry/detail +#include + +namespace boost { namespace geometry +{ + +namespace de9im +{ + +/*! +\brief DE-9IM model intersection matrix. +\ingroup de9im +\details This matrix can be used to express spatial relations as defined in + Dimensionally Extended 9-Intersection Model. + +\qbk{[heading See also]} +\qbk{* [link geometry.reference.algorithms.relation relation]} + */ +class matrix + : public detail::relate::matrix<3, 3> +{ +#ifdef DOXYGEN_INVOKED +public: + /*! + \brief Initializes all of the matrix elements to F + */ + matrix(); + /*! + \brief Subscript operator + \param index The index of the element + \return The element + */ + char operator[](std::size_t index) const; + /*! + \brief Returns the iterator to the first element + \return const RandomAccessIterator + */ + const_iterator begin() const; + /*! + \brief Returns the iterator past the last element + \return const RandomAccessIterator + */ + const_iterator end() const; + /*! + \brief Returns the number of elements + \return 9 + */ + static std::size_t size(); + /*! + \brief Returns raw pointer to elements + \return const pointer to array of elements + */ + inline const char * data() const; + /*! + \brief Returns std::string containing elements + \return string containing elements + */ + inline std::string str() const; +#endif +}; + +/*! +\brief DE-9IM model intersection mask. +\ingroup de9im +\details This mask can be used to check spatial relations as defined in + Dimensionally Extended 9-Intersection Model. + +\qbk{[heading See also]} +\qbk{* [link geometry.reference.algorithms.relate relate]} + */ +class mask + : public detail::relate::mask<3, 3> +{ + typedef detail::relate::mask<3, 3> base_type; + +public: + /*! + \brief The constructor. + \param code The mask pattern. + */ + inline explicit mask(const char* code) + : base_type(code) + {} + + /*! + \brief The constructor. + \param code The mask pattern. + */ + inline explicit mask(std::string const& code) + : base_type(code.c_str(), code.size()) + {} +}; + +// static_mask + +/*! +\brief DE-9IM model intersection mask (static version). +\ingroup de9im +\details This mask can be used to check spatial relations as defined in + Dimensionally Extended 9-Intersection Model. +\tparam II Interior/Interior intersection mask element +\tparam IB Interior/Boundary intersection mask element +\tparam IE Interior/Exterior intersection mask element +\tparam BI Boundary/Interior intersection mask element +\tparam BB Boundary/Boundary intersection mask element +\tparam BE Boundary/Exterior intersection mask element +\tparam EI Exterior/Interior intersection mask element +\tparam EB Exterior/Boundary intersection mask element +\tparam EE Exterior/Exterior intersection mask element + +\qbk{[heading See also]} +\qbk{* [link geometry.reference.algorithms.relate relate]} + */ +template +< + char II = '*', char IB = '*', char IE = '*', + char BI = '*', char BB = '*', char BE = '*', + char EI = '*', char EB = '*', char EE = '*' +> +class static_mask + : public detail::relate::static_mask + < + boost::mpl::vector_c + < + char, II, IB, IE, BI, BB, BE, EI, EB, EE + >, + 3, 3 + > +{}; + +} // namespace de9im + +namespace detail { namespace de9im +{ + +// a small helper util for ORing static masks + +template +< + typename Seq, + typename T, + bool IsSeq = boost::mpl::is_sequence::value +> +struct push_back +{ + typedef typename boost::mpl::push_back + < + Seq, + T + >::type type; +}; + +template +struct push_back +{}; + +}} // namespace detail::de9im + +namespace de9im +{ + +inline +boost::tuples::cons + < + mask, + boost::tuples::cons + > +operator||(mask const& m1, mask const& m2) +{ + namespace bt = boost::tuples; + + return bt::cons > + ( m1, bt::cons(m2, bt::null_type()) ); +} + +template +inline +typename index::detail::tuples::push_back + < + boost::tuples::cons, + mask + >::type +operator||(boost::tuples::cons const& t, mask const& m) +{ + namespace bt = boost::tuples; + + return index::detail::tuples::push_back + < + bt::cons, + mask + >::apply(t, m); +} + +template +< + char II1, char IB1, char IE1, + char BI1, char BB1, char BE1, + char EI1, char EB1, char EE1, + char II2, char IB2, char IE2, + char BI2, char BB2, char BE2, + char EI2, char EB2, char EE2 +> +inline +boost::mpl::vector< + static_mask, + static_mask +> +operator||(static_mask const& , + static_mask const& ) +{ + return boost::mpl::vector + < + static_mask, + static_mask + >(); +} + +template +< + typename Seq, + char II, char IB, char IE, + char BI, char BB, char BE, + char EI, char EB, char EE +> +inline +typename detail::de9im::push_back + < + Seq, + static_mask + >::type +operator||(Seq const& , + static_mask const& ) +{ + return typename detail::de9im::push_back + < + Seq, + static_mask + >::type(); +} + +} // namespace de9im + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace de9im +{ + +// PREDEFINED MASKS + +// TODO: +// 1. specialize for simplified masks if available +// e.g. for TOUCHES use 1 mask for A/A +// 2. Think about dimensions > 2 e.g. should TOUCHES be true +// if the interior of the Areal overlaps the boundary of the Volumetric +// like it's true for Linear/Areal + +// EQUALS +template +struct static_mask_equals_type +{ + typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', 'F', 'F', '*'> type; // wikipedia + //typedef geometry::de9im::static_mask<'T', 'F', 'F', 'F', 'T', 'F', 'F', 'F', 'T'> type; // OGC +}; + +// DISJOINT +template +struct static_mask_disjoint_type +{ + typedef geometry::de9im::static_mask<'F', 'F', '*', 'F', 'F', '*', '*', '*', '*'> type; +}; + +// TOUCHES - NOT P/P +template +< + typename Geometry1, + typename Geometry2, + std::size_t Dim1 = geometry::topological_dimension::value, + std::size_t Dim2 = geometry::topological_dimension::value +> +struct static_mask_touches_impl +{ + typedef boost::mpl::vector + < + geometry::de9im::static_mask<'F', 'T', '*', '*', '*', '*', '*', '*', '*'>, + geometry::de9im::static_mask<'F', '*', '*', 'T', '*', '*', '*', '*', '*'>, + geometry::de9im::static_mask<'F', '*', '*', '*', 'T', '*', '*', '*', '*'> + > type; +}; +// According to OGC, doesn't apply to P/P +// Using the above mask the result would be always false +template +struct static_mask_touches_impl + : not_implemented::type, + typename geometry::tag::type> +{}; + +template +struct static_mask_touches_type + : static_mask_touches_impl +{}; + +// WITHIN +template +struct static_mask_within_type +{ + typedef geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'> type; +}; + +// COVERED_BY (non OGC) +template +struct static_mask_covered_by_type +{ + typedef boost::mpl::vector + < + geometry::de9im::static_mask<'T', '*', 'F', '*', '*', 'F', '*', '*', '*'>, + geometry::de9im::static_mask<'*', 'T', 'F', '*', '*', 'F', '*', '*', '*'>, + geometry::de9im::static_mask<'*', '*', 'F', 'T', '*', 'F', '*', '*', '*'>, + geometry::de9im::static_mask<'*', '*', 'F', '*', 'T', 'F', '*', '*', '*'> + > type; +}; + +// CROSSES +// dim(G1) < dim(G2) - P/L P/A L/A +template +< + typename Geometry1, + typename Geometry2, + std::size_t Dim1 = geometry::topological_dimension::value, + std::size_t Dim2 = geometry::topological_dimension::value, + bool D1LessD2 = (Dim1 < Dim2) +> +struct static_mask_crosses_impl +{ + typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', '*', '*', '*'> type; +}; +// TODO: I'm not sure if this one below should be available! +// dim(G1) > dim(G2) - L/P A/P A/L +template +< + typename Geometry1, typename Geometry2, std::size_t Dim1, std::size_t Dim2 +> +struct static_mask_crosses_impl +{ + typedef geometry::de9im::static_mask<'T', '*', '*', '*', '*', '*', 'T', '*', '*'> type; +}; +// dim(G1) == dim(G2) - P/P A/A +template +< + typename Geometry1, typename Geometry2, std::size_t Dim +> +struct static_mask_crosses_impl + : not_implemented + < + typename geometry::tag::type, + typename geometry::tag::type + > +{}; +// dim(G1) == 1 && dim(G2) == 1 - L/L +template +struct static_mask_crosses_impl +{ + typedef geometry::de9im::static_mask<'0', '*', '*', '*', '*', '*', '*', '*', '*'> type; +}; + +template +struct static_mask_crosses_type + : static_mask_crosses_impl +{}; + +// OVERLAPS + +// dim(G1) != dim(G2) - NOT P/P, L/L, A/A +template +< + typename Geometry1, + typename Geometry2, + std::size_t Dim1 = geometry::topological_dimension::value, + std::size_t Dim2 = geometry::topological_dimension::value +> +struct static_mask_overlaps_impl + : not_implemented + < + typename geometry::tag::type, + typename geometry::tag::type + > +{}; +// dim(G1) == D && dim(G2) == D - P/P A/A +template +struct static_mask_overlaps_impl +{ + typedef geometry::de9im::static_mask<'T', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; +}; +// dim(G1) == 1 && dim(G2) == 1 - L/L +template +struct static_mask_overlaps_impl +{ + typedef geometry::de9im::static_mask<'1', '*', 'T', '*', '*', '*', 'T', '*', '*'> type; +}; + +template +struct static_mask_overlaps_type + : static_mask_overlaps_impl +{}; + +}} // namespace detail::de9im +#endif // DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_DE9IM_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp new file mode 100755 index 0000000000..b768f8727d --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/follow_helpers.hpp @@ -0,0 +1,404 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP + +#include + +#include +#include +//#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +// NOTE: This iterates through single geometries for which turns were not generated. +// It doesn't mean that the geometry is disjoint, only that no turns were detected. + +template ::type, + bool IsMulti = boost::is_base_of::value +> +struct for_each_disjoint_geometry_if + : public not_implemented +{}; + +template +struct for_each_disjoint_geometry_if +{ + template + static inline bool apply(TurnIt first, TurnIt last, + Geometry const& geometry, + Pred & pred) + { + if ( first != last ) + return false; + pred(geometry); + return true; + } +}; + +template +struct for_each_disjoint_geometry_if +{ + template + static inline bool apply(TurnIt first, TurnIt last, + Geometry const& geometry, + Pred & pred) + { + if ( first != last ) + return for_turns(first, last, geometry, pred); + else + return for_empty(geometry, pred); + } + + template + static inline bool for_empty(Geometry const& geometry, + Pred & pred) + { + typedef typename boost::range_iterator::type iterator; + + // O(N) + // check predicate for each contained geometry without generated turn + for ( iterator it = boost::begin(geometry) ; + it != boost::end(geometry) ; ++it ) + { + bool cont = pred(*it); + if ( !cont ) + break; + } + + return !boost::empty(geometry); + } + + template + static inline bool for_turns(TurnIt first, TurnIt last, + Geometry const& geometry, + Pred & pred) + { + BOOST_GEOMETRY_ASSERT(first != last); + + const std::size_t count = boost::size(geometry); + boost::ignore_unused_variable_warning(count); + + // O(I) + // gather info about turns generated for contained geometries + std::vector detected_intersections(count, false); + for ( TurnIt it = first ; it != last ; ++it ) + { + signed_size_type multi_index = it->operations[OpId].seg_id.multi_index; + BOOST_GEOMETRY_ASSERT(multi_index >= 0); + std::size_t const index = static_cast(multi_index); + BOOST_GEOMETRY_ASSERT(index < count); + detected_intersections[index] = true; + } + + bool found = false; + + // O(N) + // check predicate for each contained geometry without generated turn + for ( std::vector::iterator it = detected_intersections.begin() ; + it != detected_intersections.end() ; ++it ) + { + // if there were no intersections for this multi_index + if ( *it == false ) + { + found = true; + std::size_t const index = std::size_t(std::distance(detected_intersections.begin(), it)); + bool cont = pred(range::at(geometry, index)); + if ( !cont ) + break; + } + } + + return found; + } +}; + +// WARNING! This class stores pointers! +// Passing a reference to local variable will result in undefined behavior! +template +class point_info +{ +public: + point_info() : sid_ptr(NULL), pt_ptr(NULL) {} + point_info(Point const& pt, segment_identifier const& sid) + : sid_ptr(boost::addressof(sid)) + , pt_ptr(boost::addressof(pt)) + {} + segment_identifier const& seg_id() const + { + BOOST_GEOMETRY_ASSERT(sid_ptr); + return *sid_ptr; + } + Point const& point() const + { + BOOST_GEOMETRY_ASSERT(pt_ptr); + return *pt_ptr; + } + + //friend bool operator==(point_identifier const& l, point_identifier const& r) + //{ + // return l.seg_id() == r.seg_id() + // && detail::equals::equals_point_point(l.point(), r.point()); + //} + +private: + const segment_identifier * sid_ptr; + const Point * pt_ptr; +}; + +// WARNING! This class stores pointers! +// Passing a reference to local variable will result in undefined behavior! +class same_single +{ +public: + same_single(segment_identifier const& sid) + : sid_ptr(boost::addressof(sid)) + {} + + bool operator()(segment_identifier const& sid) const + { + return sid.multi_index == sid_ptr->multi_index; + } + + template + bool operator()(point_info const& pid) const + { + return operator()(pid.seg_id()); + } + +private: + const segment_identifier * sid_ptr; +}; + +class same_ring +{ +public: + same_ring(segment_identifier const& sid) + : sid_ptr(boost::addressof(sid)) + {} + + bool operator()(segment_identifier const& sid) const + { + return sid.multi_index == sid_ptr->multi_index + && sid.ring_index == sid_ptr->ring_index; + } + +private: + const segment_identifier * sid_ptr; +}; + +// WARNING! This class stores pointers! +// Passing a reference to local variable will result in undefined behavior! +template +class segment_watcher +{ +public: + segment_watcher() + : m_seg_id_ptr(NULL) + {} + + bool update(segment_identifier const& seg_id) + { + bool result = m_seg_id_ptr == 0 || !SameRange(*m_seg_id_ptr)(seg_id); + m_seg_id_ptr = boost::addressof(seg_id); + return result; + } + +private: + const segment_identifier * m_seg_id_ptr; +}; + +// WARNING! This class stores pointers! +// Passing a reference to local variable will result in undefined behavior! +template +class exit_watcher +{ + static const std::size_t op_id = OpId; + static const std::size_t other_op_id = (OpId + 1) % 2; + + typedef typename TurnInfo::point_type point_type; + typedef detail::relate::point_info point_info; + +public: + exit_watcher() + : m_exit_operation(overlay::operation_none) + , m_exit_turn_ptr(NULL) + {} + + void enter(TurnInfo const& turn) + { + m_other_entry_points.push_back( + point_info(turn.point, turn.operations[other_op_id].seg_id) ); + } + + // TODO: exit_per_geometry parameter looks not very safe + // wrong value may be easily passed + + void exit(TurnInfo const& turn, bool exit_per_geometry = true) + { + //segment_identifier const& seg_id = turn.operations[op_id].seg_id; + segment_identifier const& other_id = turn.operations[other_op_id].seg_id; + overlay::operation_type exit_op = turn.operations[op_id].operation; + + typedef typename std::vector::iterator point_iterator; + // search for the entry point in the same range of other geometry + point_iterator entry_it = std::find_if(m_other_entry_points.begin(), + m_other_entry_points.end(), + same_single(other_id)); + + // this end point has corresponding entry point + if ( entry_it != m_other_entry_points.end() ) + { + // erase the corresponding entry point + m_other_entry_points.erase(entry_it); + + if ( exit_per_geometry || m_other_entry_points.empty() ) + { + // here we know that we possibly left LS + // we must still check if we didn't get back on the same point + m_exit_operation = exit_op; + m_exit_turn_ptr = boost::addressof(turn); + } + } + } + + bool is_outside() const + { + // if we didn't entered anything in the past, we're outside + return m_other_entry_points.empty(); + } + + bool is_outside(TurnInfo const& turn) const + { + return m_other_entry_points.empty() + || std::find_if(m_other_entry_points.begin(), + m_other_entry_points.end(), + same_single( + turn.operations[other_op_id].seg_id)) + == m_other_entry_points.end(); + } + + overlay::operation_type get_exit_operation() const + { + return m_exit_operation; + } + + point_type const& get_exit_point() const + { + BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none); + BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr); + return m_exit_turn_ptr->point; + } + + TurnInfo const& get_exit_turn() const + { + BOOST_GEOMETRY_ASSERT(m_exit_operation != overlay::operation_none); + BOOST_GEOMETRY_ASSERT(m_exit_turn_ptr); + return *m_exit_turn_ptr; + } + + void reset_detected_exit() + { + m_exit_operation = overlay::operation_none; + } + + void reset() + { + m_exit_operation = overlay::operation_none; + m_other_entry_points.clear(); + } + +private: + overlay::operation_type m_exit_operation; + const TurnInfo * m_exit_turn_ptr; + std::vector m_other_entry_points; // TODO: use map here or sorted vector? +}; + +template +inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn) +{ + segment_identifier const& prev_seg_id = prev_turn.operations[OpId].seg_id; + segment_identifier const& curr_seg_id = curr_turn.operations[OpId].seg_id; + + if ( prev_seg_id.multi_index != curr_seg_id.multi_index + || prev_seg_id.ring_index != curr_seg_id.ring_index ) + { + return false; + } + + // TODO: will this work if between segments there will be some number of degenerated ones? + + if ( prev_seg_id.segment_index != curr_seg_id.segment_index + && ( ! curr_turn.operations[OpId].fraction.is_zero() + || prev_seg_id.segment_index + 1 != curr_seg_id.segment_index ) ) + { + return false; + } + + return detail::equals::equals_point_point(prev_turn.point, curr_turn.point); +} + +template +static inline bool is_endpoint_on_boundary(Point const& pt, + BoundaryChecker & boundary_checker) +{ + return boundary_checker.template is_endpoint_boundary(pt); +} + +template +static inline bool is_ip_on_boundary(IntersectionPoint const& ip, + OperationInfo const& operation_info, + BoundaryChecker & boundary_checker, + segment_identifier const& seg_id) +{ + boost::ignore_unused_variable_warning(seg_id); + + bool res = false; + + // IP on the last point of the linestring + if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_back || BoundaryQuery == boundary_any) + && operation_info.position == overlay::position_back ) + { + // check if this point is a boundary + res = boundary_checker.template is_endpoint_boundary(ip); + } + // IP on the last point of the linestring + else if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_front || BoundaryQuery == boundary_any) + && operation_info.position == overlay::position_front ) + { + // check if this point is a boundary + res = boundary_checker.template is_endpoint_boundary(ip); + } + + return res; +} + + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_FOLLOW_HELPERS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/implementation.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/implementation.hpp new file mode 100755 index 0000000000..0f17387a6f --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/implementation.hpp @@ -0,0 +1,110 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP + + +#include + +#include + +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry { + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch { + +template +struct relate + : detail::relate::point_point +{}; + +template +struct relate + : detail::relate::point_multipoint +{}; + +template +struct relate + : detail::relate::multipoint_point +{}; + +template +struct relate + : detail::relate::multipoint_multipoint +{}; + +// TODO - for now commented out because before implementing it we must consider: +// 1. how the Box degenerated to a Point should be treated +// 2. what should be the definition of a Box degenerated to a Point +// 3. what fields should the matrix/mask contain for dimension > 2 and dimension > 9 +// +//template +//struct relate +// : detail::relate::point_box +//{}; +// +//template +//struct relate +// : detail::relate::box_point +//{}; + + +template +struct relate + : detail::relate::point_geometry +{}; + +template +struct relate + : detail::relate::geometry_point +{}; + + +template +struct relate + : detail::relate::linear_linear +{}; + + +template +struct relate + : detail::relate::linear_areal +{}; + +template +struct relate + : detail::relate::areal_linear +{}; + + +template +struct relate + : detail::relate::areal_areal +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/interface.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/interface.hpp new file mode 100755 index 0000000000..ef6f936638 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/interface.hpp @@ -0,0 +1,348 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry { + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +// Those are used only to allow dispatch::relate to produce compile-time error + +template ::type> +struct is_supported_by_generic +{ + static const bool value + = boost::is_same::value + || boost::is_same::value + || boost::is_same::value + || boost::is_same::value + || boost::is_same::value; +}; + +template ::type, + typename Tag2 = typename geometry::tag::type> +struct is_generic +{ + static const bool value = is_supported_by_generic::value + && is_supported_by_generic::value; +}; + + +template +struct is_generic +{ + static const bool value = is_supported_by_generic::value; +}; + +template +struct is_generic +{ + static const bool value = is_supported_by_generic::value; +}; + +template +struct is_generic +{ + static const bool value = false; +}; + + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch { + + +template ::type, + typename Tag2 = typename geometry::tag::type, + int TopDim1 = geometry::topological_dimension::value, + int TopDim2 = geometry::topological_dimension::value, + bool IsGeneric = detail::relate::is_generic::value +> +struct relate : not_implemented +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +template +struct interruption_enabled +{ + static const bool value = + dispatch::relate::interruption_enabled; +}; + +template ::value> +struct result_handler_type + : not_implemented +{}; + +template +struct result_handler_type +{ + typedef mask_handler + < + geometry::de9im::mask, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +template +struct result_handler_type, false> +{ + typedef mask_handler + < + boost::tuples::cons, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +template +struct result_handler_type + < + Geometry1, + Geometry2, + geometry::de9im::static_mask, + false + > +{ + typedef static_mask_handler + < + geometry::de9im::static_mask, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +template +struct result_handler_type +{ + typedef static_mask_handler + < + StaticSequence, + interruption_enabled + < + Geometry1, + Geometry2 + >::value + > type; +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +namespace resolve_variant { + +template +struct relate +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Mask const& mask) + { + concepts::check(); + concepts::check(); + assert_dimension_equal(); + + typename detail::relate::result_handler_type + < + Geometry1, + Geometry2, + Mask + >::type handler(mask); + + dispatch::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, handler); + + return handler.result(); + } +}; + +template +struct relate, Geometry2> +{ + template + struct visitor : boost::static_visitor + { + Geometry2 const& m_geometry2; + Mask const& m_mask; + + visitor(Geometry2 const& geometry2, Mask const& mask) + : m_geometry2(geometry2), m_mask(mask) {} + + template + bool operator()(Geometry1 const& geometry1) const + { + return relate + ::apply(geometry1, m_geometry2, m_mask); + } + }; + + template + static inline bool + apply(boost::variant const& geometry1, + Geometry2 const& geometry2, + Mask const& mask) + { + return boost::apply_visitor(visitor(geometry2, mask), geometry1); + } +}; + +template +struct relate > +{ + template + struct visitor : boost::static_visitor + { + Geometry1 const& m_geometry1; + Mask const& m_mask; + + visitor(Geometry1 const& geometry1, Mask const& mask) + : m_geometry1(geometry1), m_mask(mask) {} + + template + bool operator()(Geometry2 const& geometry2) const + { + return relate + ::apply(m_geometry1, geometry2, m_mask); + } + }; + + template + static inline bool + apply(Geometry1 const& geometry1, + boost::variant const& geometry2, + Mask const& mask) + { + return boost::apply_visitor(visitor(geometry1, mask), geometry2); + } +}; + +template < + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2) +> +struct relate< + boost::variant, + boost::variant +> +{ + template + struct visitor : boost::static_visitor + { + Mask const& m_mask; + + visitor(Mask const& mask) + : m_mask(mask) {} + + template + bool operator()(Geometry1 const& geometry1, + Geometry2 const& geometry2) const + { + return relate + ::apply(geometry1, geometry2, m_mask); + } + }; + + template + static inline bool + apply(boost::variant const& geometry1, + boost::variant const& geometry2, + Mask const& mask) + { + return boost::apply_visitor(visitor(mask), geometry1, geometry2); + } +}; + +} // namespace resolve_variant + +/*! +\brief Checks relation between a pair of geometries defined by a mask. +\ingroup relate +\tparam Geometry1 \tparam_geometry +\tparam Geometry2 \tparam_geometry +\tparam Mask An intersection model Mask type. +\param geometry1 \param_geometry +\param geometry2 \param_geometry +\param mask An intersection model mask object. +\return true if the relation is compatible with the mask, false otherwise. + +\qbk{[include reference/algorithms/relate.qbk]} + */ +template +inline bool relate(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Mask const& mask) +{ + return resolve_variant::relate + < + Geometry1, + Geometry2 + >::apply(geometry1, geometry2, mask); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_INTERFACE_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/less.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/less.hpp new file mode 100755 index 0000000000..62446b4005 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/less.hpp @@ -0,0 +1,83 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP + +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace detail_dispatch { namespace relate { + +// TODO: Integrate it with geometry::less? + +template ::value> +struct less +{ + static inline bool apply(Point1 const& left, Point2 const& right) + { + typename geometry::coordinate_type::type + cleft = geometry::get(left); + typename geometry::coordinate_type::type + cright = geometry::get(right); + + if ( geometry::math::equals(cleft, cright) ) + { + return less::apply(left, right); + } + else + { + return cleft < cright; + } + } +}; + +template +struct less +{ + static inline bool apply(Point1 const&, Point2 const&) + { + return false; + } +}; + +}} // namespace detail_dispatch::relate + +#endif + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +struct less +{ + template + inline bool operator()(Point1 const& point1, Point2 const& point2) const + { + return detail_dispatch::relate::less::apply(point1, point2); + } +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp new file mode 100755 index 0000000000..6f1692633f --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -0,0 +1,1435 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +// WARNING! +// TODO: In the worst case calling this Pred in a loop for MultiLinestring/MultiPolygon may take O(NM) +// Use the rtree in this case! + +// may be used to set IE and BE for a Linear geometry for which no turns were generated +template +class no_turns_la_linestring_pred +{ +public: + no_turns_la_linestring_pred(Geometry2 const& geometry2, + Result & res, + BoundaryChecker const& boundary_checker) + : m_geometry2(geometry2) + , m_result(res) + , m_boundary_checker(boundary_checker) + , m_interrupt_flags(0) + { + if ( ! may_update(m_result) ) + { + m_interrupt_flags |= 1; + } + + if ( ! may_update(m_result) ) + { + m_interrupt_flags |= 2; + } + + if ( ! may_update(m_result) ) + { + m_interrupt_flags |= 4; + } + + if ( ! may_update(m_result) ) + { + m_interrupt_flags |= 8; + } + } + + template + bool operator()(Linestring const& linestring) + { + std::size_t const count = boost::size(linestring); + + // invalid input + if ( count < 2 ) + { + // ignore + // TODO: throw an exception? + return true; + } + + // if those flags are set nothing will change + if ( m_interrupt_flags == 0xF ) + { + return false; + } + + int const pig = detail::within::point_in_geometry(range::front(linestring), m_geometry2); + //BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs"); + + if ( pig > 0 ) + { + update(m_result); + m_interrupt_flags |= 1; + } + else + { + update(m_result); + m_interrupt_flags |= 2; + } + + // check if there is a boundary + if ( ( m_interrupt_flags & 0xC ) != 0xC // if wasn't already set + && ( m_boundary_checker.template + is_endpoint_boundary(range::front(linestring)) + || m_boundary_checker.template + is_endpoint_boundary(range::back(linestring)) ) ) + { + if ( pig > 0 ) + { + update(m_result); + m_interrupt_flags |= 4; + } + else + { + update(m_result); + m_interrupt_flags |= 8; + } + } + + return m_interrupt_flags != 0xF + && ! m_result.interrupt; + } + +private: + Geometry2 const& m_geometry2; + Result & m_result; + BoundaryChecker const& m_boundary_checker; + unsigned m_interrupt_flags; +}; + +// may be used to set EI and EB for an Areal geometry for which no turns were generated +template +class no_turns_la_areal_pred +{ +public: + no_turns_la_areal_pred(Result & res) + : m_result(res) + , interrupt(! may_update(m_result) + && ! may_update(m_result) ) + {} + + template + bool operator()(Areal const& areal) + { + if ( interrupt ) + { + return false; + } + + // TODO: + // handle empty/invalid geometries in a different way than below? + + typedef typename geometry::point_type::type point_type; + point_type dummy; + bool const ok = boost::geometry::point_on_border(dummy, areal); + + // TODO: for now ignore, later throw an exception? + if ( !ok ) + { + return true; + } + + update(m_result); + update(m_result); + + return false; + } + +private: + Result & m_result; + bool const interrupt; +}; + +// The implementation of an algorithm calculating relate() for L/A +template +struct linear_areal +{ + // check Linear / Areal + BOOST_STATIC_ASSERT(topological_dimension::value == 1 + && topological_dimension::value == 2); + + static const bool interruption_enabled = true; + + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; + + template + struct is_multi + : boost::is_base_of + < + multi_tag, + typename tag::type + > + {}; + + template + struct multi_turn_info + : turns::get_turns::turn_info + { + multi_turn_info() : priority(0) {} + int priority; // single-geometry sorting priority + }; + + template + struct turn_info_type + : boost::mpl::if_c + < + is_multi::value, + multi_turn_info, + typename turns::get_turns::turn_info + > + {}; + + template + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + { +// TODO: If Areal geometry may have infinite size, change the following line: + + // The result should be FFFFFFFFF + relate::set::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T + + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + // get and analyse turns + typedef typename turn_info_type::type turn_type; + std::vector turns; + + interrupt_policy_linear_areal interrupt_policy(geometry2, result); + + turns::get_turns::apply(turns, geometry1, geometry2, interrupt_policy); + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + boundary_checker boundary_checker1(geometry1); + no_turns_la_linestring_pred + < + Geometry2, + Result, + boundary_checker, + TransposeResult + > pred1(geometry2, result, boundary_checker1); + for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + no_turns_la_areal_pred pred2(result); + for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + if ( turns.empty() ) + return; + + // This is set here because in the case if empty Areal geometry were passed + // those shouldn't be set + relate::set(result);// FFFFFF2Fd + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + { + sort_dispatch(turns.begin(), turns.end(), is_multi()); + + turns_analyser analyser; + analyse_each_turn(result, analyser, + turns.begin(), turns.end(), + geometry1, geometry2, + boundary_checker1); + + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + } + + // If 'c' (insersection_boundary) was not found we know that any Ls isn't equal to one of the Rings + if ( !interrupt_policy.is_boundary_found ) + { + relate::set(result); + } + // Don't calculate it if it's required + else if ( may_update(result) ) + { +// TODO: REVISE THIS CODE AND PROBABLY REWRITE SOME PARTS TO BE MORE HUMAN-READABLE +// IN GENERAL IT ANALYSES THE RINGS OF AREAL GEOMETRY AND DETECTS THE ONES THAT +// MAY OVERLAP THE INTERIOR OF LINEAR GEOMETRY (NO IPs OR NON-FAKE 'u' OPERATION) +// NOTE: For one case std::sort may be called again to sort data by operations for data already sorted by ring index +// In the worst case scenario the complexity will be O( NlogN + R*(N/R)log(N/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) +// Some benchmarking should probably be done to check if only one std::sort should be used + + // sort by multi_index and rind_index + std::sort(turns.begin(), turns.end(), less_ring()); + + typedef typename std::vector::iterator turn_iterator; + + turn_iterator it = turns.begin(); + segment_identifier * prev_seg_id_ptr = NULL; + // for each ring + for ( ; it != turns.end() ; ) + { + // it's the next single geometry + if ( prev_seg_id_ptr == NULL + || prev_seg_id_ptr->multi_index != it->operations[1].seg_id.multi_index ) + { + // if the first ring has no IPs + if ( it->operations[1].seg_id.ring_index > -1 ) + { + // we can be sure that the exterior overlaps the boundary + relate::set(result); + break; + } + // if there was some previous ring + if ( prev_seg_id_ptr != NULL ) + { + signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1; + BOOST_GEOMETRY_ASSERT(next_ring_index >= 0); + + // if one of the last rings of previous single geometry was ommited + if ( static_cast(next_ring_index) + < geometry::num_interior_rings( + single_geometry(geometry2, *prev_seg_id_ptr)) ) + { + // we can be sure that the exterior overlaps the boundary + relate::set(result); + break; + } + } + } + // if it's the same single geometry + else /*if ( previous_multi_index == it->operations[1].seg_id.multi_index )*/ + { + // and we jumped over one of the rings + if ( prev_seg_id_ptr != NULL // just in case + && prev_seg_id_ptr->ring_index + 1 < it->operations[1].seg_id.ring_index ) + { + // we can be sure that the exterior overlaps the boundary + relate::set(result); + break; + } + } + + prev_seg_id_ptr = boost::addressof(it->operations[1].seg_id); + + // find the next ring first iterator and check if the analysis should be performed + has_boundary_intersection has_boundary_inters; + turn_iterator next = find_next_ring(it, turns.end(), has_boundary_inters); + + // if there is no 1d overlap with the boundary + if ( !has_boundary_inters.result ) + { + // we can be sure that the exterior overlaps the boundary + relate::set(result); + break; + } + // else there is 1d overlap with the boundary so we must analyse the boundary + else + { + // u, c + typedef turns::less<1, turns::less_op_areal_linear<1> > less; + std::sort(it, next, less()); + + // analyse + areal_boundary_analyser analyser; + for ( turn_iterator rit = it ; rit != next ; ++rit ) + { + // if the analyser requests, break the search + if ( !analyser.apply(it, rit, next) ) + break; + } + + // if the boundary of Areal goes out of the Linear + if ( analyser.is_union_detected ) + { + // we can be sure that the boundary of Areal overlaps the exterior of Linear + relate::set(result); + break; + } + } + + it = next; + } + + // if there was some previous ring + if ( prev_seg_id_ptr != NULL ) + { + signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1; + BOOST_GEOMETRY_ASSERT(next_ring_index >= 0); + + // if one of the last rings of previous single geometry was ommited + if ( static_cast(next_ring_index) + < geometry::num_interior_rings( + single_geometry(geometry2, *prev_seg_id_ptr)) ) + { + // we can be sure that the exterior overlaps the boundary + relate::set(result); + } + } + } + } + + template + static void for_each_equal_range(It first, It last, Pred pred, Comp comp) + { + if ( first == last ) + return; + + It first_equal = first; + It prev = first; + for ( ++first ; ; ++first, ++prev ) + { + if ( first == last || !comp(*prev, *first) ) + { + pred(first_equal, first); + first_equal = first; + } + + if ( first == last ) + break; + } + } + + struct same_ip + { + template + bool operator()(Turn const& left, Turn const& right) const + { + return left.operations[0].seg_id == right.operations[0].seg_id + && left.operations[0].fraction == right.operations[0].fraction; + } + }; + + struct same_ip_and_multi_index + { + template + bool operator()(Turn const& left, Turn const& right) const + { + return same_ip()(left, right) + && left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index; + } + }; + + template + struct set_turns_group_priority + { + template + void operator()(TurnIt first, TurnIt last) const + { + BOOST_GEOMETRY_ASSERT(first != last); + static OpToPriority op_to_priority; + // find the operation with the least priority + int least_priority = op_to_priority(first->operations[0]); + for ( TurnIt it = first + 1 ; it != last ; ++it ) + { + int priority = op_to_priority(it->operations[0]); + if ( priority < least_priority ) + least_priority = priority; + } + // set the least priority for all turns of the group + for ( TurnIt it = first ; it != last ; ++it ) + { + it->priority = least_priority; + } + } + }; + + template + struct sort_turns_group + { + struct less + { + template + bool operator()(Turn const& left, Turn const& right) const + { + return left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index ? + SingleLess()(left, right) : + left.priority < right.priority; + } + }; + + template + void operator()(TurnIt first, TurnIt last) const + { + std::sort(first, last, less()); + } + }; + + template + static void sort_dispatch(TurnIt first, TurnIt last, boost::true_type const& /*is_multi*/) + { + // sort turns by Linear seg_id, then by fraction, then by other multi_index + typedef turns::less<0, turns::less_other_multi_index<0> > less; + std::sort(first, last, less()); + + // For the same IP and multi_index - the same other's single geometry + // set priorities as the least operation found for the whole single geometry + // so e.g. single geometries containing 'u' will always be before those only containing 'i' + typedef turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic; + for_each_equal_range(first, last, + set_turns_group_priority(), // least operation in xuic order + same_ip_and_multi_index()); // other's multi_index + + // When priorities for single geometries are set now sort turns for the same IP + // if multi_index is the same sort them according to the single-less + // else use priority of the whole single-geometry set earlier + typedef turns::less<0, turns::less_op_linear_areal_single<0> > single_less; + for_each_equal_range(first, last, + sort_turns_group(), + same_ip()); + } + + template + static void sort_dispatch(TurnIt first, TurnIt last, boost::false_type const& /*is_multi*/) + { + // sort turns by Linear seg_id, then by fraction, then + // for same ring id: x, u, i, c + // for different ring id: c, i, u, x + typedef turns::less<0, turns::less_op_linear_areal_single<0> > less; + std::sort(first, last, less()); + } + + + // interrupt policy which may be passed to get_turns to interrupt the analysis + // based on the info in the passed result/mask + template + class interrupt_policy_linear_areal + { + public: + static bool const enabled = true; + + interrupt_policy_linear_areal(Areal const& areal, Result & result) + : m_result(result), m_areal(areal) + , is_boundary_found(false) + {} + +// TODO: since we update result for some operations here, we may not do it in the analyser! + + template + inline bool apply(Range const& turns) + { + typedef typename boost::range_iterator::type iterator; + + for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it) + { + if ( it->operations[0].operation == overlay::operation_intersection ) + { + bool const no_interior_rings + = geometry::num_interior_rings( + single_geometry(m_areal, it->operations[1].seg_id)) == 0; + + // WARNING! THIS IS TRUE ONLY IF THE POLYGON IS SIMPLE! + // OR WITHOUT INTERIOR RINGS (AND OF COURSE VALID) + if ( no_interior_rings ) + update(m_result); + } + else if ( it->operations[0].operation == overlay::operation_continue ) + { + update(m_result); + is_boundary_found = true; + } + else if ( ( it->operations[0].operation == overlay::operation_union + || it->operations[0].operation == overlay::operation_blocked ) + && it->operations[0].position == overlay::position_middle ) + { +// TODO: here we could also check the boundaries and set BB at this point + update(m_result); + } + } + + return m_result.interrupt; + } + + private: + Result & m_result; + Areal const& m_areal; + + public: + bool is_boundary_found; + }; + + // This analyser should be used like Input or SinglePass Iterator + // IMPORTANT! It should be called also for the end iterator - last + template + class turns_analyser + { + typedef typename TurnInfo::point_type turn_point_type; + + static const std::size_t op_id = 0; + static const std::size_t other_op_id = 1; + + public: + turns_analyser() + : m_previous_turn_ptr(NULL) + , m_previous_operation(overlay::operation_none) + , m_boundary_counter(0) + , m_interior_detected(false) + , m_first_interior_other_id_ptr(NULL) + , m_first_from_unknown(false) + , m_first_from_unknown_boundary_detected(false) + {} + + template + void apply(Result & res, TurnIt it, + Geometry const& geometry, + OtherGeometry const& other_geometry, + BoundaryChecker const& boundary_checker) + { + overlay::operation_type op = it->operations[op_id].operation; + + if ( op != overlay::operation_union + && op != overlay::operation_intersection + && op != overlay::operation_blocked + && op != overlay::operation_continue ) // operation_boundary / operation_boundary_intersection + { + return; + } + + segment_identifier const& seg_id = it->operations[op_id].seg_id; + segment_identifier const& other_id = it->operations[other_op_id].seg_id; + + const bool first_in_range = m_seg_watcher.update(seg_id); + + // TODO: should apply() for the post-last ip be called if first_in_range ? + // this would unify how last points in ranges are handled + // possibly replacing parts of the code below + // e.g. for is_multi and m_interior_detected + + // handle possible exit + bool fake_enter_detected = false; + if ( m_exit_watcher.get_exit_operation() == overlay::operation_union ) + { + // real exit point - may be multiple + // we know that we entered and now we exit + if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + { + m_exit_watcher.reset_detected_exit(); + + update(res); + + // next single geometry + if ( first_in_range && m_previous_turn_ptr ) + { + // NOTE: similar code is in the post-last-ip-apply() + segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; + + bool const prev_back_b = is_endpoint_on_boundary( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); + + // if there is a boundary on the last point + if ( prev_back_b ) + { + update(res); + } + } + } + // fake exit point, reset state + else if ( op == overlay::operation_intersection + || op == overlay::operation_continue ) // operation_boundary + { + m_exit_watcher.reset_detected_exit(); + fake_enter_detected = true; + } + } + else if ( m_exit_watcher.get_exit_operation() == overlay::operation_blocked ) + { + // ignore multiple BLOCKs for this same single geometry1 + if ( op == overlay::operation_blocked + && seg_id.multi_index == m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) + { + return; + } + + if ( ( op == overlay::operation_intersection + || op == overlay::operation_continue ) + && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + { + fake_enter_detected = true; + } + + m_exit_watcher.reset_detected_exit(); + } + + if ( BOOST_GEOMETRY_CONDITION( is_multi::value ) + && m_first_from_unknown ) + { + // For MultiPolygon many x/u operations may be generated as a first IP + // if for all turns x/u was generated and any of the Polygons doesn't contain the LineString + // then we know that the LineString is outside + // Similar with the u/u turns, if it was the first one it doesn't mean that the + // Linestring came from the exterior + if ( ( m_previous_operation == overlay::operation_blocked + && ( op != overlay::operation_blocked // operation different than block + || seg_id.multi_index != m_previous_turn_ptr->operations[op_id].seg_id.multi_index ) ) // or the next single-geometry + || ( m_previous_operation == overlay::operation_union + && ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + ) + { + update(res); + if ( m_first_from_unknown_boundary_detected ) + { + update(res); + } + + m_first_from_unknown = false; + m_first_from_unknown_boundary_detected = false; + } + } + +// NOTE: THE WHOLE m_interior_detected HANDLING IS HERE BECAUSE WE CAN'T EFFICIENTLY SORT TURNS (CORRECTLY) +// BECAUSE THE SAME IP MAY BE REPRESENTED BY TWO SEGMENTS WITH DIFFERENT DISTANCES +// IT WOULD REQUIRE THE CALCULATION OF MAX DISTANCE +// TODO: WE COULD GET RID OF THE TEST IF THE DISTANCES WERE NORMALIZED + +// UPDATE: THEY SHOULD BE NORMALIZED NOW + +// TODO: THIS IS POTENTIALLY ERROREOUS! +// THIS ALGORITHM DEPENDS ON SOME SPECIFIC SEQUENCE OF OPERATIONS +// IT WOULD GIVE WRONG RESULTS E.G. +// IN THE CASE OF SELF-TOUCHING POINT WHEN 'i' WOULD BE BEFORE 'u' + + // handle the interior overlap + if ( m_interior_detected ) + { + BOOST_GEOMETRY_ASSERT_MSG(m_previous_turn_ptr, "non-NULL ptr expected"); + + // real interior overlap + if ( ! turn_on_the_same_ip(*m_previous_turn_ptr, *it) ) + { + update(res); + m_interior_detected = false; + + // new range detected - reset previous state and check the boundary + if ( first_in_range ) + { + segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; + + bool const prev_back_b = is_endpoint_on_boundary( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); + + // if there is a boundary on the last point + if ( prev_back_b ) + { + update(res); + } + + // The exit_watcher is reset below + // m_exit_watcher.reset(); + } + } + // fake interior overlap + else if ( op == overlay::operation_continue ) + { + m_interior_detected = false; + } + else if ( op == overlay::operation_union ) + { +// TODO: this probably is not a good way of handling the interiors/enters +// the solution similar to exit_watcher would be more robust +// all enters should be kept and handled. +// maybe integrate it with the exit_watcher -> enter_exit_watcher + if ( m_first_interior_other_id_ptr + && m_first_interior_other_id_ptr->multi_index == other_id.multi_index ) + { + m_interior_detected = false; + } + } + } + + // NOTE: If post-last-ip apply() was called this wouldn't be needed + if ( first_in_range ) + { + m_exit_watcher.reset(); + m_boundary_counter = 0; + m_first_from_unknown = false; + m_first_from_unknown_boundary_detected = false; + } + + // i/u, c/u + if ( op == overlay::operation_intersection + || op == overlay::operation_continue ) // operation_boundary/operation_boundary_intersection + { + bool const first_point = first_in_range || m_first_from_unknown; + bool no_enters_detected = m_exit_watcher.is_outside(); + m_exit_watcher.enter(*it); + + if ( op == overlay::operation_intersection ) + { + if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear ) + --m_boundary_counter; + + if ( m_boundary_counter == 0 ) + { + // interiors overlaps + //update(res); + +// TODO: think about the implementation of the more robust version +// this way only the first enter will be handled + if ( !m_interior_detected ) + { + // don't update now + // we might enter a boundary of some other ring on the same IP + m_interior_detected = true; + m_first_interior_other_id_ptr = boost::addressof(other_id); + } + } + } + else // operation_boundary + { + // don't add to the count for all met boundaries + // only if this is the "new" boundary + if ( first_point || !it->operations[op_id].is_collinear ) + ++m_boundary_counter; + + update(res); + } + + bool const this_b + = is_ip_on_boundary(it->point, + it->operations[op_id], + boundary_checker, + seg_id); + // going inside on boundary point + if ( this_b ) + { + update(res); + } + // going inside on non-boundary point + else + { + update(res); + + // if we didn't enter in the past, we were outside + if ( no_enters_detected + && ! fake_enter_detected + && it->operations[op_id].position != overlay::position_front ) + { +// TODO: calculate_from_inside() is only needed if the current Linestring is not closed + bool const from_inside = first_point + && calculate_from_inside(geometry, + other_geometry, + *it); + + if ( from_inside ) + update(res); + else + update(res); + + // if it's the first IP then the first point is outside + if ( first_point ) + { + bool const front_b = is_endpoint_on_boundary( + range::front(sub_range(geometry, seg_id)), + boundary_checker); + + // if there is a boundary on the first point + if ( front_b ) + { + if ( from_inside ) + update(res); + else + update(res); + } + } + } + } + + if ( BOOST_GEOMETRY_CONDITION( is_multi::value ) ) + { + m_first_from_unknown = false; + m_first_from_unknown_boundary_detected = false; + } + } + // u/u, x/u + else if ( op == overlay::operation_union || op == overlay::operation_blocked ) + { + bool const op_blocked = op == overlay::operation_blocked; + bool const no_enters_detected = m_exit_watcher.is_outside() +// TODO: is this condition ok? +// TODO: move it into the exit_watcher? + && m_exit_watcher.get_exit_operation() == overlay::operation_none; + + if ( op == overlay::operation_union ) + { + if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear ) + --m_boundary_counter; + } + else // overlay::operation_blocked + { + m_boundary_counter = 0; + } + + // we're inside, possibly going out right now + if ( ! no_enters_detected ) + { + if ( op_blocked + && it->operations[op_id].position == overlay::position_back ) // ignore spikes! + { + // check if this is indeed the boundary point + // NOTE: is_ip_on_boundary<>() should be called here but the result will be the same + if ( is_endpoint_on_boundary(it->point, boundary_checker) ) + { + update(res); + } + } + // union, inside, but no exit -> collinear on self-intersection point + // not needed since we're already inside the boundary + /*else if ( !exit_detected ) + { + update(res); + }*/ + } + // we're outside or inside and this is the first turn + else + { + bool const this_b = is_ip_on_boundary(it->point, + it->operations[op_id], + boundary_checker, + seg_id); + // if current IP is on boundary of the geometry + if ( this_b ) + { + update(res); + } + // if current IP is not on boundary of the geometry + else + { + update(res); + } + + // TODO: very similar code is used in the handling of intersection + if ( it->operations[op_id].position != overlay::position_front ) + { +// TODO: calculate_from_inside() is only needed if the current Linestring is not closed + // NOTE: this is not enough for MultiPolygon and operation_blocked + // For LS/MultiPolygon multiple x/u turns may be generated + // the first checked Polygon may be the one which LS is outside for. + bool const first_point = first_in_range || m_first_from_unknown; + bool const first_from_inside = first_point + && calculate_from_inside(geometry, + other_geometry, + *it); + if ( first_from_inside ) + { + update(res); + + // notify the exit_watcher that we started inside + m_exit_watcher.enter(*it); + // and reset unknown flags since we know that we started inside + m_first_from_unknown = false; + m_first_from_unknown_boundary_detected = false; + } + else + { + if ( BOOST_GEOMETRY_CONDITION( is_multi::value ) + /*&& ( op == overlay::operation_blocked + || op == overlay::operation_union )*/ ) // if we're here it's u or x + { + m_first_from_unknown = true; + } + else + { + update(res); + } + } + + // first IP on the last segment point - this means that the first point is outside or inside + if ( first_point && ( !this_b || op_blocked ) ) + { + bool const front_b = is_endpoint_on_boundary( + range::front(sub_range(geometry, seg_id)), + boundary_checker); + + // if there is a boundary on the first point + if ( front_b ) + { + if ( first_from_inside ) + { + update(res); + } + else + { + if ( BOOST_GEOMETRY_CONDITION( is_multi::value ) + /*&& ( op == overlay::operation_blocked + || op == overlay::operation_union )*/ ) // if we're here it's u or x + { + BOOST_GEOMETRY_ASSERT(m_first_from_unknown); + m_first_from_unknown_boundary_detected = true; + } + else + { + update(res); + } + } + } + } + } + } + + // if we're going along a boundary, we exit only if the linestring was collinear + if ( m_boundary_counter == 0 + || it->operations[op_id].is_collinear ) + { + // notify the exit watcher about the possible exit + m_exit_watcher.exit(*it); + } + } + + // store ref to previously analysed (valid) turn + m_previous_turn_ptr = boost::addressof(*it); + // and previously analysed (valid) operation + m_previous_operation = op; + } + + // it == last + template + void apply(Result & res, + TurnIt first, TurnIt last, + Geometry const& geometry, + OtherGeometry const& /*other_geometry*/, + BoundaryChecker const& boundary_checker) + { + boost::ignore_unused(first, last); + //BOOST_GEOMETRY_ASSERT( first != last ); + + // For MultiPolygon many x/u operations may be generated as a first IP + // if for all turns x/u was generated and any of the Polygons doesn't contain the LineString + // then we know that the LineString is outside + if ( BOOST_GEOMETRY_CONDITION( is_multi::value ) + && m_first_from_unknown ) + { + update(res); + if ( m_first_from_unknown_boundary_detected ) + { + update(res); + } + + // done below + //m_first_from_unknown = false; + //m_first_from_unknown_boundary_detected = false; + } + + // here, the possible exit is the real one + // we know that we entered and now we exit + if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT + ||*/ m_previous_operation == overlay::operation_union + && !m_interior_detected ) + { + // for sure + update(res); + + BOOST_GEOMETRY_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr); + + segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; + + bool const prev_back_b = is_endpoint_on_boundary( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); + + // if there is a boundary on the last point + if ( prev_back_b ) + { + update(res); + } + } + // we might enter some Areal and didn't go out, + else if ( m_previous_operation == overlay::operation_intersection + || m_interior_detected ) + { + // just in case + update(res); + m_interior_detected = false; + + BOOST_GEOMETRY_ASSERT(first != last); + BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr); + + segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; + + bool const prev_back_b = is_endpoint_on_boundary( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); + + // if there is a boundary on the last point + if ( prev_back_b ) + { + update(res); + } + } + + // This condition may be false if the Linestring is lying on the Polygon's collinear spike + // if Polygon's spikes are not handled in get_turns() or relate() (they currently aren't) + //BOOST_GEOMETRY_ASSERT_MSG(m_previous_operation != overlay::operation_continue, + // "Unexpected operation! Probably the error in get_turns(L,A) or relate(L,A)"); + // Currently one c/c turn is generated for the exit + // when a Linestring is going out on a collinear spike + // When a Linestring is going in on a collinear spike + // the turn is not generated for the entry + // So assume it's the former + if ( m_previous_operation == overlay::operation_continue ) + { + update(res); + + segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id; + + bool const prev_back_b = is_endpoint_on_boundary( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); + + // if there is a boundary on the last point + if ( prev_back_b ) + { + update(res); + } + } + + // Reset exit watcher before the analysis of the next Linestring + m_exit_watcher.reset(); + m_boundary_counter = 0; + m_first_from_unknown = false; + m_first_from_unknown_boundary_detected = false; + } + + // check if the passed turn's segment of Linear geometry arrived + // from the inside or the outside of the Areal geometry + template + static inline bool calculate_from_inside(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Turn const& turn) + { + typedef typename cs_tag::type cs_tag; + + if ( turn.operations[op_id].position == overlay::position_front ) + return false; + + typename sub_range_return_type::type + range1 = sub_range(geometry1, turn.operations[op_id].seg_id); + + typedef detail::normalized_view const range2_type; + typedef typename boost::range_iterator::type range2_iterator; + range2_type range2(sub_range(geometry2, turn.operations[other_op_id].seg_id)); + + BOOST_GEOMETRY_ASSERT(boost::size(range1)); + std::size_t const s2 = boost::size(range2); + BOOST_GEOMETRY_ASSERT(s2 > 2); + std::size_t const seg_count2 = s2 - 1; + + std::size_t const p_seg_ij = static_cast(turn.operations[op_id].seg_id.segment_index); + std::size_t const q_seg_ij = static_cast(turn.operations[other_op_id].seg_id.segment_index); + + BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1)); + BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2); + + point1_type const& pi = range::at(range1, p_seg_ij); + point2_type const& qi = range::at(range2, q_seg_ij); + point2_type const& qj = range::at(range2, q_seg_ij + 1); + point1_type qi_conv; + geometry::convert(qi, qi_conv); + bool const is_ip_qj = equals::equals_point_point(turn.point, qj); +// TODO: test this! +// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi)); +// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi)); + point1_type new_pj; + geometry::convert(turn.point, new_pj); + + if ( is_ip_qj ) + { + std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2; +// TODO: the following function should return immediately, however the worst case complexity is O(N) +// It would be good to replace it with some O(1) mechanism + range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2), + range::pos(range2, q_seg_jk), + boost::end(range2)); + + // Will this sequence of points be always correct? + overlay::side_calculator side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it); + + return calculate_from_inside_sides(side_calc); + } + else + { + point1_type new_qj; + geometry::convert(turn.point, new_qj); + + overlay::side_calculator side_calc(qi_conv, new_pj, pi, qi, new_qj, qj); + + return calculate_from_inside_sides(side_calc); + } + } + + template + static inline It find_next_non_duplicated(It first, It current, It last) + { + BOOST_GEOMETRY_ASSERT( current != last ); + + It it = current; + + for ( ++it ; it != last ; ++it ) + { + if ( !equals::equals_point_point(*current, *it) ) + return it; + } + + // if not found start from the beginning + for ( it = first ; it != current ; ++it ) + { + if ( !equals::equals_point_point(*current, *it) ) + return it; + } + + return current; + } + + // calculate inside or outside based on side_calc + // this is simplified version of a check from equal<> + template + static inline bool calculate_from_inside_sides(SideCalc const& side_calc) + { + int const side_pk_p = side_calc.pk_wrt_p1(); + int const side_qk_p = side_calc.qk_wrt_p1(); + // If they turn to same side (not opposite sides) + if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p)) + { + int const side_pk_q2 = side_calc.pk_wrt_q2(); + return side_pk_q2 == -1; + } + else + { + return side_pk_p == -1; + } + } + + private: + exit_watcher m_exit_watcher; + segment_watcher m_seg_watcher; + TurnInfo * m_previous_turn_ptr; + overlay::operation_type m_previous_operation; + unsigned m_boundary_counter; + bool m_interior_detected; + const segment_identifier * m_first_interior_other_id_ptr; + bool m_first_from_unknown; + bool m_first_from_unknown_boundary_detected; + }; + + // call analyser.apply() for each turn in range + // IMPORTANT! The analyser is also called for the end iterator - last + template + static inline void analyse_each_turn(Result & res, + Analyser & analyser, + TurnIt first, TurnIt last, + Geometry const& geometry, + OtherGeometry const& other_geometry, + BoundaryChecker const& boundary_checker) + { + if ( first == last ) + return; + + for ( TurnIt it = first ; it != last ; ++it ) + { + analyser.apply(res, it, + geometry, other_geometry, + boundary_checker); + + if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) ) + return; + } + + analyser.apply(res, first, last, + geometry, other_geometry, + boundary_checker); + } + + // less comparator comparing multi_index then ring_index + // may be used to sort turns by ring + struct less_ring + { + template + inline bool operator()(Turn const& left, Turn const& right) const + { + return left.operations[1].seg_id.multi_index < right.operations[1].seg_id.multi_index + || ( left.operations[1].seg_id.multi_index == right.operations[1].seg_id.multi_index + && left.operations[1].seg_id.ring_index < right.operations[1].seg_id.ring_index ); + } + }; + + // policy/functor checking if a turn's operation is operation_continue + struct has_boundary_intersection + { + has_boundary_intersection() + : result(false) {} + + template + inline void operator()(Turn const& turn) + { + if ( turn.operations[1].operation == overlay::operation_continue ) + result = true; + } + + bool result; + }; + + // iterate through the range and search for the different multi_index or ring_index + // also call fun for each turn in the current range + template + static inline It find_next_ring(It first, It last, Fun & fun) + { + if ( first == last ) + return last; + + signed_size_type const multi_index = first->operations[1].seg_id.multi_index; + signed_size_type const ring_index = first->operations[1].seg_id.ring_index; + + fun(*first); + ++first; + + for ( ; first != last ; ++first ) + { + if ( multi_index != first->operations[1].seg_id.multi_index + || ring_index != first->operations[1].seg_id.ring_index ) + { + return first; + } + + fun(*first); + } + + return last; + } + + // analyser which called for turns sorted by seg/distance/operation + // checks if the boundary of Areal geometry really got out + // into the exterior of Linear geometry + template + class areal_boundary_analyser + { + public: + areal_boundary_analyser() + : is_union_detected(false) + , m_previous_turn_ptr(NULL) + {} + + template + bool apply(TurnIt /*first*/, TurnIt it, TurnIt last) + { + overlay::operation_type op = it->operations[1].operation; + + if ( it != last ) + { + if ( op != overlay::operation_union + && op != overlay::operation_continue ) + { + return true; + } + + if ( is_union_detected ) + { + BOOST_GEOMETRY_ASSERT(m_previous_turn_ptr != NULL); + if ( !detail::equals::equals_point_point(it->point, m_previous_turn_ptr->point) ) + { + // break + return false; + } + else if ( op == overlay::operation_continue ) // operation_boundary + { + is_union_detected = false; + } + } + + if ( op == overlay::operation_union ) + { + is_union_detected = true; + m_previous_turn_ptr = boost::addressof(*it); + } + + return true; + } + else + { + return false; + } + } + + bool is_union_detected; + + private: + const TurnInfo * m_previous_turn_ptr; + }; +}; + +template +struct areal_linear +{ + typedef linear_areal linear_areal_type; + + static const bool interruption_enabled = linear_areal_type::interruption_enabled; + + template + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + { + linear_areal_type::apply(geometry2, geometry1, result); + } +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_AREAL_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp new file mode 100755 index 0000000000..a3f82928d1 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -0,0 +1,791 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +template +class disjoint_linestring_pred +{ +public: + disjoint_linestring_pred(Result & res, + BoundaryChecker const& boundary_checker) + : m_result(res) + , m_boundary_checker(boundary_checker) + , m_flags(0) + { + if ( ! may_update(m_result) ) + { + m_flags |= 1; + } + if ( ! may_update(m_result) ) + { + m_flags |= 2; + } + } + + template + bool operator()(Linestring const& linestring) + { + if ( m_flags == 3 ) + { + return false; + } + + std::size_t const count = boost::size(linestring); + + // invalid input + if ( count < 2 ) + { + // ignore + // TODO: throw an exception? + return true; + } + + // point-like linestring + if ( count == 2 + && equals::equals_point_point(range::front(linestring), + range::back(linestring)) ) + { + update(m_result); + } + else + { + update(m_result); + m_flags |= 1; + + // check if there is a boundary + if ( m_flags < 2 + && ( m_boundary_checker.template + is_endpoint_boundary(range::front(linestring)) + || m_boundary_checker.template + is_endpoint_boundary(range::back(linestring)) ) ) + { + update(m_result); + m_flags |= 2; + } + } + + return m_flags != 3 + && ! m_result.interrupt; + } + +private: + Result & m_result; + BoundaryChecker const& m_boundary_checker; + unsigned m_flags; +}; + +template +struct linear_linear +{ + static const bool interruption_enabled = true; + + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; + + template + static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Result & result) + { + // The result should be FFFFFFFFF + relate::set::value>(result);// FFFFFFFFd, d in [1,9] or T + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + // get and analyse turns + typedef typename turns::get_turns::turn_info turn_type; + std::vector turns; + + interrupt_policy_linear_linear interrupt_policy(result); + + turns::get_turns + < + Geometry1, + Geometry2, + detail::get_turns::get_turn_info_type > + >::apply(turns, geometry1, geometry2, interrupt_policy); + + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + boundary_checker boundary_checker1(geometry1); + disjoint_linestring_pred, false> pred1(result, boundary_checker1); + for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1); + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + boundary_checker boundary_checker2(geometry2); + disjoint_linestring_pred, true> pred2(result, boundary_checker2); + for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2); + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + if ( turns.empty() ) + return; + + // TODO: turns must be sorted and followed only if it's possible to go out and in on the same point + // for linear geometries union operation must be detected which I guess would be quite often + + if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) ) + { + typedef turns::less<0, turns::less_op_linear_linear<0> > less; + std::sort(turns.begin(), turns.end(), less()); + + turns_analyser analyser; + analyse_each_turn(result, analyser, + turns.begin(), turns.end(), + geometry1, geometry2, + boundary_checker1, boundary_checker2); + } + + if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) + return; + + if ( may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) + || may_update(result) ) + { + typedef turns::less<1, turns::less_op_linear_linear<1> > less; + std::sort(turns.begin(), turns.end(), less()); + + turns_analyser analyser; + analyse_each_turn(result, analyser, + turns.begin(), turns.end(), + geometry2, geometry1, + boundary_checker2, boundary_checker1); + } + } + + template + class interrupt_policy_linear_linear + { + public: + static bool const enabled = true; + + explicit interrupt_policy_linear_linear(Result & result) + : m_result(result) + {} + +// TODO: since we update result for some operations here, we may not do it in the analyser! + + template + inline bool apply(Range const& turns) + { + typedef typename boost::range_iterator::type iterator; + + for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it) + { + if ( it->operations[0].operation == overlay::operation_intersection + || it->operations[1].operation == overlay::operation_intersection ) + { + update(m_result); + } + else if ( ( it->operations[0].operation == overlay::operation_union + || it->operations[0].operation == overlay::operation_blocked + || it->operations[1].operation == overlay::operation_union + || it->operations[1].operation == overlay::operation_blocked ) + && it->operations[0].position == overlay::position_middle + && it->operations[1].position == overlay::position_middle ) + { +// TODO: here we could also check the boundaries and set IB,BI,BB at this point + update(m_result); + } + } + + return m_result.interrupt; + } + + private: + Result & m_result; + }; + + // This analyser should be used like Input or SinglePass Iterator + template + class turns_analyser + { + typedef typename TurnInfo::point_type turn_point_type; + + static const std::size_t op_id = OpId; + static const std::size_t other_op_id = (OpId + 1) % 2; + static const bool transpose_result = OpId != 0; + + public: + turns_analyser() + : m_previous_turn_ptr(NULL) + , m_previous_operation(overlay::operation_none) + , m_degenerated_turn_ptr(NULL) + , m_collinear_spike_exit(false) + {} + + template + void apply(Result & res, TurnIt it, + Geometry const& geometry, + OtherGeometry const& other_geometry, + BoundaryChecker const& boundary_checker, + OtherBoundaryChecker const& other_boundary_checker) + { + overlay::operation_type const op = it->operations[op_id].operation; + + segment_identifier const& seg_id = it->operations[op_id].seg_id; + segment_identifier const& other_id = it->operations[other_op_id].seg_id; + + bool const first_in_range = m_seg_watcher.update(seg_id); + + if ( op != overlay::operation_union + && op != overlay::operation_intersection + && op != overlay::operation_blocked ) + { + // degenerated turn + if ( op == overlay::operation_continue + && it->method == overlay::method_none + && m_exit_watcher.is_outside(*it) + /*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none + || ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) )*/ ) + { + // TODO: rewrite the above condition + + // WARNING! For spikes the above condition may be TRUE + // When degenerated turns are be marked in a different way than c,c/c + // different condition will be checked + + handle_degenerated(res, *it, + geometry, other_geometry, + boundary_checker, other_boundary_checker, + first_in_range); + + // TODO: not elegant solution! should be rewritten. + if ( it->operations[op_id].position == overlay::position_back ) + { + m_previous_operation = overlay::operation_blocked; + m_exit_watcher.reset_detected_exit(); + } + } + + return; + } + + // reset + m_degenerated_turn_ptr = NULL; + + // handle possible exit + bool fake_enter_detected = false; + if ( m_exit_watcher.get_exit_operation() == overlay::operation_union ) + { + // real exit point - may be multiple + // we know that we entered and now we exit + if ( ! turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + { + m_exit_watcher.reset_detected_exit(); + + // not the last IP + update(res); + } + // fake exit point, reset state + else if ( op == overlay::operation_intersection ) + { + m_exit_watcher.reset_detected_exit(); + fake_enter_detected = true; + } + } + else if ( m_exit_watcher.get_exit_operation() == overlay::operation_blocked ) + { + // ignore multiple BLOCKs + if ( op == overlay::operation_blocked ) + return; + + if ( op == overlay::operation_intersection + && turn_on_the_same_ip(m_exit_watcher.get_exit_turn(), *it) ) + { + fake_enter_detected = true; + } + + m_exit_watcher.reset_detected_exit(); + } + + // i/i, i/x, i/u + if ( op == overlay::operation_intersection ) + { + bool const was_outside = m_exit_watcher.is_outside(); + m_exit_watcher.enter(*it); + + // interiors overlaps + update(res); + + bool const this_b = it->operations[op_id].position == overlay::position_front // ignore spikes! + && is_ip_on_boundary(it->point, + it->operations[op_id], + boundary_checker, + seg_id); + + // going inside on boundary point + // may be front only + if ( this_b ) + { + // may be front and back + bool const other_b = is_ip_on_boundary(it->point, + it->operations[other_op_id], + other_boundary_checker, + other_id); + + // it's also the boundary of the other geometry + if ( other_b ) + { + update(res); + } + else + { + update(res); + } + } + // going inside on non-boundary point + else + { + // if we didn't enter in the past, we were outside + if ( was_outside + && ! fake_enter_detected + && it->operations[op_id].position != overlay::position_front + && ! m_collinear_spike_exit ) + { + update(res); + + // if it's the first IP then the first point is outside + if ( first_in_range ) + { + bool const front_b = is_endpoint_on_boundary( + range::front(sub_range(geometry, seg_id)), + boundary_checker); + + // if there is a boundary on the first point + if ( front_b ) + { + update(res); + } + } + } + } + + m_collinear_spike_exit = false; + } + // u/i, u/u, u/x, x/i, x/u, x/x + else if ( op == overlay::operation_union || op == overlay::operation_blocked ) + { + // TODO: is exit watcher still needed? + // couldn't is_collinear and some going inside counter be used instead? + + bool const is_collinear = it->operations[op_id].is_collinear; + bool const was_outside = m_exit_watcher.is_outside() + && m_exit_watcher.get_exit_operation() == overlay::operation_none; +// TODO: move the above condition into the exit_watcher? + + // to exit we must be currently inside and the current segment must be collinear + if ( !was_outside && is_collinear ) + { + m_exit_watcher.exit(*it, false); + // if the position is not set to back it must be a spike + if ( it->operations[op_id].position != overlay::position_back ) + { + m_collinear_spike_exit = true; + } + } + + bool const op_blocked = op == overlay::operation_blocked; + + // we're inside and going out from inside + // possibly going out right now + if ( ! was_outside && is_collinear ) + { + if ( op_blocked + && it->operations[op_id].position == overlay::position_back ) // ignore spikes! + { + // check if this is indeed the boundary point + // NOTE: is_ip_on_boundary<>() should be called here but the result will be the same + if ( is_endpoint_on_boundary(it->point, boundary_checker) ) + { + // may be front and back + bool const other_b = is_ip_on_boundary(it->point, + it->operations[other_op_id], + other_boundary_checker, + other_id); + // it's also the boundary of the other geometry + if ( other_b ) + { + update(res); + } + else + { + update(res); + } + } + } + } + // we're outside or intersects some segment from the outside + else + { + // if we are truly outside + if ( was_outside + && it->operations[op_id].position != overlay::position_front + && ! m_collinear_spike_exit + /*&& !is_collinear*/ ) + { + update(res); + } + + // boundaries don't overlap - just an optimization + if ( it->method == overlay::method_crosses ) + { + // the L1 is going from one side of the L2 to the other through the point + update(res); + + // it's the first point in range + if ( first_in_range ) + { + bool const front_b = is_endpoint_on_boundary( + range::front(sub_range(geometry, seg_id)), + boundary_checker); + + // if there is a boundary on the first point + if ( front_b ) + { + update(res); + } + } + } + // method other than crosses, check more conditions + else + { + bool const this_b = is_ip_on_boundary(it->point, + it->operations[op_id], + boundary_checker, + seg_id); + + bool const other_b = is_ip_on_boundary(it->point, + it->operations[other_op_id], + other_boundary_checker, + other_id); + + // if current IP is on boundary of the geometry + if ( this_b ) + { + // it's also the boundary of the other geometry + if ( other_b ) + { + update(res); + } + else + { + update(res); + } + } + // if current IP is not on boundary of the geometry + else + { + // it's also the boundary of the other geometry + if ( other_b ) + { + update(res); + } + else + { + update(res); + } + } + + // first IP on the last segment point - this means that the first point is outside + if ( first_in_range + && ( !this_b || op_blocked ) + && was_outside + && it->operations[op_id].position != overlay::position_front + && ! m_collinear_spike_exit + /*&& !is_collinear*/ ) + { + bool const front_b = is_endpoint_on_boundary( + range::front(sub_range(geometry, seg_id)), + boundary_checker); + + // if there is a boundary on the first point + if ( front_b ) + { + update(res); + } + } + + } + } + } + + // store ref to previously analysed (valid) turn + m_previous_turn_ptr = boost::addressof(*it); + // and previously analysed (valid) operation + m_previous_operation = op; + } + + // Called for last + template + void apply(Result & res, + TurnIt first, TurnIt last, + Geometry const& geometry, + OtherGeometry const& /*other_geometry*/, + BoundaryChecker const& boundary_checker, + OtherBoundaryChecker const& /*other_boundary_checker*/) + { + boost::ignore_unused(first, last); + //BOOST_GEOMETRY_ASSERT( first != last ); + + // here, the possible exit is the real one + // we know that we entered and now we exit + if ( /*m_exit_watcher.get_exit_operation() == overlay::operation_union // THIS CHECK IS REDUNDANT + ||*/ m_previous_operation == overlay::operation_union + || m_degenerated_turn_ptr ) + { + update(res); + + BOOST_GEOMETRY_ASSERT(first != last); + + const TurnInfo * turn_ptr = NULL; + if ( m_degenerated_turn_ptr ) + turn_ptr = m_degenerated_turn_ptr; + else if ( m_previous_turn_ptr ) + turn_ptr = m_previous_turn_ptr; + + if ( turn_ptr ) + { + segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id; + + //BOOST_GEOMETRY_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id))); + bool const prev_back_b = is_endpoint_on_boundary( + range::back(sub_range(geometry, prev_seg_id)), + boundary_checker); + + // if there is a boundary on the last point + if ( prev_back_b ) + { + update(res); + } + } + } + + // Just in case, + // reset exit watcher before the analysis of the next Linestring + // note that if there are some enters stored there may be some error above + m_exit_watcher.reset(); + + m_previous_turn_ptr = NULL; + m_previous_operation = overlay::operation_none; + m_degenerated_turn_ptr = NULL; + + // actually if this is set to true here there is some error + // in get_turns_ll or relate_ll, an assert could be checked here + m_collinear_spike_exit = false; + } + + template + void handle_degenerated(Result & res, + Turn const& turn, + Geometry const& geometry, + OtherGeometry const& other_geometry, + BoundaryChecker const& boundary_checker, + OtherBoundaryChecker const& /*other_boundary_checker*/, + bool first_in_range) + { + typename detail::single_geometry_return_type::type + ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id); + typename detail::single_geometry_return_type::type + ls2_ref = detail::single_geometry(other_geometry, turn.operations[other_op_id].seg_id); + + // only one of those should be true: + + if ( turn.operations[op_id].position == overlay::position_front ) + { + // valid, point-sized + if ( boost::size(ls2_ref) == 2 ) + { + bool const front_b = is_endpoint_on_boundary(turn.point, boundary_checker); + + if ( front_b ) + { + update(res); + } + else + { + update(res); + } + + // operation 'c' should be last for the same IP so we know that the next point won't be the same + update(res); + + m_degenerated_turn_ptr = boost::addressof(turn); + } + } + else if ( turn.operations[op_id].position == overlay::position_back ) + { + // valid, point-sized + if ( boost::size(ls2_ref) == 2 ) + { + update(res); + + bool const back_b = is_endpoint_on_boundary(turn.point, boundary_checker); + + if ( back_b ) + { + update(res); + } + else + { + update(res); + } + + if ( first_in_range ) + { + //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref)); + bool const front_b = is_endpoint_on_boundary( + range::front(ls1_ref), boundary_checker); + if ( front_b ) + { + update(res); + } + } + } + } + else if ( turn.operations[op_id].position == overlay::position_middle + && turn.operations[other_op_id].position == overlay::position_middle ) + { + update(res); + + // here we don't know which one is degenerated + + bool const is_point1 = boost::size(ls1_ref) == 2 + && equals::equals_point_point(range::front(ls1_ref), range::back(ls1_ref)); + bool const is_point2 = boost::size(ls2_ref) == 2 + && equals::equals_point_point(range::front(ls2_ref), range::back(ls2_ref)); + + // if the second one is degenerated + if ( !is_point1 && is_point2 ) + { + update(res); + + if ( first_in_range ) + { + //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref)); + bool const front_b = is_endpoint_on_boundary( + range::front(ls1_ref), boundary_checker); + if ( front_b ) + { + update(res); + } + } + + m_degenerated_turn_ptr = boost::addressof(turn); + } + } + + // NOTE: other.position == front and other.position == back + // will be handled later, for the other geometry + } + + private: + exit_watcher m_exit_watcher; + segment_watcher m_seg_watcher; + const TurnInfo * m_previous_turn_ptr; + overlay::operation_type m_previous_operation; + const TurnInfo * m_degenerated_turn_ptr; + bool m_collinear_spike_exit; + }; + + template + static inline void analyse_each_turn(Result & res, + Analyser & analyser, + TurnIt first, TurnIt last, + Geometry const& geometry, + OtherGeometry const& other_geometry, + BoundaryChecker const& boundary_checker, + OtherBoundaryChecker const& other_boundary_checker) + { + if ( first == last ) + return; + + for ( TurnIt it = first ; it != last ; ++it ) + { + analyser.apply(res, it, + geometry, other_geometry, + boundary_checker, other_boundary_checker); + + if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) ) + return; + } + + analyser.apply(res, first, last, + geometry, other_geometry, + boundary_checker, other_boundary_checker); + } +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LINEAR_LINEAR_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp new file mode 100755 index 0000000000..29aef12373 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/point_geometry.hpp @@ -0,0 +1,208 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP + +#include +//#include +//#include + +#include +#include + +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +// non-point geometry +template +struct point_geometry +{ + // TODO: interrupt only if the topology check is complex + + static const bool interruption_enabled = true; + + template + static inline void apply(Point const& point, Geometry const& geometry, Result & result) + { + int pig = detail::within::point_in_geometry(point, geometry); + + if ( pig > 0 ) // within + { + relate::set(result); + } + else if ( pig == 0 ) + { + relate::set(result); + } + else // pig < 0 - not within + { + relate::set(result); + } + + relate::set::value, Transpose>(result); + + if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) + return; + + // the point is on the boundary + if ( pig == 0 ) + { + // NOTE: even for MLs, if there is at least one boundary point, + // somewhere there must be another one + + // check if there are other boundaries outside + typedef detail::relate::topology_check tc_t; + //tc_t tc(geometry, point); + //if ( tc.has_interior ) + relate::set(result); + //if ( tc.has_boundary ) + relate::set(result); + } + else + { + // check if there is a boundary in Geometry + typedef detail::relate::topology_check tc_t; + tc_t tc(geometry); + if ( tc.has_interior ) + relate::set(result); + if ( tc.has_boundary ) + relate::set(result); + } + } +}; + +// transposed result of point_geometry +template +struct geometry_point +{ + // TODO: interrupt only if the topology check is complex + + static const bool interruption_enabled = true; + + template + static inline void apply(Geometry const& geometry, Point const& point, Result & result) + { + point_geometry::apply(point, geometry, result); + } +}; + +// TODO: rewrite the folowing: + +//// NOTE: Those tests should be consistent with within(Point, Box) and covered_by(Point, Box) +//// There is no EPS used in those functions, values are compared using < or <= +//// so comparing MIN and MAX in the same way should be fine +// +//template ::value> +//struct box_has_interior +//{ +// static inline bool apply(Box const& box) +// { +// return geometry::get(box) < geometry::get(box) +// && box_has_interior::apply(box); +// } +//}; +// +//template +//struct box_has_interior +//{ +// static inline bool apply(Box const&) { return true; } +//}; +// +//// NOTE: especially important here (see the NOTE above). +// +//template ::value> +//struct box_has_equal_min_max +//{ +// static inline bool apply(Box const& box) +// { +// return geometry::get(box) == geometry::get(box) +// && box_has_equal_min_max::apply(box); +// } +//}; +// +//template +//struct box_has_equal_min_max +//{ +// static inline bool apply(Box const&) { return true; } +//}; +// +//template +//struct point_box +//{ +// static inline result apply(Point const& point, Box const& box) +// { +// result res; +// +// if ( geometry::within(point, box) ) // this also means that the box has interior +// { +// return result("0FFFFFTTT"); +// } +// else if ( geometry::covered_by(point, box) ) // point is on the boundary +// { +// //if ( box_has_interior::apply(box) ) +// //{ +// // return result("F0FFFFTTT"); +// //} +// //else if ( box_has_equal_min_max::apply(box) ) // no boundary outside point +// //{ +// // return result("F0FFFFFFT"); +// //} +// //else // no interior outside point +// //{ +// // return result("F0FFFFFTT"); +// //} +// return result("F0FFFF**T"); +// } +// else +// { +// /*if ( box_has_interior::apply(box) ) +// { +// return result("FF0FFFTTT"); +// } +// else +// { +// return result("FF0FFFFTT"); +// }*/ +// return result("FF0FFF*TT"); +// } +// +// return res; +// } +//}; +// +//template +//struct box_point +//{ +// static inline result apply(Box const& box, Point const& point) +// { +// if ( geometry::within(point, box) ) +// return result("0FTFFTFFT"); +// else if ( geometry::covered_by(point, box) ) +// return result("FF*0F*FFT"); +// else +// return result("FF*FFT0FT"); +// } +//}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/point_point.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/point_point.hpp new file mode 100755 index 0000000000..1c609f4773 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/point_point.hpp @@ -0,0 +1,245 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014. +// Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP + +#include +#include + +#include + +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +template +struct point_point +{ + static const bool interruption_enabled = false; + + template + static inline void apply(Point1 const& point1, Point2 const& point2, Result & result) + { + bool equal = detail::equals::equals_point_point(point1, point2); + if ( equal ) + { + relate::set(result); + } + else + { + relate::set(result); + relate::set(result); + } + + relate::set::value>(result); + } +}; + +template +std::pair point_multipoint_check(Point const& point, MultiPoint const& multi_point) +{ + bool found_inside = false; + bool found_outside = false; + + // point_in_geometry could be used here but why iterate over MultiPoint twice? + // we must search for a point in the exterior because all points in MultiPoint can be equal + + typedef typename boost::range_iterator::type iterator; + iterator it = boost::begin(multi_point); + iterator last = boost::end(multi_point); + for ( ; it != last ; ++it ) + { + bool ii = detail::equals::equals_point_point(point, *it); + + if ( ii ) + found_inside = true; + else + found_outside = true; + + if ( found_inside && found_outside ) + break; + } + + return std::make_pair(found_inside, found_outside); +} + +template +struct point_multipoint +{ + static const bool interruption_enabled = false; + + template + static inline void apply(Point const& point, MultiPoint const& multi_point, Result & result) + { + if ( boost::empty(multi_point) ) + { + // TODO: throw on empty input? + relate::set(result); + return; + } + + std::pair rel = point_multipoint_check(point, multi_point); + + if ( rel.first ) // some point of MP is equal to P + { + relate::set(result); + + if ( rel.second ) // a point of MP was found outside P + { + relate::set(result); + } + } + else + { + relate::set(result); + relate::set(result); + } + + relate::set::value, Transpose>(result); + } +}; + +template +struct multipoint_point +{ + static const bool interruption_enabled = false; + + template + static inline void apply(MultiPoint const& multi_point, Point const& point, Result & result) + { + point_multipoint::apply(point, multi_point, result); + } +}; + +template +struct multipoint_multipoint +{ + static const bool interruption_enabled = true; + + template + static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2, Result & result) + { + { + // TODO: throw on empty input? + bool empty1 = boost::empty(multi_point1); + bool empty2 = boost::empty(multi_point2); + if ( empty1 && empty2 ) + { + return; + } + else if ( empty1 ) + { + relate::set(result); + return; + } + else if ( empty2 ) + { + relate::set(result); + return; + } + } + +// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED + +// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed +// so if e.g. only I/I must be analysed we musn't check the other MPt + +// TODO: Also, the geometry with the smaller number of points may be analysed first + //if ( boost::size(multi_point1) < boost::size(multi_point2) ) + + // NlogN + MlogN + bool all_handled = search(multi_point1, multi_point2, result); + + if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) ) + return; + + // MlogM + NlogM + search(multi_point2, multi_point1, result); + } + + template + static inline bool search(SortedMultiPoint const& sorted_mpt, + IteratedMultiPoint const& iterated_mpt, + Result & result) + { + // sort points from the 1 MPt + typedef typename geometry::point_type::type point_type; + std::vector points(boost::begin(sorted_mpt), boost::end(sorted_mpt)); + std::sort(points.begin(), points.end(), less()); + + bool found_inside = false; + bool found_outside = false; + + // for each point in the second MPt + typedef typename boost::range_iterator::type iterator; + for ( iterator it = boost::begin(iterated_mpt) ; + it != boost::end(iterated_mpt) ; ++it ) + { + bool ii = + std::binary_search(points.begin(), points.end(), *it, less()); + if ( ii ) + found_inside = true; + else + found_outside = true; + + if ( found_inside && found_outside ) + break; + } + + // an optimization + bool all_handled = false; + + if ( found_inside ) // some point of MP2 is equal to some of MP1 + { +// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed +// so if e.g. only I/I must be analysed we musn't check the other MPt + + relate::set(result); + + if ( found_outside ) // some point of MP2 was found outside of MP1 + { + relate::set(result); + } + } + else + { + relate::set(result); + relate::set(result); + + // if no point is intersecting the other MPt then we musn't analyse the reversed case + all_handled = true; + } + + relate::set::value, Transpose>(result); + + return all_handled; + } +}; + +}} // namespace detail::relate +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP diff --git a/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/relate_impl.hpp b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/relate_impl.hpp new file mode 100755 index 0000000000..309d3055d0 --- /dev/null +++ b/bundled/boost-1.62.0/include/boost/geometry/algorithms/detail/relate/relate_impl.hpp @@ -0,0 +1,80 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// This file was modified by Oracle on 2013, 2014, 2015. +// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_RELATE_IMPL_HPP + +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace geometry { + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace relate { + +struct implemented_tag {}; + +template