stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -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 <boost/range.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/variant.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace append
{
template <typename Geometry, typename Point>
struct append_no_action
{
static inline void apply(Geometry& , Point const& ,
int = 0, int = 0)
{
}
};
template <typename Geometry, typename Point>
struct append_point
{
static inline void apply(Geometry& geometry, Point const& point,
int = 0, int = 0)
{
typename geometry::point_type<Geometry>::type copy;
geometry::detail::conversion::convert_point_to_point(point, copy);
traits::push_back<Geometry>::apply(geometry, copy);
}
};
template <typename Geometry, typename Range>
struct append_range
{
typedef typename boost::range_value<Range>::type point_type;
static inline void apply(Geometry& geometry, Range const& range,
int = 0, int = 0)
{
for (typename boost::range_iterator<Range const>::type
it = boost::begin(range);
it != boost::end(range);
++it)
{
append_point<Geometry, point_type>::apply(geometry, *it);
}
}
};
template <typename Polygon, typename Point>
struct point_to_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
static inline void apply(Polygon& polygon, Point const& point,
int ring_index, int = 0)
{
if (ring_index == -1)
{
append_point<ring_type, Point>::apply(
exterior_ring(polygon), point);
}
else if (ring_index < int(num_interior_rings(polygon)))
{
append_point<ring_type, Point>::apply(
range::at(interior_rings(polygon), ring_index), point);
}
}
};
template <typename Polygon, typename Range>
struct range_to_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
static inline void apply(Polygon& polygon, Range const& range,
int ring_index, int = 0)
{
if (ring_index == -1)
{
append_range<ring_type, Range>::apply(
exterior_ring(polygon), range);
}
else if (ring_index < int(num_interior_rings(polygon)))
{
append_range<ring_type, 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 <typename Tag, typename Geometry, typename Point>
struct append_point
: detail::append::append_no_action<Geometry, Point>
{};
template <typename Geometry, typename Point>
struct append_point<linestring_tag, Geometry, Point>
: detail::append::append_point<Geometry, Point>
{};
template <typename Geometry, typename Point>
struct append_point<ring_tag, Geometry, Point>
: detail::append::append_point<Geometry, Point>
{};
template <typename Polygon, typename Point>
struct append_point<polygon_tag, Polygon, Point>
: detail::append::point_to_polygon<Polygon, Point>
{};
template <typename Tag, typename Geometry, typename Range>
struct append_range
: detail::append::append_no_action<Geometry, Range>
{};
template <typename Geometry, typename Range>
struct append_range<linestring_tag, Geometry, Range>
: detail::append::append_range<Geometry, Range>
{};
template <typename Geometry, typename Range>
struct append_range<ring_tag, Geometry, Range>
: detail::append::append_range<Geometry, Range>
{};
template <typename Polygon, typename Range>
struct append_range<polygon_tag, Polygon, Range>
: detail::append::range_to_polygon<Polygon, Range>
{};
} // 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<RangeOrPoint>::type
>
struct append
: splitted_dispatch::append_range<typename tag<Geometry>::type, Geometry, RangeOrPoint>
{};
// Specialization for point to append a point to any geometry
template <typename Geometry, typename RangeOrPoint>
struct append<Geometry, RangeOrPoint, point_tag>
: splitted_dispatch::append_point<typename tag<Geometry>::type, Geometry, RangeOrPoint>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace append
{
template <typename MultiGeometry, typename RangeOrPoint>
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<MultiGeometry>::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 <typename Geometry, typename Point>
struct append_point<multi_point_tag, Geometry, Point>
: detail::append::append_point<Geometry, Point>
{};
template <typename Geometry, typename Range>
struct append_range<multi_point_tag, Geometry, Range>
: detail::append::append_range<Geometry, Range>
{};
template <typename MultiGeometry, typename RangeOrPoint>
struct append_point<multi_linestring_tag, MultiGeometry, RangeOrPoint>
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
{};
template <typename MultiGeometry, typename RangeOrPoint>
struct append_range<multi_linestring_tag, MultiGeometry, RangeOrPoint>
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
{};
template <typename MultiGeometry, typename RangeOrPoint>
struct append_point<multi_polygon_tag, MultiGeometry, RangeOrPoint>
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
{};
template <typename MultiGeometry, typename RangeOrPoint>
struct append_range<multi_polygon_tag, MultiGeometry, RangeOrPoint>
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
{};
} // namespace splitted_dispatch
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
template <typename Geometry>
struct append
{
template <typename RangeOrPoint>
static inline void apply(Geometry& geometry,
RangeOrPoint const& range_or_point,
int ring_index,
int multi_index)
{
concepts::check<Geometry>();
dispatch::append<Geometry, RangeOrPoint>::apply(geometry,
range_or_point,
ring_index,
multi_index);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename RangeOrPoint>
struct visitor: boost::static_visitor<void>
{
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 <typename Geometry>
void operator()(Geometry& geometry) const
{
append<Geometry>::apply(geometry,
m_range_or_point,
m_ring_index,
m_multi_index);
}
};
template <typename RangeOrPoint>
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& variant_geometry,
RangeOrPoint const& range_or_point,
int ring_index,
int multi_index)
{
boost::apply_visitor(
visitor<RangeOrPoint>(
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 <typename Geometry, typename RangeOrPoint>
inline void append(Geometry& geometry, RangeOrPoint const& range_or_point,
int ring_index = -1, int multi_index = 0)
{
resolve_variant::append<Geometry>
::apply(geometry, range_or_point, ring_index, multi_index);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
@@ -0,0 +1,329 @@
// 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 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// 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_AREA_HPP
#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
#include <boost/concept_check.hpp>
#include <boost/mpl/if.hpp>
#include <boost/range/functions.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/calculate_null.hpp>
#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
#include <boost/geometry/algorithms/detail/multi_sum.hpp>
#include <boost/geometry/strategies/area.hpp>
#include <boost/geometry/strategies/default_area_result.hpp>
#include <boost/geometry/strategies/concepts/area_concept.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/views/reversible_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace area
{
struct box_area
{
template <typename Box, typename Strategy>
static inline typename coordinate_type<Box>::type
apply(Box const& box, Strategy const&)
{
// Currently only works for 2D Cartesian boxes
assert_dimension<Box, 2>();
return (get<max_corner, 0>(box) - get<min_corner, 0>(box))
* (get<max_corner, 1>(box) - get<min_corner, 1>(box));
}
};
template
<
iterate_direction Direction,
closure_selector Closure
>
struct ring_area
{
template <typename Ring, typename Strategy>
static inline typename Strategy::return_type
apply(Ring const& ring, Strategy const& strategy)
{
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Strategy>) );
assert_dimension<Ring, 2>();
// 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<Closure>::value)
{
return typename Strategy::return_type();
}
typedef typename reversible_view<Ring const, Direction>::type rview_type;
typedef typename closeable_view
<
rview_type const, Closure
>::type view_type;
typedef typename boost::range_iterator<view_type const>::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<Geometry>::type
>
struct area : detail::calculate_null
{
template <typename Strategy>
static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
{
return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
}
};
template <typename Geometry>
struct area<Geometry, box_tag> : detail::area::box_area
{};
template <typename Ring>
struct area<Ring, ring_tag>
: detail::area::ring_area
<
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value
>
{};
template <typename Polygon>
struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
{
template <typename Strategy>
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<geometry::point_order<Polygon>::value>::value,
geometry::closure<Polygon>::value
>
>(polygon, strategy);
}
};
template <typename MultiGeometry>
struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
{
template <typename Strategy>
static inline typename Strategy::return_type
apply(MultiGeometry const& multi, Strategy const& strategy)
{
return multi_sum::apply
<
typename Strategy::return_type,
area<typename boost::range_value<MultiGeometry>::type>
>(multi, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
template <typename Geometry>
struct area
{
template <typename Strategy>
static inline typename Strategy::return_type apply(Geometry const& geometry,
Strategy const& strategy)
{
return dispatch::area<Geometry>::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<typename Strategy::return_type>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
typename Strategy::return_type operator()(Geometry const& geometry) const
{
return area<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline typename Strategy::return_type
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(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 <typename Geometry>
inline typename default_area_result<Geometry>::type area(Geometry const& geometry)
{
concepts::check<Geometry const>();
// TODO put this into a resolve_strategy stage
// (and take the return type from resolve_variant)
typedef typename point_type<Geometry>::type point_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type,
point_type
>::type strategy_type;
// detail::throw_on_empty_input(geometry);
return resolve_variant::area<Geometry>::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_spherical Spherical]
[/link geometry.reference.strategies.strategy_area_geographic Geographic]
}
*/
template <typename Geometry, typename Strategy>
inline typename Strategy::return_type area(
Geometry const& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
// detail::throw_on_empty_input(geometry);
return resolve_variant::area<Geometry>::apply(geometry, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_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 <cstddef>
#include <boost/concept/requires.hpp>
#include <boost/concept_check.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
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 <typename Geometry, typename Range>
inline void assign_points(Geometry& geometry, Range const& range)
{
concepts::check<Geometry>();
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 <typename Geometry>
inline void assign_inverse(Geometry& geometry)
{
concepts::check<Geometry>();
dispatch::assign_inverse
<
typename tag<Geometry>::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 <typename Geometry>
inline void assign_zero(Geometry& geometry)
{
concepts::check<Geometry>();
dispatch::assign_zero
<
typename tag<Geometry>::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 <typename Geometry, typename Type>
inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
{
concepts::check<Geometry>();
dispatch::assign
<
typename tag<Geometry>::type,
Geometry,
geometry::dimension<Geometry>::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 <typename Geometry, typename Type>
inline void assign_values(Geometry& geometry,
Type const& c1, Type const& c2, Type const& c3)
{
concepts::check<Geometry>();
dispatch::assign
<
typename tag<Geometry>::type,
Geometry,
geometry::dimension<Geometry>::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 <typename Geometry, typename Type>
inline void assign_values(Geometry& geometry,
Type const& c1, Type const& c2, Type const& c3, Type const& c4)
{
concepts::check<Geometry>();
dispatch::assign
<
typename tag<Geometry>::type,
Geometry,
geometry::dimension<Geometry>::type::value
>::apply(geometry, c1, c2, c3, c4);
}
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct assign
{
static inline void
apply(Geometry1& geometry1, const Geometry2& geometry2)
{
concepts::check<Geometry1>();
concepts::check<Geometry2 const>();
concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
static bool const same_point_order
= point_order<Geometry1>::value == point_order<Geometry2>::value;
BOOST_MPL_ASSERT_MSG
(
(same_point_order),
ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER,
(types<Geometry1, Geometry2>)
);
static bool const same_closure
= closure<Geometry1>::value == closure<Geometry2>::value;
BOOST_MPL_ASSERT_MSG
(
(same_closure),
ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE,
(types<Geometry1, Geometry2>)
);
dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
struct visitor: static_visitor<void>
{
Geometry2 const& m_geometry2;
visitor(Geometry2 const& geometry2)
: m_geometry2(geometry2)
{}
template <typename Geometry1>
result_type operator()(Geometry1& geometry1) const
{
return assign
<
Geometry1,
Geometry2
>::apply
(geometry1, m_geometry2);
}
};
static inline void
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
Geometry2 const& geometry2)
{
return boost::apply_visitor(visitor(geometry2), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: static_visitor<void>
{
Geometry1& m_geometry1;
visitor(Geometry1 const& geometry1)
: m_geometry1(geometry1)
{}
template <typename Geometry2>
result_type operator()(Geometry2 const& geometry2) const
{
return assign
<
Geometry1,
Geometry2
>::apply
(m_geometry1, geometry2);
}
};
static inline void
apply(Geometry1& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
{
return boost::apply_visitor(visitor(geometry1), geometry2);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
struct visitor: static_visitor<void>
{
template <typename Geometry1, typename Geometry2>
result_type operator()(
Geometry1& geometry1,
Geometry2 const& geometry2) const
{
return assign
<
Geometry1,
Geometry2
>::apply
(geometry1, geometry2);
}
};
static inline void
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> 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 <typename Geometry1, typename Geometry2>
inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)
{
resolve_variant::assign<Geometry1, Geometry2>::apply(geometry1, geometry2);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
@@ -0,0 +1,302 @@
// 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 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// 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_BUFFER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
#include <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
struct box_loop
{
typedef typename coordinate_type<BoxOut>::type coordinate_type;
static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
{
coordinate_type d = distance;
set<C, D>(box_out, get<C, D>(box_in) + d);
box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
}
};
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
struct box_loop<BoxIn, BoxOut, T, C, N, N>
{
static inline void apply(BoxIn const&, T const&, BoxOut&) {}
};
// Extends a box with the same amount in all directions
template<typename BoxIn, typename BoxOut, typename T>
inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
{
assert_dimension_equal<BoxIn, BoxOut>();
static const std::size_t N = dimension<BoxIn>::value;
box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::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<Input>::type,
typename TagOut = typename tag<Output>::type
>
struct buffer: not_implemented<TagIn, TagOut>
{};
template <typename BoxIn, typename BoxOut>
struct buffer<BoxIn, BoxOut, box_tag, box_tag>
{
template <typename Distance>
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 <typename Geometry>
struct buffer
{
template <typename Distance, typename GeometryOut>
static inline void apply(Geometry const& geometry,
Distance const& distance,
Distance const& chord_length,
GeometryOut& out)
{
dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Distance, typename GeometryOut>
struct visitor: boost::static_visitor<void>
{
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 <typename Geometry>
void operator()(Geometry const& geometry) const
{
buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
}
};
template <typename Distance, typename GeometryOut>
static inline void apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Distance const& distance,
Distance const& chord_length,
GeometryOut& out
)
{
boost::apply_visitor(visitor<Distance, GeometryOut>(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 <typename Input, typename Output, typename Distance>
inline void buffer(Input const& geometry_in, Output& geometry_out,
Distance const& distance, Distance const& chord_length = -1)
{
concepts::check<Input const>();
concepts::check<Output>();
resolve_variant::buffer<Input>::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 <typename Output, typename Input, typename Distance>
Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
{
concepts::check<Input const>();
concepts::check<Output>();
Output geometry_out;
resolve_variant::buffer<Input>::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<MultiPolygon>::type polygon_type;
concepts::check<GeometryIn const>();
concepts::check<polygon_type>();
typedef typename point_type<GeometryIn>::type point_type;
typedef typename rescale_policy_type<point_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<point_type> box;
geometry::envelope(geometry_in, box);
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
typename strategy::intersection::services::default_strategy
<
typename cs_tag<GeometryIn>::type
>::type intersection_strategy;
rescale_policy_type rescale_policy
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
distance_strategy,
side_strategy,
join_strategy,
end_strategy,
point_strategy,
intersection_strategy,
rescale_policy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
@@ -0,0 +1,681 @@
// 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-2017 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 <cstddef>
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/throw_exception.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/concepts/centroid_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
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<typename Point, typename PointCentroid, typename Strategy>
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<Indexed>::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<min_corner, Dimension>(indexed);
coordinate_type const c2 = get<max_corner, Dimension>(indexed);
coordinate_type m = c1 + c2;
coordinate_type const two = 2;
m /= two;
set<Dimension>(centroid, m);
centroid_indexed_calculator
<
Indexed, Point, Dimension + 1
>::apply(indexed, centroid);
}
};
template<typename Indexed, typename Point, std::size_t DimensionCount>
struct centroid_indexed_calculator<Indexed, Point, DimensionCount, DimensionCount>
{
static inline void apply(Indexed const& , Point& )
{
}
};
struct centroid_indexed
{
template<typename Indexed, typename Point, typename Strategy>
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<typename Point, typename Range>
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)
BOOST_THROW_EXCEPTION(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 <closure_selector Closure>
struct centroid_range_state
{
template<typename Ring, typename PointTransformer, typename Strategy>
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<Ring const>::type point_type;
typedef typename closeable_view<Ring const, Closure>::type view_type;
typedef typename boost::range_iterator<view_type const>::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<point_type const&>(previous_pt),
static_cast<point_type const&>(pt),
state);
previous_pt = pt;
}
}
}
};
template <closure_selector Closure>
struct centroid_range
{
template<typename Range, typename Point, typename Strategy>
static inline bool apply(Range const& range, Point& centroid,
Strategy const& strategy)
{
if (range_ok(range, centroid))
{
// prepare translation transformer
translating_transformer<Range> transformer(*boost::begin(range));
typename Strategy::state_type state;
centroid_range_state<Closure>::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<typename Polygon, typename PointTransformer, typename Strategy>
static inline void apply(Polygon const& poly,
PointTransformer const& transformer,
Strategy const& strategy,
typename Strategy::state_type& state)
{
typedef typename ring_type<Polygon>::type ring_type;
typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;
per_ring::apply(exterior_ring(poly), transformer, strategy, state);
typename interior_return_type<Polygon const>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_ring::apply(*it, transformer, strategy, state);
}
}
};
struct centroid_polygon
{
template<typename Polygon, typename Point, typename Strategy>
static inline bool apply(Polygon const& poly, Point& centroid,
Strategy const& strategy)
{
if (range_ok(exterior_ring(poly), centroid))
{
// prepare translation transformer
translating_transformer<Polygon>
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 <typename Point, typename PointTransformer, typename Strategy>
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<Point const&>(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 <typename Policy>
struct centroid_multi
{
template <typename Multi, typename Point, typename Strategy>
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))
{
BOOST_THROW_EXCEPTION(centroid_exception());
}
#endif
// prepare translation transformer
translating_transformer<Multi> transformer(multi);
typename Strategy::state_type state;
for (typename boost::range_iterator<Multi const>::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 <typename Algorithm>
struct centroid_linear_areal
{
template <typename Geometry, typename Point, typename Strategy>
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<Geometry>::type
>
struct centroid: not_implemented<Tag>
{};
template <typename Geometry>
struct centroid<Geometry, point_tag>
: detail::centroid::centroid_point
{};
template <typename Box>
struct centroid<Box, box_tag>
: detail::centroid::centroid_indexed
{};
template <typename Segment>
struct centroid<Segment, segment_tag>
: detail::centroid::centroid_indexed
{};
template <typename Ring>
struct centroid<Ring, ring_tag>
: detail::centroid::centroid_linear_areal
<
detail::centroid::centroid_range<geometry::closure<Ring>::value>
>
{};
template <typename Linestring>
struct centroid<Linestring, linestring_tag>
: detail::centroid::centroid_linear_areal
<
detail::centroid::centroid_range<closed>
>
{};
template <typename Polygon>
struct centroid<Polygon, polygon_tag>
: detail::centroid::centroid_linear_areal
<
detail::centroid::centroid_polygon
>
{};
template <typename MultiLinestring>
struct centroid<MultiLinestring, multi_linestring_tag>
: detail::centroid::centroid_linear_areal
<
detail::centroid::centroid_multi
<
detail::centroid::centroid_range_state<closed>
>
>
{};
template <typename MultiPolygon>
struct centroid<MultiPolygon, multi_polygon_tag>
: detail::centroid::centroid_linear_areal
<
detail::centroid::centroid_multi
<
detail::centroid::centroid_polygon_state
>
>
{};
template <typename MultiPoint>
struct centroid<MultiPoint, multi_point_tag>
: detail::centroid::centroid_multi
<
detail::centroid::centroid_multi_point_state
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy {
template <typename Geometry>
struct centroid
{
template <typename Point, typename Strategy>
static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
{
dispatch::centroid<Geometry>::apply(geometry, out, strategy);
}
template <typename Point>
static inline void apply(Geometry const& geometry, Point& out, default_strategy)
{
typedef typename strategy::centroid::services::default_strategy
<
typename cs_tag<Geometry>::type,
typename tag_cast
<
typename tag<Geometry>::type,
pointlike_tag,
linear_tag,
areal_tag
>::type,
dimension<Geometry>::type::value,
Point,
Geometry
>::type strategy_type;
dispatch::centroid<Geometry>::apply(geometry, out, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry>
struct centroid
{
template <typename Point, typename Strategy>
static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions<Point, Geometry const>();
resolve_strategy::centroid<Geometry>::apply(geometry, out, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Point, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Point& m_out;
Strategy const& m_strategy;
visitor(Point& out, Strategy const& strategy)
: m_out(out), m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
centroid<Geometry>::apply(geometry, m_out, m_strategy);
}
};
template <typename Point, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Point& out,
Strategy const& strategy)
{
boost::apply_visitor(visitor<Point, Strategy>(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<typename Geometry, typename Point, typename Strategy>
inline void centroid(Geometry const& geometry, Point& c,
Strategy const& strategy)
{
resolve_variant::centroid<Geometry>::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<typename Geometry, typename Point>
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<typename Point, typename Geometry>
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<typename Point, typename Geometry, typename Strategy>
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
@@ -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 <boost/type_traits/remove_const.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace clear
{
template <typename Geometry>
struct collection_clear
{
static inline void apply(Geometry& geometry)
{
traits::clear<Geometry>::apply(geometry);
}
};
template <typename Polygon>
struct polygon_clear
{
static inline void apply(Polygon& polygon)
{
traits::clear
<
typename boost::remove_reference
<
typename traits::interior_mutable_type<Polygon>::type
>::type
>::apply(interior_rings(polygon));
traits::clear
<
typename boost::remove_reference
<
typename traits::ring_mutable_type<Polygon>::type
>::type
>::apply(exterior_ring(polygon));
}
};
template <typename Geometry>
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<typename tag<Geometry>::type, multi_tag>::type
>
struct clear: not_implemented<Tag>
{};
// Point/box/segment do not have clear. So specialize to do nothing.
template <typename Geometry>
struct clear<Geometry, point_tag>
: detail::clear::no_action<Geometry>
{};
template <typename Geometry>
struct clear<Geometry, box_tag>
: detail::clear::no_action<Geometry>
{};
template <typename Geometry>
struct clear<Geometry, segment_tag>
: detail::clear::no_action<Geometry>
{};
template <typename Geometry>
struct clear<Geometry, linestring_tag>
: detail::clear::collection_clear<Geometry>
{};
template <typename Geometry>
struct clear<Geometry, ring_tag>
: detail::clear::collection_clear<Geometry>
{};
// Polygon can (indirectly) use std for clear
template <typename Polygon>
struct clear<Polygon, polygon_tag>
: detail::clear::polygon_clear<Polygon>
{};
template <typename Geometry>
struct clear<Geometry, multi_tag>
: detail::clear::collection_clear<Geometry>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
template <typename Geometry>
struct clear
{
static inline void apply(Geometry& geometry)
{
dispatch::clear<Geometry>::apply(geometry);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct clear<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: static_visitor<void>
{
template <typename Geometry>
inline void operator()(Geometry& geometry) const
{
clear<Geometry>::apply(geometry);
}
};
static inline void apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& 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 <typename Geometry>
inline void clear(Geometry& geometry)
{
concepts::check<Geometry>();
resolve_variant::clear<Geometry>::apply(geometry);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_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 <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_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 <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/for_each.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
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<Box>::type coordinate_type;
set<Index, Dimension>(box,
boost::numeric_cast<coordinate_type>(get<Dimension>(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<Point, Box, Index, DimensionCount, DimensionCount>
{
static inline void apply(Point const& , Box& )
{}
};
template <typename Box, typename Range, bool Close, bool Reverse>
struct box_to_range
{
static inline void apply(Box const& box, Range& range)
{
traits::resize<Range>::apply(range, Close ? 5 : 4);
assign_box_corners_oriented<Reverse>(box, range);
if (Close)
{
range::at(range, 4) = range::at(range, 0);
}
}
};
template <typename Segment, typename Range>
struct segment_to_range
{
static inline void apply(Segment const& segment, Range& range)
{
traits::resize<Range>::apply(range, 2);
typename boost::range_iterator<Range>::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<Range1>::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<Range1>::type size_type;
size_type n = boost::size(view);
if (geometry::closure<Range2>::value == geometry::open)
{
n--;
}
// If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()
// but ok, sice below it == end()
size_type i = 0;
for (typename boost::range_iterator<view_type const>::type it
= boost::begin(view);
it != boost::end(view) && i < n;
++it, ++i)
{
geometry::append(destination, *it);
}
}
};
template <typename Polygon1, typename Polygon2>
struct polygon_to_polygon
{
typedef range_to_range
<
typename geometry::ring_type<Polygon1>::type,
typename geometry::ring_type<Polygon2>::type,
geometry::point_order<Polygon1>::value
!= geometry::point_order<Polygon2>::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<Polygon2>::type
>::type
>::apply(interior_rings(destination), num_interior_rings(source));
typename interior_return_type<Polygon1 const>::type
rings_source = interior_rings(source);
typename interior_return_type<Polygon2>::type
rings_dest = interior_rings(destination);
typename detail::interior_iterator<Polygon1 const>::type
it_source = boost::begin(rings_source);
typename detail::interior_iterator<Polygon2>::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 <typename Single, typename Multi, typename Policy>
struct single_to_multi: private Policy
{
static inline void apply(Single const& single, Multi& multi)
{
traits::resize<Multi>::apply(multi, 1);
Policy::apply(single, *boost::begin(multi));
}
};
template <typename Multi1, typename Multi2, typename Policy>
struct multi_to_multi: private Policy
{
static inline void apply(Multi1 const& multi1, Multi2& multi2)
{
traits::resize<Multi2>::apply(multi2, boost::size(multi1));
typename boost::range_iterator<Multi1 const>::type it1
= boost::begin(multi1);
typename boost::range_iterator<Multi2>::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<typename tag<Geometry1>::type, multi_tag>::type,
typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value
&& !boost::is_array<Geometry1>::value
>
struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >
{};
template
<
typename Geometry1, typename Geometry2,
typename Tag,
std::size_t DimensionCount
>
struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
{
// 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<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
: detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
{};
template
<
typename Box1, typename Box2,
std::size_t DimensionCount
>
struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
: detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
{};
template
<
typename Segment1, typename Segment2,
std::size_t DimensionCount
>
struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
: detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
{};
template <typename Segment, typename LineString, std::size_t DimensionCount>
struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
: detail::conversion::segment_to_range<Segment, LineString>
{};
template <typename Ring1, typename Ring2, std::size_t DimensionCount>
struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
: detail::conversion::range_to_range
<
Ring1,
Ring2,
geometry::point_order<Ring1>::value
!= geometry::point_order<Ring2>::value
>
{};
template <typename LineString1, typename LineString2, std::size_t DimensionCount>
struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
: detail::conversion::range_to_range<LineString1, LineString2>
{};
template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
: detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
{};
template <typename Box, typename Ring>
struct convert<Box, Ring, box_tag, ring_tag, 2, false>
: detail::conversion::box_to_range
<
Box,
Ring,
geometry::closure<Ring>::value == closed,
geometry::point_order<Ring>::value == counterclockwise
>
{};
template <typename Box, typename Polygon>
struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
{
static inline void apply(Box const& box, Polygon& polygon)
{
typedef typename ring_type<Polygon>::type ring_type;
convert
<
Box, ring_type,
box_tag, ring_tag,
2, false
>::apply(box, exterior_ring(polygon));
}
};
template <typename Point, typename Box, std::size_t DimensionCount>
struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
{
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 <typename Ring, typename Polygon, std::size_t DimensionCount>
struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
{
static inline void apply(Ring const& ring, Polygon& polygon)
{
typedef typename ring_type<Polygon>::type ring_type;
convert
<
Ring, ring_type,
ring_tag, ring_tag,
DimensionCount, false
>::apply(ring, exterior_ring(polygon));
}
};
template <typename Polygon, typename Ring, std::size_t DimensionCount>
struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
{
static inline void apply(Polygon const& polygon, Ring& ring)
{
typedef typename ring_type<Polygon>::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 <typename Multi1, typename Multi2, std::size_t DimensionCount>
struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
: detail::conversion::multi_to_multi
<
Multi1,
Multi2,
convert
<
typename boost::range_value<Multi1>::type,
typename boost::range_value<Multi2>::type,
typename single_tag_of
<
typename tag<Multi1>::type
>::type,
typename single_tag_of
<
typename tag<Multi2>::type
>::type,
DimensionCount
>
>
{};
template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>
struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>
: detail::conversion::single_to_multi
<
Single,
Multi,
convert
<
Single,
typename boost::range_value<Multi>::type,
typename tag<Single>::type,
typename single_tag_of
<
typename tag<Multi>::type
>::type,
DimensionCount,
false
>
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct convert
{
static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
{
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
struct visitor: static_visitor<void>
{
Geometry2& m_geometry2;
visitor(Geometry2& geometry2)
: m_geometry2(geometry2)
{}
template <typename Geometry1>
inline void operator()(Geometry1 const& geometry1) const
{
convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
}
};
static inline void apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> 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 <typename Geometry1, typename Geometry2>
inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
{
resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_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 <boost/array.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/convex_hull.hpp>
#include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/as_range.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace convex_hull
{
template <order_selector Order, closure_selector Closure>
struct hull_insert
{
// Member template function (to avoid inconvenient declaration
// of output-iterator-type, from hull_to_geometry)
template <typename Geometry, typename OutputIterator, typename Strategy>
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 <typename Geometry, typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry, OutputGeometry& out,
Strategy const& strategy)
{
hull_insert
<
geometry::point_order<OutputGeometry>::value,
geometry::closure<OutputGeometry>::value
>::apply(geometry,
range::back_inserter(
// Handle linestring, ring and polygon the same:
detail::as_range
<
typename range_type<OutputGeometry>::type
>(out)), strategy);
}
};
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct convex_hull
: detail::convex_hull::hull_to_geometry
{};
template <typename Box>
struct convex_hull<Box, box_tag>
{
template <typename OutputGeometry, typename Strategy>
static inline void apply(Box const& box, OutputGeometry& out,
Strategy const& )
{
static bool const Close
= geometry::closure<OutputGeometry>::value == closed;
static bool const Reverse
= geometry::point_order<OutputGeometry>::value == counterclockwise;
// A hull for boxes is trivial. Any strategy is (currently) skipped.
boost::array<typename point_type<Box>::type, 4> range;
geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
geometry::append(out, range);
if (BOOST_GEOMETRY_CONDITION(Close))
{
geometry::append(out, *boost::begin(range));
}
}
};
template <order_selector Order, closure_selector Closure>
struct convex_hull_insert
: detail::convex_hull::hull_insert<Order, Closure>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy {
struct convex_hull
{
template <typename Geometry, typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
}
template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
default_strategy)
{
typedef typename strategy_convex_hull<
Geometry,
typename point_type<Geometry>::type
>::type strategy_type;
apply(geometry, out, strategy_type());
}
};
struct convex_hull_insert
{
template <typename Geometry, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator& out,
Strategy const& strategy)
{
BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
return dispatch::convex_hull_insert<
geometry::point_order<Geometry>::value,
geometry::closure<Geometry>::value
>::apply(geometry, out, strategy);
}
template <typename Geometry, typename OutputIterator>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator& out,
default_strategy)
{
typedef typename strategy_convex_hull<
Geometry,
typename point_type<Geometry>::type
>::type strategy_type;
return apply(geometry, out, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry>
struct convex_hull
{
template <typename OutputGeometry, typename Strategy>
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 <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename OutputGeometry, typename Strategy>
struct visitor: boost::static_visitor<void>
{
OutputGeometry& m_out;
Strategy const& m_strategy;
visitor(OutputGeometry& out, Strategy const& strategy)
: m_out(out), m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
convex_hull<Geometry>::apply(geometry, m_out, m_strategy);
}
};
template <typename OutputGeometry, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy), geometry);
}
};
template <typename Geometry>
struct convex_hull_insert
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy)
{
// Concept: output point type = point type of input geometry
concepts::check<Geometry const>();
concepts::check<typename point_type<Geometry>::type>();
return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename OutputIterator, typename Strategy>
struct visitor: boost::static_visitor<OutputIterator>
{
OutputIterator& m_out;
Strategy const& m_strategy;
visitor(OutputIterator& out, Strategy const& strategy)
: m_out(out), m_strategy(strategy)
{}
template <typename Geometry>
OutputIterator operator()(Geometry const& geometry) const
{
return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);
}
};
template <typename OutputIterator, typename Strategy>
static inline OutputIterator
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
OutputIterator& out,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);
}
};
} // namespace resolve_variant
template<typename Geometry, typename OutputGeometry, typename Strategy>
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<Geometry>::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<typename Geometry, typename OutputGeometry>
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<typename Geometry, typename OutputIterator, typename Strategy>
inline OutputIterator convex_hull_insert(Geometry const& geometry,
OutputIterator out, Strategy const& strategy)
{
return resolve_variant::convex_hull_insert<Geometry>
::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<typename Geometry, typename OutputIterator>
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
@@ -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 <algorithm>
#include <cstddef>
#include <functional>
#include <boost/mpl/assert.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
#include <boost/geometry/util/order_as_direction.hpp>
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 <typename Geometry>
struct correct_nop
{
static inline void apply(Geometry& )
{}
};
template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
struct correct_box_loop
{
typedef typename coordinate_type<Box>::type coordinate_type;
static inline void apply(Box& box)
{
if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
{
// Swap the coordinates
coordinate_type max_value = get<min_corner, Dimension>(box);
coordinate_type min_value = get<max_corner, Dimension>(box);
set<min_corner, Dimension>(box, min_value);
set<max_corner, Dimension>(box, max_value);
}
correct_box_loop
<
Box, Dimension + 1, DimensionCount
>::apply(box);
}
};
template <typename Box, std::size_t DimensionCount>
struct correct_box_loop<Box, DimensionCount, DimensionCount>
{
static inline void apply(Box& )
{}
};
// Correct a box: make min/max correct
template <typename Box>
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<Box>::type::value
>::apply(box);
}
};
// Close a ring, if not closed
template <typename Ring, typename Predicate>
struct correct_ring
{
typedef typename point_type<Ring>::type point_type;
typedef typename coordinate_type<Ring>::type coordinate_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type,
point_type
>::type strategy_type;
typedef detail::area::ring_area
<
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::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<Ring>::value;
if (disjoint && (s == closed))
{
geometry::append(r, *boost::begin(r));
}
if (! disjoint && s != closed)
{
// Open it by removing last point
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
}
}
// Check area
Predicate predicate;
typedef typename default_area_result<Ring>::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 <typename Polygon>
struct correct_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
typedef typename default_area_result<Polygon>::type area_result_type;
static inline void apply(Polygon& poly)
{
correct_ring
<
ring_type,
std::less<area_result_type>
>::apply(exterior_ring(poly));
typename interior_return_type<Polygon>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
correct_ring
<
ring_type,
std::greater<area_result_type>
>::apply(*it);
}
}
};
}} // namespace detail::correct
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct correct: not_implemented<Tag>
{};
template <typename Point>
struct correct<Point, point_tag>
: detail::correct::correct_nop<Point>
{};
template <typename LineString>
struct correct<LineString, linestring_tag>
: detail::correct::correct_nop<LineString>
{};
template <typename Segment>
struct correct<Segment, segment_tag>
: detail::correct::correct_nop<Segment>
{};
template <typename Box>
struct correct<Box, box_tag>
: detail::correct::correct_box<Box>
{};
template <typename Ring>
struct correct<Ring, ring_tag>
: detail::correct::correct_ring
<
Ring,
std::less<typename default_area_result<Ring>::type>
>
{};
template <typename Polygon>
struct correct<Polygon, polygon_tag>
: detail::correct::correct_polygon<Polygon>
{};
template <typename MultiPoint>
struct correct<MultiPoint, multi_point_tag>
: detail::correct::correct_nop<MultiPoint>
{};
template <typename MultiLineString>
struct correct<MultiLineString, multi_linestring_tag>
: detail::correct::correct_nop<MultiLineString>
{};
template <typename Geometry>
struct correct<Geometry, multi_polygon_tag>
: detail::multi_modify
<
Geometry,
detail::correct::correct_polygon
<
typename boost::range_value<Geometry>::type
>
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
template <typename Geometry>
struct correct
{
static inline void apply(Geometry& geometry)
{
concepts::check<Geometry const>();
dispatch::correct<Geometry>::apply(geometry);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: boost::static_visitor<void>
{
template <typename Geometry>
void operator()(Geometry& geometry) const
{
correct<Geometry>::apply(geometry);
}
};
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& 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 <typename Geometry>
inline void correct(Geometry& geometry)
{
resolve_variant::correct<Geometry>::apply(geometry);
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
@@ -0,0 +1,462 @@
// 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, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// 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_COVERED_BY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
#include <cstddef>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace covered_by {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
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 <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
typedef typename detail::de9im::static_mask_covered_by_type
<
Geometry1, Geometry2
>::type covered_by_mask;
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
}
};
}} // namespace detail::covered_by
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct covered_by
: not_implemented<Tag1, Tag2>
{};
template <typename Point, typename Box>
struct covered_by<Point, Box, point_tag, box_tag>
{
template <typename Strategy>
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 <typename Box1, typename Box2>
struct covered_by<Box1, Box2, box_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
assert_dimension_equal<Box1, Box2>();
::boost::ignore_unused_variable_warning(strategy);
return strategy.apply(box1, box2);
}
};
// P/P
template <typename Point1, typename Point2>
struct covered_by<Point1, Point2, point_tag, point_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiPoint>
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
: public detail::covered_by::use_point_in_geometry
{};
// P/L
template <typename Point, typename Segment>
struct covered_by<Point, Segment, point_tag, segment_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename Linestring>
struct covered_by<Point, Linestring, point_tag, linestring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiLinestring>
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
: public detail::covered_by::use_point_in_geometry
{};
// P/A
template <typename Point, typename Ring>
struct covered_by<Point, Ring, point_tag, ring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename Polygon>
struct covered_by<Point, Polygon, point_tag, polygon_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiPolygon>
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
: public detail::covered_by::use_point_in_geometry
{};
// L/L
template <typename Linestring1, typename Linestring2>
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename MultiLinestring>
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Linestring>
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring1, typename MultiLinestring2>
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
: public detail::covered_by::use_relate
{};
// L/A
template <typename Linestring, typename Ring>
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Ring>
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename Polygon>
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Polygon>
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename MultiPolygon>
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename MultiPolygon>
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
// A/A
template <typename Ring1, typename Ring2>
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Ring, typename Polygon>
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon, typename Ring>
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon1, typename Polygon2>
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Ring, typename MultiPolygon>
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon, typename Ring>
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon, typename MultiPolygon>
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon, typename Polygon>
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon1, typename MultiPolygon2>
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy {
struct covered_by
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::within::check
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
Strategy
>();
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>();
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
geometry2,
strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::covered_by::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return covered_by::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct covered_by
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_strategy::covered_by
::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2), m_strategy(strategy) {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return covered_by<Geometry1, Geometry2>
::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1), m_strategy(strategy) {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return covered_by<Geometry1, Geometry2>
::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct covered_by<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(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<typename Geometry1, typename Geometry2>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::covered_by<Geometry1, Geometry2>
::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<typename Geometry1, typename Geometry2, typename Strategy>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
@@ -0,0 +1,267 @@
// 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, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// 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_CROSSES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
#include <cstddef>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct crosses
: detail::relate::relate_impl
<
detail::de9im::static_mask_crosses_type,
Geometry1,
Geometry2
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct crosses
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct crosses
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_strategy::crosses::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
result_type operator()(Geometry1 const& geometry1) const
{
return crosses
<
Geometry1,
Geometry2
>::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct crosses<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
result_type operator()(Geometry2 const& geometry2) const
{
return crosses
<
Geometry1,
Geometry2
>::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
result_type operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return crosses
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check2{crosses}
\ingroup crosses
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Crosses}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{crosses}
\return \return_check2{crosses}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/crosses.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool crosses(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::crosses
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\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 <typename Geometry1, typename Geometry2>
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::crosses
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_CROSSES_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 <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/add_const_if_c.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename GeometryTag, typename Geometry, typename Range, bool IsConst>
struct as_range
{
static inline typename add_const_if_c<IsConst, Range>::type& get(
typename add_const_if_c<IsConst, Geometry>::type& input)
{
return input;
}
};
template <typename Geometry, typename Range, bool IsConst>
struct as_range<polygon_tag, Geometry, Range, IsConst>
{
static inline typename add_const_if_c<IsConst, Range>::type& get(
typename add_const_if_c<IsConst, Geometry>::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 <typename Range, typename Geometry>
inline Range& as_range(Geometry& input)
{
return dispatch::as_range
<
typename tag<Geometry>::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 <typename Range, typename Geometry>
inline Range const& as_range(Geometry const& input)
{
return dispatch::as_range
<
typename tag<Geometry>::type,
Geometry,
Range,
true
>::get(input);
}
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_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 <cstddef>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/util/range.hpp>
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 <typename Box, typename Point>
inline void assign_box_corners(Box const& box,
Point& lower_left, Point& lower_right,
Point& upper_left, Point& upper_right)
{
concepts::check<Box const>();
concepts::check<Point>();
detail::assign::assign_box_2d_corner
<min_corner, min_corner>(box, lower_left);
detail::assign::assign_box_2d_corner
<max_corner, min_corner>(box, lower_right);
detail::assign::assign_box_2d_corner
<min_corner, max_corner>(box, upper_left);
detail::assign::assign_box_2d_corner
<max_corner, max_corner>(box, upper_right);
}
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
template <bool Reverse, typename Box, typename Range>
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
@@ -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 <cstddef>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
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 <std::size_t Index, typename Geometry, typename Point>
inline void assign_point_to_index(Point const& point, Geometry& geometry)
{
concepts::check<Point const>();
concepts::check<Geometry>();
detail::assign::assign_point_to_index
<
Geometry, Point, Index, 0, dimension<Geometry>::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 <std::size_t Index, typename Point, typename Geometry>
inline void assign_point_from_index(Geometry const& geometry, Point& point)
{
concepts::check<Geometry const>();
concepts::check<Point>();
detail::assign::assign_point_from_index
<
Geometry, Point, Index, 0, dimension<Geometry>::type::value
>::apply(geometry, point);
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_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 <cstddef>
#include <boost/concept/requires.hpp>
#include <boost/concept_check.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace assign
{
template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>
struct initialize
{
template <typename Box>
static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)
{
geometry::set<Index, Dimension>(box, value);
initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);
}
};
template <std::size_t Index, std::size_t DimensionCount>
struct initialize<Index, DimensionCount, DimensionCount>
{
template <typename Box>
static inline void apply(Box&, typename coordinate_type<Box>::type const&)
{}
};
struct assign_zero_point
{
template <typename Point>
static inline void apply(Point& point)
{
geometry::assign_value(point, 0);
}
};
struct assign_inverse_box_or_segment
{
template <typename BoxOrSegment>
static inline void apply(BoxOrSegment& geometry)
{
typedef typename point_type<BoxOrSegment>::type point_type;
typedef typename coordinate_type<point_type>::type bound_type;
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, boost::numeric::bounds<bound_type>::highest()
);
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, boost::numeric::bounds<bound_type>::lowest()
);
}
};
struct assign_zero_box_or_segment
{
template <typename BoxOrSegment>
static inline void apply(BoxOrSegment& geometry)
{
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, coordinate_type()
);
initialize<1, 0, dimension<BoxOrSegment>::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<Box, 2>();
assert_dimension<Point, 2>();
// Copy coordinates
typedef typename coordinate_type<Point>::type coordinate_type;
geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(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<Index, Dimension>(geometry, boost::numeric_cast
<
typename coordinate_type<Geometry>::type
>(geometry::get<Dimension>(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<Dimension>( point, boost::numeric_cast
<
typename coordinate_type<Point>::type
>(geometry::get<Index, Dimension>(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 <typename Geometry>
struct assign_2d_box_or_segment
{
typedef typename coordinate_type<Geometry>::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 <typename Type>
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<coordinate_type>(x1));
geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
}
};
}} // namespace detail::assign
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
struct assign
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (types<Geometry>)
);
};
template <typename Point>
struct assign<point_tag, Point, 2>
{
typedef typename coordinate_type<Point>::type coordinate_type;
template <typename T>
static inline void apply(Point& point, T const& c1, T const& c2)
{
set<0>(point, boost::numeric_cast<coordinate_type>(c1));
set<1>(point, boost::numeric_cast<coordinate_type>(c2));
}
};
template <typename Point>
struct assign<point_tag, Point, 3>
{
typedef typename coordinate_type<Point>::type coordinate_type;
template <typename T>
static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
{
set<0>(point, boost::numeric_cast<coordinate_type>(c1));
set<1>(point, boost::numeric_cast<coordinate_type>(c2));
set<2>(point, boost::numeric_cast<coordinate_type>(c3));
}
};
template <typename Box>
struct assign<box_tag, Box, 2>
: detail::assign::assign_2d_box_or_segment<Box>
{};
template <typename Segment>
struct assign<segment_tag, Segment, 2>
: detail::assign::assign_2d_box_or_segment<Segment>
{};
template <typename GeometryTag, typename Geometry>
struct assign_zero {};
template <typename Point>
struct assign_zero<point_tag, Point>
: detail::assign::assign_zero_point
{};
template <typename Box>
struct assign_zero<box_tag, Box>
: detail::assign::assign_zero_box_or_segment
{};
template <typename Segment>
struct assign_zero<segment_tag, Segment>
: detail::assign::assign_zero_box_or_segment
{};
template <typename GeometryTag, typename Geometry>
struct assign_inverse {};
template <typename Box>
struct assign_inverse<box_tag, Box>
: detail::assign::assign_inverse_box_or_segment
{};
template <typename Segment>
struct assign_inverse<segment_tag, Segment>
: detail::assign::assign_inverse_box_or_segment
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
@@ -0,0 +1,148 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014, 2016, 2017.
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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_AZIMUTH_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
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 <typename ReturnType, typename Tag>
struct azimuth
: not_implemented<Tag>
{};
template <typename ReturnType>
struct azimuth<ReturnType, geographic_tag>
{
template <typename P1, typename P2, typename Spheroid>
static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)
{
return geometry::formula::vincenty_inverse<ReturnType, false, true>().apply
( get_as_radian<0>(p1), get_as_radian<1>(p1),
get_as_radian<0>(p2), get_as_radian<1>(p2),
spheroid ).azimuth;
}
template <typename P1, typename P2>
static inline ReturnType apply(P1 const& p1, P2 const& p2)
{
return apply(p1, p2, srs::spheroid<ReturnType>());
}
};
template <typename ReturnType>
struct azimuth<ReturnType, spherical_equatorial_tag>
{
template <typename P1, typename P2, typename Sphere>
static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
{
return geometry::formula::spherical_azimuth<ReturnType, false>
( get_as_radian<0>(p1), get_as_radian<1>(p1),
get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth;
}
template <typename P1, typename P2>
static inline ReturnType apply(P1 const& p1, P2 const& p2)
{
return apply(p1, p2, 0); // dummy model
}
};
template <typename ReturnType>
struct azimuth<ReturnType, spherical_polar_tag>
: azimuth<ReturnType, spherical_equatorial_tag>
{};
template <typename ReturnType>
struct azimuth<ReturnType, cartesian_tag>
{
template <typename P1, typename P2, typename Plane>
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 <typename P1, typename P2>
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 <typename ReturnType, typename Point1, typename Point2>
inline ReturnType azimuth(Point1 const& p1, Point2 const& p2)
{
return detail_dispatch::azimuth
<
ReturnType,
typename geometry::cs_tag<Point1>::type
>::apply(p1, p2);
}
/// Calculate azimuth between two points.
/// The result is in radians.
template <typename ReturnType, typename Point1, typename Point2, typename Model>
inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model)
{
return detail_dispatch::azimuth
<
ReturnType,
typename geometry::cs_tag<Point1>::type
>::apply(p1, p2, model);
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
@@ -0,0 +1,241 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017, 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_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 <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/strategies/buffer.hpp>
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 Strategy,
typename RobustPolicy,
typename Visitor
>
static inline void apply(std::size_t size_at_start,
Rings& rings, typename boost::range_value<Rings>::type& ring,
Turns& turns,
typename boost::range_value<Turns>::type const& /*turn*/,
Operation& operation,
detail::overlay::traverse_error_type /*traverse_error*/,
Geometry const& ,
Geometry const& ,
Strategy 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 <typename Turns>
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)
{
}
template <typename Turns>
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)
{
}
template <typename Turns>
void visit_turns(int , Turns const& ) {}
template <typename Clusters, typename Turns>
void visit_clusters(Clusters const& , Turns const& ) {}
template <typename Turns, typename Turn, typename Operation>
void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/)
{
}
template <typename Turns, typename Turn, typename Operation>
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 <typename Point, typename SegmentRatio>
struct buffer_turn_operation
: public detail::overlay::traversal_turn_operation<Point, SegmentRatio>
{
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 <typename Point, typename RobustPoint, typename SegmentRatio>
struct buffer_turn_info
: public detail::overlay::turn_info
<
Point,
SegmentRatio,
buffer_turn_operation<Point, SegmentRatio>
>
{
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 <typename Turn>
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
@@ -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 <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
struct buffered_ring_collection_tag : polygonal_tag, multi_tag
{};
template <typename Ring>
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 <typename Ring>
struct buffered_ring_collection : public std::vector<Ring>
{
};
}} // namespace detail::buffer
// Turn off concept checking (for now)
namespace dispatch
{
template <typename Geometry, bool IsConst>
struct check<Geometry, detail::buffer::buffered_ring_collection_tag, IsConst>
{
};
}
#endif // DOXYGEN_NO_DETAIL
// Register the types
namespace traits
{
template <typename Ring>
struct tag<geometry::detail::buffer::buffered_ring<Ring> >
{
typedef ring_tag type;
};
template <typename Ring>
struct point_order<geometry::detail::buffer::buffered_ring<Ring> >
{
static const order_selector value = geometry::point_order<Ring>::value;
};
template <typename Ring>
struct closure<geometry::detail::buffer::buffered_ring<Ring> >
{
static const closure_selector value = geometry::closure<Ring>::value;
};
template <typename Ring>
struct point_type<geometry::detail::buffer::buffered_ring_collection<Ring> >
{
typedef typename geometry::point_type<Ring>::type type;
};
template <typename Ring>
struct tag<geometry::detail::buffer::buffered_ring_collection<Ring> >
{
typedef geometry::detail::buffer::buffered_ring_collection_tag type;
};
} // namespace traits
namespace core_dispatch
{
template <typename Ring>
struct ring_type
<
detail::buffer::buffered_ring_collection_tag,
detail::buffer::buffered_ring_collection<Ring>
>
{
typedef Ring type;
};
// There is a specific tag, so this specialization cannot be placed in traits
template <typename Ring>
struct point_order<detail::buffer::buffered_ring_collection_tag,
geometry::detail::buffer::buffered_ring_collection
<
geometry::detail::buffer::buffered_ring<Ring>
> >
{
static const order_selector value
= core_dispatch::point_order<ring_tag, Ring>::value;
};
}
template <>
struct single_tag_of<detail::buffer::buffered_ring_collection_tag>
{
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<MultiRing>::type,
Reverse,
SegmentIdentifier,
PointOut
>
>
{};
template<bool Reverse>
struct copy_segments
<
detail::buffer::buffered_ring_collection_tag,
Reverse
>
: detail::copy_segments::copy_segments_multi
<
detail::copy_segments::copy_segments_ring<Reverse>
>
{};
template <typename Point, typename MultiGeometry>
struct within
<
Point,
MultiGeometry,
point_tag,
detail::buffer::buffered_ring_collection_tag
>
{
template <typename Strategy>
static inline bool apply(Point const& point,
MultiGeometry const& multi, Strategy const& strategy)
{
return detail::within::point_in_geometry(point, multi, strategy) == 1;
}
};
template <typename Geometry>
struct is_empty<Geometry, detail::buffer::buffered_ring_collection_tag>
: detail::is_empty::multi_is_empty<detail::is_empty::range_is_empty>
{};
template <typename Geometry>
struct envelope<Geometry, detail::buffer::buffered_ring_collection_tag>
: detail::envelope::envelope_multi_range
<
detail::envelope::envelope_range
>
{};
} // namespace dispatch
namespace detail { namespace overlay
{
template<>
struct get_ring<detail::buffer::buffered_ring_collection_tag>
{
template<typename MultiGeometry>
static inline typename ring_type<MultiGeometry>::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<ring_tag>::apply(id, multi_ring[id.multi_index]);
}
};
}}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
@@ -0,0 +1,304 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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_GET_PIECE_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
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 IntersectionStrategy,
typename RobustPolicy
>
class piece_turn_visitor
{
Pieces const& m_pieces;
Rings const& m_rings;
Turns& m_turns;
IntersectionStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
template <typename Piece>
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 <typename Piece>
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 <typename Range, typename Iterator>
inline void move_to_next_point(Range const& range, Iterator& next) const
{
++next;
if (next == boost::end(range))
{
next = boost::begin(range) + 1;
}
}
template <typename Range, typename Iterator>
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 <std::size_t Dimension, typename Iterator, typename Box>
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<Dimension>(dir, *(it_begin + 1),
other_bounding_box, m_robust_policy);
++it_begin, index++)
{}
}
template <std::size_t Dimension, typename Iterator, typename Box>
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<Dimension>(dir, *(it_beyond - 2),
other_bounding_box, m_robust_policy))
{
--it_beyond;
}
else
{
return;
}
}
}
template <typename Piece, typename Section>
inline void calculate_turns(Piece const& piece1, Piece const& piece2,
Section const& section1, Section const& section2)
{
typedef typename boost::range_value<Rings const>::type ring_type;
typedef typename boost::range_value<Turns const>::type turn_type;
typedef typename boost::range_iterator<ring_type const>::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_intersection_strategy,
m_robust_policy,
std::back_inserter(m_turns));
}
}
}
public:
piece_turn_visitor(Pieces const& pieces,
Rings const& ring_collection,
Turns& turns,
IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy)
: m_pieces(pieces)
, m_rings(ring_collection)
, m_turns(turns)
, m_intersection_strategy(intersection_strategy)
, m_robust_policy(robust_policy)
{}
template <typename Section>
inline void apply(Section const& section1, Section const& section2,
bool first = true)
{
boost::ignore_unused_variable_warning(first);
typedef typename boost::range_value<Pieces const>::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
@@ -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 <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
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 <typename Point>
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<Point>::type coordinate_type;
coordinate_type const denominator
= determinant<coordinate_type>(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<coordinate_type>(get<0>(pi), get<1>(pi), get<0>(pj), get<1>(pj));
coordinate_type d2 = determinant<coordinate_type>(get<0>(qi), get<1>(qi), get<0>(qj), get<1>(qj));
double const multiplier = 1.0 / denominator;
set<0>(ip, determinant<coordinate_type>(d1, get<0>(pi) - get<0>(pj), d2, get<0>(qi) - get<0>(qj)) * multiplier);
set<1>(ip, determinant<coordinate_type>(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
@@ -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 <typename T>
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
@@ -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 <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/buffer.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
struct original_get_box
{
template <typename Box, typename Original>
static inline void apply(Box& total, Original const& original)
{
geometry::expand(total, original.m_box);
}
};
struct original_ovelaps_box
{
template <typename Box, typename Original>
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 <typename Turn>
static inline bool apply(Turn const& turn)
{
return turn.location == location_ok;
}
};
struct turn_in_original_ovelaps_box
{
template <typename Box, typename Turn>
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 <typename Point, typename Original>
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<Point> 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<sections_type const>::type iterator_type;
typedef typename boost::range_value<sections_type const>::type section_type;
typedef typename geometry::coordinate_type<Point>::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<min_corner, 0>(section.bounding_box)
&& point_x <= geometry::get<max_corner, 0>(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 <typename Turns>
class turn_in_original_visitor
{
public:
turn_in_original_visitor(Turns& turns)
: m_mutable_turns(turns)
{}
template <typename Turn, typename Original>
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
@@ -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 <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
#endif
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
struct piece_get_box
{
template <typename Box, typename Piece>
static inline void apply(Box& total, Piece const& piece)
{
geometry::expand(total, piece.robust_envelope);
}
};
struct piece_ovelaps_box
{
template <typename Box, typename Piece>
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 <typename Box, typename Turn>
static inline void apply(Box& total, Turn const& turn)
{
geometry::expand(total, turn.robust_point);
}
};
struct turn_ovelaps_box
{
template <typename Box, typename Turn>
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 <typename Point>
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<Point> box_type;
box_type box;
geometry::assign_inverse(box);
geometry::expand(box, previous);
geometry::expand(box, current);
return geometry::covered_by(point, box);
}
template <typename Point, typename Turn>
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<Point const> 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<Point>::type
>::type side_strategy;
typedef typename geometry::coordinate_type<Point>::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 <typename Turn, typename Piece>
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<point_type>::type coordinate_type;
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
typedef geometry::model::referring_segment<point_type const> 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<point_type> 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<min_corner, 0>(section.bounding_box) - 1
&& point_x <= geometry::get<max_corner, 0>(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 <typename Point, typename Turn>
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<Point const> 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<Point> 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<Point>::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<Point> 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 <typename Turn, typename Piece>
static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
{
typedef typename Turn::robust_point_type point_type;
geometry::equal_to<point_type> comparator;
point_type points[4];
signed_size_type helper_count = static_cast<signed_size_type>(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<point_type>::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 <typename Turn, typename Piece, typename Compare>
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 <typename Turn, typename Piece>
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<point_type> 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<point_type, 0>());
if (code != analyse_continue) return code;
}
else if (piece.is_monotonic_increasing[1])
{
code = check_monotonic(turn, piece, geometry::less<point_type, 1>());
if (code != analyse_continue) return code;
}
else if (piece.is_monotonic_decreasing[0])
{
code = check_monotonic(turn, piece, geometry::greater<point_type, 0>());
if (code != analyse_continue) return code;
}
else if (piece.is_monotonic_decreasing[1])
{
code = check_monotonic(turn, piece, geometry::greater<point_type, 1>());
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 <typename Turns, typename Pieces>
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 <typename Operation, typename Piece>
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 <typename Turn, typename Piece>
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<point_type const> segment;
segment const p(turn.rob_pi, turn.rob_pj);
segment const q(turn.rob_qi, turn.rob_qj);
typedef typename boost::range_iterator<ring_type const>::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<point_type> 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 <typename Turn, typename Piece>
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
@@ -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<typename ReturnType, typename Geometry, typename Strategy>
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
@@ -0,0 +1,62 @@
// 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.
// This file was modified by Oracle on 2016.
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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_CALCULATE_SUM_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
#include <boost/range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
class calculate_polygon_sum
{
template <typename ReturnType, typename Policy, typename Rings, typename Strategy>
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
{
ReturnType sum = ReturnType(0);
for (typename boost::range_iterator<Rings const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
sum += Policy::apply(*it, strategy);
}
return sum;
}
public :
template <typename ReturnType, typename Policy, typename Polygon, typename Strategy>
static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)
{
return Policy::apply(exterior_ring(poly), strategy)
+ sum_interior_rings<ReturnType, Policy>(interior_rings(poly), strategy)
;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_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 <cstddef>
#include <boost/core/addressof.hpp>
#include <boost/core/ref.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
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 <typename Geometry,
typename CastedTag = typename tag_cast
<
typename tag<Geometry>::type,
areal_tag
>::type,
typename CSTag = typename cs_tag<Geometry>::type>
struct translating_transformer
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef boost::reference_wrapper<point_type const> 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 <typename ResPt>
void apply_reverse(ResPt &) const {}
};
// Specialization for Areal Geometries in cartesian CS
template <typename Geometry>
struct translating_transformer<Geometry, areal_tag, cartesian_tag>
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef point_type result_type;
explicit translating_transformer(Geometry const& geom)
: m_origin(NULL)
{
geometry::point_iterator<Geometry const>
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 <typename ResPt>
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
@@ -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 <boost/core/ignore_unused.hpp>
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 <typename Predicate, bool AllowEmptyRange = true>
struct check_iterator_range
{
template <typename InputIterator>
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 <typename InputIterator>
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
@@ -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 <iterator>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
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<RangeIterator>::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<RangeIterator>::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<Geometry>::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
@@ -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 <utility>
#include <boost/range.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
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<Range const>::type iterator_type;
template <typename Distance>
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<iterator_type, iterator_type> return_type;
template <typename Distance>
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<Range>::type
>::type dist_min;
return apply(point, first, last, strategy, dist_min);
}
template <typename Distance>
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 <typename Point, typename Range, typename Strategy>
class point_to_point_range<Point, Range, open, Strategy>
: point_to_point_range<Point, Range, closed, Strategy>
{
private:
typedef point_to_point_range<Point, Range, closed, Strategy> base_type;
typedef typename base_type::iterator_type iterator_type;
template <typename Distance>
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<iterator_type, iterator_type> return_type;
template <typename Distance>
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<Range>::type
>::type distance_return_type;
distance_return_type dist_min;
return apply(point, first, last, strategy, dist_min);
}
template <typename Distance>
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
@@ -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 <cstddef>
#include <iterator>
#include <utility>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/index/rtree.hpp>
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<RTreeValueType, index::linear<8> > 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 <typename RTreeRangeIterator, typename QueryRangeIterator>
struct return_type
{
typedef std::pair
<
typename std::iterator_traits<RTreeRangeIterator>::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<rtree_value_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
@@ -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 <boost/geometry/algorithms/detail/distance/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_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 <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/comparable_distance_result.hpp>
#include <boost/geometry/strategies/default_comparable_distance_result.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
struct comparable_distance
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline
typename comparable_distance_result<Geometry1, Geometry2, Strategy>::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 <typename Geometry1, typename Geometry2>
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 <typename Geometry1, typename Geometry2>
struct comparable_distance
{
template <typename Strategy>
static inline
typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_strategy::comparable_distance::apply(geometry1,
geometry2,
strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct comparable_distance
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Geometry2
>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename comparable_distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
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 Geometry1>
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 <typename Strategy>
static inline typename comparable_distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Geometry2,
Strategy
>::type
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct comparable_distance
<
Geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename comparable_distance_result
<
Geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
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 Geometry2>
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 <typename Strategy>
static inline typename comparable_distance_result
<
Geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Strategy
>::type
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct comparable_distance
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename comparable_distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
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 <typename Strategy>
static inline typename comparable_distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(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 <typename Geometry1, typename Geometry2, typename Strategy>
inline typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
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 <typename Geometry1, typename Geometry2>
inline typename default_comparable_distance_result<Geometry1, Geometry2>::type
comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return geometry::comparable_distance(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_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 <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
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<Destination>::type coordinate_type;
geometry::set<min_corner, Dimension>(destination,
boost::numeric_cast<coordinate_type>(
geometry::get<min_corner, Dimension>(source)));
geometry::set<max_corner, Dimension>(destination,
boost::numeric_cast<coordinate_type>(
geometry::get<max_corner, Dimension>(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<Source, Destination, DimensionCount, DimensionCount>
{
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
@@ -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 <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
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 point_to_point
{
static inline void apply(Source const& source, Destination& destination)
{
typedef typename coordinate_type<Destination>::type coordinate_type;
set<Dimension>(destination, boost::numeric_cast<coordinate_type>(get<Dimension>(source)));
point_to_point<Source, Destination, Dimension + 1, DimensionCount>::apply(source, destination);
}
};
template <typename Source, typename Destination, std::size_t DimensionCount>
struct point_to_point<Source, Destination, DimensionCount, DimensionCount>
{
static inline void apply(Source const& , Destination& )
{}
};
template <typename Source, typename Destination>
inline void convert_point_to_point(Source const& source, Destination& destination)
{
point_to_point<Source, Destination, 0, dimension<Destination>::value>::apply(source, destination);
}
}} // namespace detail::conversion
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_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 <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace counting
{
template <std::size_t D>
struct other_count
{
template <typename Geometry>
static inline std::size_t apply(Geometry const&)
{
return D;
}
template <typename Geometry>
static inline std::size_t apply(Geometry const&, bool)
{
return D;
}
};
template <typename RangeCount>
struct polygon_count
{
template <typename Polygon>
static inline std::size_t apply(Polygon const& poly)
{
std::size_t n = RangeCount::apply(exterior_ring(poly));
typename interior_return_type<Polygon const>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
n += RangeCount::apply(*it);
}
return n;
}
};
template <typename SingleCount>
struct multi_count
{
template <typename MultiGeometry>
static inline std::size_t apply(MultiGeometry const& geometry)
{
std::size_t n = 0;
for (typename boost::range_iterator<MultiGeometry const>::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
@@ -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 <boost/geometry/algorithms/detail/azimuth.hpp>
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 <typename ReturnType, typename Point1, typename Point2>
inline ReturnType course(Point1 const& p1, Point2 const& p2)
{
return azimuth<ReturnType>(p1, p2);
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_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 <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t Index, typename Point1, typename Point2>
inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
{
return
math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))
?
0
:
(geometry::get<Index>(point1) > geometry::get<Index>(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 <typename Point1, typename Point2>
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
@@ -0,0 +1,180 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct check_each_ring_for_within_call_covered_by
{
/*!
\tparam Strategy point_in_geometry strategy
*/
template <typename Point, typename Strategy>
static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy)
{
return geometry::covered_by(p, g, strategy);
}
};
template <typename Geometry>
struct check_each_ring_for_within_call_covered_by<Geometry, box_tag>
{
template <typename Point, typename Strategy>
static inline bool apply(Point const& p, Geometry const& g, Strategy const& )
{
return geometry::covered_by(p, g);
}
};
/*!
\tparam Strategy point_in_geometry strategy
*/
template<typename Geometry, typename Strategy>
struct check_each_ring_for_within
{
bool not_disjoint;
Geometry const& m_geometry;
Strategy const& m_strategy;
inline check_each_ring_for_within(Geometry const& g,
Strategy const& strategy)
: not_disjoint(false)
, m_geometry(g)
, m_strategy(strategy)
{}
template <typename Range>
inline void apply(Range const& range)
{
typename point_type<Range>::type pt;
not_disjoint = not_disjoint
|| ( geometry::point_on_border(pt, range)
&& check_each_ring_for_within_call_covered_by
<
Geometry
>::apply(pt, m_geometry, m_strategy) );
}
};
/*!
\tparam Strategy point_in_geometry strategy
*/
template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
inline bool rings_containing(FirstGeometry const& geometry1,
SecondGeometry const& geometry2,
Strategy const& strategy)
{
check_each_ring_for_within
<
FirstGeometry, Strategy
> checker(geometry1, strategy);
geometry::detail::for_each_range(geometry2, checker);
return checker.not_disjoint;
}
template <typename Geometry1, typename Geometry2>
struct general_areal
{
/*!
\tparam Strategy relate (segments intersection) strategy
*/
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) )
{
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,
strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>())
|| rings_containing(geometry2, geometry1,
strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()) )
{
return false;
}
return true;
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Areal1, typename Areal2>
struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false>
: detail::disjoint::general_areal<Areal1, Areal2>
{};
template <typename Areal, typename Box>
struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>
: detail::disjoint::general_areal<Areal, Box>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
@@ -0,0 +1,175 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
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<Box1>::value,
typename CSTag = typename tag_cast
<
typename cs_tag<Box1>::type,
spherical_tag
>::type
>
struct box_box
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
{
return apply(box1, box2);
}
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
{
return true;
}
if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
{
return true;
}
return box_box
<
Box1, Box2,
Dimension + 1, DimensionCount
>::apply(box1, box2);
}
};
template <typename Box1, typename Box2, std::size_t DimensionCount, typename CSTag>
struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>
{
static inline bool apply(Box1 const& , Box2 const& )
{
return false;
}
};
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
{
return apply(box1, box2);
}
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
typedef typename geometry::select_most_precise
<
typename coordinate_type<Box1>::type,
typename coordinate_type<Box2>::type
>::type calc_t;
typedef typename coordinate_system<Box1>::type::units units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
calc_t const b1_min = get<min_corner, 0>(box1);
calc_t const b1_max = get<max_corner, 0>(box1);
calc_t const b2_min = get<min_corner, 0>(box2);
calc_t const b2_max = get<max_corner, 0>(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<units_t>(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 <typename Box1, typename Box2>
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
{
return box_box<Box1, Box2>::apply(box1, box2);
}
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
: detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_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 <boost/geometry/algorithms/detail/disjoint/areal_areal.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_areal.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
@@ -0,0 +1,246 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <cstddef>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/relate/interface.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
struct disjoint
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::disjoint
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::disjoint::services::default_strategy
<
Geometry1, Geometry2
>::type strategy_type;
return dispatch::disjoint
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct disjoint
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
<
Geometry1 const,
Geometry2 const
>();
return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct disjoint<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return disjoint<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct disjoint<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return disjoint<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct disjoint
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check2{are disjoint}
\ingroup disjoint
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Disjoint}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{disjoint}
\return \return_check2{are disjoint}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/disjoint.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool disjoint(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::disjoint
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\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 <typename Geometry1, typename Geometry2>
inline bool disjoint(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
return resolve_variant::disjoint
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP
@@ -0,0 +1,301 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <iterator>
#include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename Geometry1, typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
struct disjoint_no_intersections_policy
{
/*!
\tparam Strategy point_in_geometry strategy
*/
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
typedef typename point_type<Geometry1>::type point1_type;
point1_type p;
geometry::point_on_border(p, g1);
return !geometry::covered_by(p, g2, strategy);
}
};
template <typename Geometry1, typename Geometry2, typename Tag1>
struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
{
/*!
\tparam Strategy point_in_geometry strategy
*/
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// TODO: use partition or rtree on g2
typedef typename boost::range_iterator<Geometry1 const>::type iterator;
for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
{
typedef typename boost::range_value<Geometry1 const>::type value_type;
if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
::apply(*it, g2, strategy) )
{
return false;
}
}
return true;
}
};
template<typename Geometry1, typename Geometry2,
typename NoIntersectionsPolicy
= disjoint_no_intersections_policy<Geometry1, Geometry2> >
struct disjoint_linear_areal
{
/*!
\tparam Strategy relate (segments intersection) strategy
*/
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// if there are intersections - return false
if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2, strategy) )
{
return false;
}
return NoIntersectionsPolicy
::apply(g1, g2,
strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>());
}
};
template
<
typename Segment,
typename Areal,
typename Tag = typename tag<Areal>::type
>
struct disjoint_segment_areal
: not_implemented<Segment, Areal>
{};
template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
private:
template <typename InteriorRings, typename Strategy>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
Segment const& segment,
Strategy const& strategy)
{
typedef typename boost::range_value<InteriorRings>::type ring_type;
typedef unary_disjoint_geometry_to_query_geometry
<
Segment,
Strategy,
disjoint_range_segment_or_box
<
ring_type, closure<ring_type>::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, strategy));
}
public:
template <typename IntersectionStrategy>
static inline bool apply(Segment const& segment,
Polygon const& polygon,
IntersectionStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring;
if ( !disjoint_range_segment_or_box
<
ring, closure<Polygon>::value, Segment
>::apply(geometry::exterior_ring(polygon), segment, strategy) )
{
return false;
}
if ( !check_interior_rings(geometry::interior_rings(polygon), segment, strategy) )
{
return false;
}
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
return !geometry::covered_by(p, polygon,
strategy.template get_point_in_geometry_strategy<Segment, Polygon>());
}
};
template <typename Segment, typename MultiPolygon>
struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
{
template <typename IntersectionStrategy>
static inline bool apply(Segment const& segment, MultiPolygon const& multipolygon,
IntersectionStrategy const& strategy)
{
return multirange_constant_size_geometry
<
MultiPolygon, Segment
>::apply(multipolygon, segment, strategy);
}
};
template <typename Segment, typename Ring>
struct disjoint_segment_areal<Segment, Ring, ring_tag>
{
template <typename IntersectionStrategy>
static inline bool apply(Segment const& segment,
Ring const& ring,
IntersectionStrategy const& strategy)
{
if ( !disjoint_range_segment_or_box
<
Ring, closure<Ring>::value, Segment
>::apply(ring, segment, strategy) )
{
return false;
}
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
return !geometry::covered_by(p, ring,
strategy.template get_point_in_geometry_strategy<Segment, Ring>());
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Areal>
struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>
: public detail::disjoint::disjoint_linear_areal<Linear, Areal>
{};
template <typename Areal, typename Linear>
struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
{
template <typename Strategy>
static inline bool apply(Areal const& areal, Linear const& linear,
Strategy const& strategy)
{
return detail::disjoint::disjoint_linear_areal
<
Linear, Areal
>::apply(linear, areal, strategy);
}
};
template <typename Areal, typename Segment>
struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>
{
template <typename Strategy>
static inline bool apply(Areal const& g1, Segment const& g2,
Strategy const& strategy)
{
return detail::disjoint::disjoint_segment_areal
<
Segment, Areal
>::apply(g2, g1, strategy);
}
};
template <typename Segment, typename Areal>
struct disjoint<Segment, Areal, 2, segment_tag, areal_tag, false>
: detail::disjoint::disjoint_segment_areal<Segment, Areal>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
@@ -0,0 +1,191 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <cstddef>
#include <deque>
#include <boost/range.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename Segment1, typename Segment2>
struct disjoint_segment
{
template <typename Strategy>
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
Strategy const& strategy)
{
typedef typename point_type<Segment1>::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;
typedef policies::relate::segments_intersection_points
<
intersection_return_type
> intersection_policy;
intersection_return_type is = strategy.apply(segment1, segment2,
intersection_policy(),
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 <typename Geometry1, typename Geometry2>
struct disjoint_linear
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
typedef typename geometry::point_type<Geometry1>::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<turn_info_type> 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<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
Geometry1,
Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, // should be false
overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, // should be false
detail::get_turns::get_turn_info_type
<
Geometry1, Geometry2, assign_disjoint_policy
>
>::apply(0, geometry1, 1, geometry2,
strategy, 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 <typename Linear1, typename Linear2>
struct disjoint<Linear1, Linear2, 2, linear_tag, linear_tag, false>
: detail::disjoint::disjoint_linear<Linear1, Linear2>
{};
template <typename Segment1, typename Segment2>
struct disjoint<Segment1, Segment2, 2, segment_tag, segment_tag, false>
: detail::disjoint::disjoint_segment<Segment1, Segment2>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
@@ -0,0 +1,171 @@
// 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 <boost/range.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
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
{
template <typename Strategy>
static inline bool apply(Range const& range,
SegmentOrBox const& segment_or_box,
Strategy const& strategy)
{
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename ::boost::range_value<view_type>::type point_type;
typedef typename ::boost::range_iterator
<
view_type const
>::type const_iterator;
typedef typename ::boost::range_size<view_type>::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_type const>(view),
segment_or_box,
strategy.template get_point_in_geometry_strategy<Range, SegmentOrBox>());
}
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, strategy) )
{
return false;
}
}
return true;
}
}
};
template
<
typename Linear,
typename SegmentOrBox,
typename Tag = typename tag<Linear>::type
>
struct disjoint_linear_segment_or_box
: not_implemented<Linear, SegmentOrBox>
{};
template <typename Linestring, typename SegmentOrBox>
struct disjoint_linear_segment_or_box<Linestring, SegmentOrBox, linestring_tag>
: disjoint_range_segment_or_box<Linestring, closed, SegmentOrBox>
{};
template <typename MultiLinestring, typename SegmentOrBox>
struct disjoint_linear_segment_or_box
<
MultiLinestring, SegmentOrBox, multi_linestring_tag
> : multirange_constant_size_geometry<MultiLinestring, SegmentOrBox>
{};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Segment>
struct disjoint<Linear, Segment, 2, linear_tag, segment_tag, false>
: detail::disjoint::disjoint_linear_segment_or_box<Linear, Segment>
{};
template <typename Linear, typename Box, std::size_t DimensionCount>
struct disjoint<Linear, Box, DimensionCount, linear_tag, box_tag, false>
: detail::disjoint::disjoint_linear_segment_or_box<Linear, Box>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP
@@ -0,0 +1,332 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2017, 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_DISJOINT_MULTIPOINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
#include <algorithm>
#include <vector>
#include <boost/range.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename MultiPoint1, typename MultiPoint2>
class multipoint_multipoint
{
private:
template <typename Iterator>
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 <typename Point>
inline bool apply(Point const& point) const
{
return !std::binary_search(m_first,
m_last,
point,
static_cast<base_type const&>(*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<MultiPoint1>::type point1_type;
std::vector<point1_type> points1(boost::begin(multipoint1),
boost::end(multipoint1));
std::sort(points1.begin(), points1.end(), detail::relate::less());
typedef unary_disjoint_predicate
<
typename std::vector<point1_type>::const_iterator
> predicate_type;
return check_iterator_range
<
predicate_type
>::apply(boost::begin(multipoint2),
boost::end(multipoint2),
predicate_type(points1.begin(), points1.end()));
}
};
template <typename MultiPoint, typename Linear>
class multipoint_linear
{
private:
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
geometry::expand(total, point);
}
};
// TODO: After adding non-cartesian Segment envelope to the library
// this policy should be modified to take envelope strategy.
struct expand_box_segment
{
template <typename Box, typename Segment>
static inline void apply(Box& total, Segment const& segment)
{
geometry::expand(total, geometry::return_envelope<Box>(segment));
}
};
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough in this case
typedef typename strategy::disjoint::services::default_strategy
<
Point, Box
>::type strategy_type;
return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type());
}
};
// TODO: After implementing disjoint Segment/Box for non-cartesian geometries
// this strategy should be passed here.
// TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy
// which by default is winding containing CS-specific side strategy
// TODO: disjoint Segment/Box will be called in this case which may take
// quite long in non-cartesian CS. So we should consider passing range of bounding boxes
// of segments after calculating them once.
struct overlaps_box_segment
{
template <typename Box, typename Segment>
static inline bool apply(Box const& box, Segment const& segment)
{
typedef typename strategy::disjoint::services::default_strategy
<
Segment, Box
>::type strategy_type;
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
}
};
template <typename PtSegStrategy>
class item_visitor_type
{
public:
item_visitor_type(PtSegStrategy const& strategy)
: m_intersection_found(false)
, m_strategy(strategy)
{}
template <typename Item1, typename Item2>
inline void apply(Item1 const& item1, Item2 const& item2)
{
if (! m_intersection_found
&& ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
{
m_intersection_found = true;
}
}
inline bool intersection_found() const { return m_intersection_found; }
private:
bool m_intersection_found;
PtSegStrategy const& m_strategy;
};
// structs for partition -- end
class segment_range
{
public:
typedef geometry::segment_iterator<Linear const> 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:
template <typename Strategy>
static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy)
{
item_visitor_type<Strategy> visitor(strategy);
geometry::partition
<
geometry::model::box<typename point_type<MultiPoint>::type>
>::apply(multipoint, segment_range(linear), visitor,
expand_box_point(), overlaps_box_point(),
expand_box_segment(), overlaps_box_segment());
return ! visitor.intersection_found();
}
template <typename Strategy>
static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy)
{
return apply(multipoint, linear, strategy);
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point, typename MultiPoint, std::size_t DimensionCount>
struct disjoint
<
Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Point>
{};
template <typename MultiPoint, typename Segment, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Segment>
{};
template <typename MultiPoint, typename Box, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Box>
{};
template
<
typename MultiPoint1,
typename MultiPoint2,
std::size_t DimensionCount
>
struct disjoint
<
MultiPoint1, MultiPoint2, DimensionCount,
multi_point_tag, multi_point_tag, false
>
{
template <typename Strategy>
static inline bool apply(MultiPoint1 const& multipoint1,
MultiPoint2 const& multipoint2,
Strategy const& )
{
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 <typename Linear, typename MultiPoint, std::size_t DimensionCount>
struct disjoint
<
Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false
> : detail::disjoint::multipoint_linear<MultiPoint, Linear>
{};
template <typename MultiPoint, typename Linear, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false
> : detail::disjoint::multipoint_linear<MultiPoint, Linear>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
@@ -0,0 +1,94 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2017, 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_DISJOINT_MULTIRANGE_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename Geometry, typename Strategy, typename BinaryPredicate>
class unary_disjoint_geometry_to_query_geometry
{
public:
unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
Strategy const& strategy)
: m_geometry(geometry)
, m_strategy(strategy)
{}
template <typename QueryGeometry>
inline bool apply(QueryGeometry const& query_geometry) const
{
return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
}
private:
Geometry const& m_geometry;
Strategy const& m_strategy;
};
template<typename MultiRange, typename ConstantSizeGeometry>
struct multirange_constant_size_geometry
{
template <typename Strategy>
static inline bool apply(MultiRange const& multirange,
ConstantSizeGeometry const& constant_size_geometry,
Strategy const& strategy)
{
typedef unary_disjoint_geometry_to_query_geometry
<
ConstantSizeGeometry,
Strategy,
dispatch::disjoint
<
typename boost::range_value<MultiRange>::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, strategy));
}
template <typename Strategy>
static inline bool apply(ConstantSizeGeometry const& constant_size_geometry,
MultiRange const& multirange,
Strategy const& strategy)
{
return apply(multirange, constant_size_geometry, strategy);
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
@@ -0,0 +1,83 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
/*!
\brief Internal utility function to detect if point/box are disjoint
*/
template <typename Point, typename Box>
inline bool disjoint_point_box(Point const& point, Box const& box)
{
typedef typename strategy::disjoint::services::default_strategy
<
Point, Box
>::type strategy_type;
// ! covered_by(point, box)
return ! strategy_type::apply(point, box);
}
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
{
template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& )
{
// ! covered_by(point, box)
return ! Strategy::apply(point, box);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
@@ -0,0 +1,89 @@
// 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 <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
struct reverse_covered_by
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return ! geometry::covered_by(geometry1, geometry2, strategy);
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template<typename Point, typename Linear, std::size_t DimensionCount>
struct disjoint<Point, Linear, DimensionCount, point_tag, linear_tag, false>
: detail::disjoint::reverse_covered_by
{};
template <typename Point, typename Areal, std::size_t DimensionCount>
struct disjoint<Point, Areal, DimensionCount, point_tag, areal_tag, false>
: detail::disjoint::reverse_covered_by
{};
template<typename Point, typename Segment, std::size_t DimensionCount>
struct disjoint<Point, Segment, DimensionCount, point_tag, segment_tag, false>
: detail::disjoint::reverse_covered_by
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
@@ -0,0 +1,247 @@
// 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, 2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <cstddef>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/algorithms/transform.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_point_generic
{
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& )
{
return apply(p1, p2);
}
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
{
return true;
}
return
point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);
}
};
template <std::size_t DimensionCount>
struct point_point_generic<DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const&, Point2 const& )
{
return false;
}
};
class point_point_on_spheroid
{
private:
template <typename Point1, typename Point2, bool SameUnits>
struct are_same_points
{
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
typedef typename helper_geometry<Point1>::type helper_point_type1;
typedef typename helper_geometry<Point2>::type helper_point_type2;
helper_point_type1 point1_normalized
= return_normalized<helper_point_type1>(point1);
helper_point_type2 point2_normalized
= return_normalized<helper_point_type2>(point2);
return point_point_generic
<
0, dimension<Point1>::value
>::apply(point1_normalized, point2_normalized);
}
};
template <typename Point1, typename Point2>
struct are_same_points<Point1, Point2, false> // points have different units
{
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
typedef typename geometry::select_most_precise
<
typename fp_coordinate_type<Point1>::type,
typename fp_coordinate_type<Point2>::type
>::type calculation_type;
typename helper_geometry
<
Point1, calculation_type, radian
>::type helper_point1, helper_point2;
Point1 point1_normalized = return_normalized<Point1>(point1);
Point2 point2_normalized = return_normalized<Point2>(point2);
geometry::transform(point1_normalized, helper_point1);
geometry::transform(point2_normalized, helper_point2);
return point_point_generic
<
0, dimension<Point1>::value
>::apply(helper_point1, helper_point2);
}
};
public:
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
{
return apply(point1, point2);
}
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
return are_same_points
<
Point1,
Point2,
boost::is_same
<
typename coordinate_system<Point1>::type::units,
typename coordinate_system<Point2>::type::units
>::value
>::apply(point1, point2);
}
};
template
<
typename Point1, typename Point2,
std::size_t Dimension, std::size_t DimensionCount,
typename CSTag1 = typename cs_tag<Point1>::type,
typename CSTag2 = CSTag1
>
struct point_point
: point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
{};
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<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
: point_point_generic<Dimension, DimensionCount>
{};
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2>
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
{
return point_point
<
Point1, Point2,
0, dimension<Point1>::type::value
>::apply(point1, point2);
}
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point1, typename Point2, std::size_t DimensionCount>
struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
: detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
@@ -0,0 +1,70 @@
// 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-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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 <cstddef>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
struct disjoint_segment_box
{
template <typename Segment, typename Box, typename Strategy>
static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy)
{
return strategy.apply(segment, box);
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Segment, typename Box, std::size_t DimensionCount>
struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
: detail::disjoint::disjoint_segment_box
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_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 <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template<typename Point, typename Segment, typename Strategy>
struct point_to_segment
{
static inline typename strategy::distance::services::return_type
<
Strategy,
Point,
typename point_type<Segment>::type
>::type
apply(Point const& point, Segment const& segment, Strategy const& )
{
typename detail::distance::default_ps_strategy
<
Point,
typename point_type<Segment>::type,
Strategy
>::type segment_strategy;
typename point_type<Segment>::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 <typename Point, typename Segment, typename Strategy>
struct distance
<
Point, Segment, Strategy,
point_tag, segment_tag, strategy_tag_distance_point_point,
false
> : detail::distance::point_to_segment<Point, Segment, Strategy>
{};
// Point-line version 1, where point-point strategy is specified
template <typename Point, typename Linestring, typename Strategy>
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<Linestring>::type
>::type
apply(Point const& point,
Linestring const& linestring,
Strategy const&)
{
typedef typename detail::distance::default_ps_strategy
<
Point,
typename point_type<Linestring>::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 <typename Point, typename Ring, typename Strategy>
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<Ring>::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<Ring>::type,
Strategy
>::type ps_strategy_type;
return detail::distance::point_to_ring
<
Point, Ring,
geometry::closure<Ring>::value,
ps_strategy_type
>::apply(point, ring, ps_strategy_type());
}
};
// Point-polygon , where point-point strategy is specified
template <typename Point, typename Polygon, typename Strategy>
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<Polygon>::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<Polygon>::type,
Strategy
>::type ps_strategy_type;
return detail::distance::point_to_polygon
<
Point,
Polygon,
geometry::closure<Polygon>::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<MultiGeometry>::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<MultiGeometry>::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<MultiPoint>::type,
typename point_type<Geometry>::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<MultiPoint>::type,
typename point_type<Geometry>::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<MultiPoint>::type,
typename point_type<MultiGeometry>::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<MultiPoint>::type,
typename point_type<MultiGeometry>::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
@@ -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 <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Box1, typename Box2, typename Strategy>
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<Box1>::type,
typename point_type<Box2>::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
@@ -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 <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/strategies/distance.hpp>
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<Geometry1>::type, pointlike_tag
>::type,
typename Tag2 = typename tag_cast
<
typename tag<Geometry2>::type, pointlike_tag
>::type,
bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct default_strategy
: strategy::distance::services::default_strategy
<
point_tag, segment_tag,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>
{};
template
<
typename Geometry1,
typename Geometry2,
typename Tag1,
typename Tag2
>
struct default_strategy<Geometry1, Geometry2, Tag1, Tag2, true>
: default_strategy<Geometry2, Geometry1, Tag2, Tag1, false>
{};
template <typename Pointlike1, typename Pointlike2>
struct default_strategy
<
Pointlike1, Pointlike2,
pointlike_tag, pointlike_tag, false
> : strategy::distance::services::default_strategy
<
point_tag, point_tag,
typename point_type<Pointlike1>::type,
typename point_type<Pointlike2>::type
>
{};
template <typename Pointlike, typename Box>
struct default_strategy<Pointlike, Box, pointlike_tag, box_tag, false>
: strategy::distance::services::default_strategy
<
point_tag, box_tag,
typename point_type<Pointlike>::type,
typename point_type<Box>::type
>
{};
template <typename Box1, typename Box2>
struct default_strategy<Box1, Box2, box_tag, box_tag, false>
: strategy::distance::services::default_strategy
<
box_tag, box_tag,
typename point_type<Box1>::type,
typename point_type<Box2>::type
>
{};
// Helper metafunction for default point-segment strategy retrieval
template <typename Geometry1, typename Geometry2, typename Strategy>
struct default_ps_strategy
: strategy::distance::services::default_strategy
<
point_tag, segment_tag,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
typename cs_tag<typename point_type<Geometry1>::type>::type,
typename cs_tag<typename point_type<Geometry2>::type>::type,
Strategy
>
{};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_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 <iterator>
#include <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/util/condition.hpp>
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<SegmentOrBox>::type
>
struct segment_or_box_point_range_closure
: not_implemented<SegmentOrBox>
{};
template <typename Segment>
struct segment_or_box_point_range_closure<Segment, segment_tag>
{
static const closure_selector value = closed;
};
template <typename Box>
struct segment_or_box_point_range_closure<Box, box_tag>
{
static const closure_selector value = open;
};
template
<
typename Geometry,
typename SegmentOrBox,
typename Strategy,
typename Tag = typename tag<Geometry>::type
>
class geometry_to_segment_or_box
{
private:
typedef typename point_type<SegmentOrBox>::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<Geometry>::type,
std::vector<segment_or_box_point>,
segment_or_box_point_range_closure<SegmentOrBox>::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<Geometry>::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<SegOrBox>::type
>
struct assign_new_min_iterator
: not_implemented<SegOrBox>
{};
template <typename Segment>
struct assign_new_min_iterator<Segment, segment_tag>
{
template <typename Iterator>
static inline void apply(Iterator&, Iterator)
{
}
};
template <typename Box>
struct assign_new_min_iterator<Box, box_tag>
{
template <typename Iterator>
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<SegOrBox>::type
>
struct assign_segment_or_box_points
{};
template <typename Segment, typename PointRange>
struct assign_segment_or_box_points<Segment, PointRange, segment_tag>
{
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 <typename Box, typename PointRange>
struct assign_segment_or_box_points<Box, PointRange, box_tag>
{
static inline void apply(Box const& box, PointRange& range)
{
detail::assign_box_corners_oriented<true>(box, range);
}
};
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry>::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<Geometry const> point_iterator_type;
typedef geometry::segment_iterator
<
Geometry const
> segment_iterator_type;
typedef typename boost::range_const_iterator
<
std::vector<segment_or_box_point>
>::type seg_or_box_const_iterator;
typedef assign_new_min_iterator<SegmentOrBox> 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<segment_or_box_point>
seg_or_box_points(geometry::num_points(segment_or_box));
assign_segment_or_box_points
<
SegmentOrBox,
std::vector<segment_or_box_point>
>::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<Strategy>::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 <typename MultiPoint, typename SegmentOrBox, typename Strategy>
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<SegmentOrBox>::type,
typename point_type<MultiPoint>::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<Strategy>::type,
typename point_type<SegmentOrBox>::type,
typename point_type<MultiPoint>::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<Strategy>::value
?
cd_min
:
dispatch::distance
<
typename point_type<MultiPoint>::type,
SegmentOrBox,
Strategy
>::apply(*it_min, segment_or_box, strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Segment, typename Strategy>
struct distance
<
Linear, Segment, Strategy, linear_tag, segment_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Linear, Segment, Strategy>
{};
template <typename Areal, typename Segment, typename Strategy>
struct distance
<
Areal, Segment, Strategy, areal_tag, segment_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>
{};
template <typename Segment, typename Areal, typename Strategy>
struct distance
<
Segment, Areal, Strategy, segment_tag, areal_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>
{};
template <typename Linear, typename Box, typename Strategy>
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 <typename Areal, typename Box, typename Strategy>
struct distance
<
Areal, Box, Strategy, areal_tag, box_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::geometry_to_segment_or_box<Areal, Box, Strategy>
{};
template <typename MultiPoint, typename Segment, typename Strategy>
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 <typename MultiPoint, typename Box, typename Strategy>
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
@@ -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 <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/box_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/backward_compatibility.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_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 <boost/concept_check.hpp>
#include <boost/mpl/always.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/strategies/distance_result.hpp>
#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
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<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Geometry2>::type,
typename point_type<Geometry1>::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 <typename Geometry1, typename Geometry2, typename Strategy>
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::distance
<
Geometry1, Geometry2, Strategy
>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline
typename distance_result<Geometry1, Geometry2, default_strategy>::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 <typename Geometry1, typename Geometry2>
struct distance
{
template <typename Strategy>
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return
resolve_strategy::distance::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename distance_result
<
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
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 Geometry1>
typename distance_result<Geometry1, Geometry2, Strategy>::type
operator()(Geometry1 const& geometry1) const
{
return distance
<
Geometry1,
Geometry2
>::template apply
<
Strategy
>(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline typename distance_result
<
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Geometry2,
Strategy
>::type
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: static_visitor
<
typename distance_result
<
Geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
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 Geometry2>
typename distance_result<Geometry1, Geometry2, Strategy>::type
operator()(Geometry2 const& geometry2) const
{
return distance
<
Geometry1,
Geometry2
>::template apply
<
Strategy
>(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline typename distance_result
<
Geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Strategy
>::type
apply(
Geometry1 const& geometry1,
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct distance
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
typename distance_result<Geometry1, Geometry2, Strategy>::type
operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
{
return distance
<
Geometry1,
Geometry2
>::template apply
<
Strategy
>(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline typename distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(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 <typename Geometry1, typename Geometry2, typename Strategy>
inline typename distance_result<Geometry1, Geometry2, Strategy>::type
distance(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
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 <typename Geometry1, typename Geometry2>
inline typename default_distance_result<Geometry1, Geometry2>::type
distance(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return geometry::distance(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_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 <boost/type_traits/is_same.hpp>
#include <boost/geometry/strategies/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// metafunction to determine is a strategy is comparable or not
template <typename Strategy>
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
@@ -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 <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// class to choose between point_iterator and segment_iterator
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct iterator_selector
{
typedef geometry::segment_iterator<Geometry> 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 <typename MultiPoint>
struct iterator_selector<MultiPoint, multi_point_tag>
{
typedef geometry::point_iterator<MultiPoint> 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
@@ -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 <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Linear, typename Areal, typename Strategy>
struct linear_to_areal
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Linear>::type,
typename point_type<Areal>::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 <typename Areal1, typename Areal2, typename Strategy>
struct areal_to_areal
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Areal1>::type,
typename point_type<Areal2>::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 <typename Linear, typename Areal, typename Strategy>
struct distance
<
Linear, Areal, Strategy,
linear_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
<
Linear, Areal, Strategy
>
{};
template <typename Areal, typename Linear, typename Strategy>
struct distance
<
Areal, Linear, Strategy,
areal_tag, linear_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
<
Linear, Areal, Strategy
>
{};
template <typename Areal1, typename Areal2, typename Strategy>
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
@@ -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 <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/num_segments.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Linear1, typename Linear2, typename Strategy>
struct linear_to_linear
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Linear1>::type,
typename point_type<Linear2>::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<Linear1>::type,
Linear2,
Strategy
>::apply(*points_begin(linear1), linear2, strategy);
}
if (geometry::num_points(linear2) == 1)
{
return dispatch::distance
<
typename point_type<Linear2>::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<Linear2 const>,
Linear1,
Strategy
>::apply(geometry::segments_begin(linear2),
geometry::segments_end(linear2),
linear1,
strategy);
}
return point_or_segment_range_to_geometry_rtree
<
geometry::segment_iterator<Linear1 const>,
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 <typename Linear1, typename Linear2, typename Strategy>
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
@@ -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 <boost/range.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
struct multipoint_to_multipoint
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint1>::type,
typename point_type<MultiPoint2>::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<MultiPoint2 const>::type,
MultiPoint1,
Strategy
>::apply(boost::begin(multipoint2),
boost::end(multipoint2),
multipoint1,
strategy);
}
return point_or_segment_range_to_geometry_rtree
<
typename boost::range_iterator<MultiPoint1 const>::type,
MultiPoint2,
Strategy
>::apply(boost::begin(multipoint1),
boost::end(multipoint1),
multipoint2,
strategy);
}
};
template <typename MultiPoint, typename Linear, typename Strategy>
struct multipoint_to_linear
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<MultiPoint>::type,
typename point_type<Linear>::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<MultiPoint const>::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 <typename MultiPoint, typename Areal, typename Strategy>
class multipoint_to_areal
{
private:
struct not_covered_by_areal
{
not_covered_by_areal(Areal const& areal)
: m_areal(areal)
{}
template <typename Point>
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<MultiPoint>::type,
typename point_type<Areal>::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<MultiPoint const>::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 <typename MultiPoint1, typename MultiPoint2, typename Strategy>
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 <typename MultiPoint, typename Linear, typename Strategy>
struct distance
<
MultiPoint, Linear, Strategy, multi_point_tag, linear_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
{};
template <typename Linear, typename MultiPoint, typename Strategy>
struct distance
<
Linear, MultiPoint, Strategy, linear_tag, multi_point_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
{};
template <typename MultiPoint, typename Areal, typename Strategy>
struct distance
<
MultiPoint, Areal, Strategy, multi_point_tag, areal_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
{};
template <typename Areal, typename MultiPoint, typename Strategy>
struct distance
<
Areal, MultiPoint, Strategy, areal_tag, multi_point_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_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 <iterator>
#include <boost/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename P1, typename P2, typename Strategy>
struct point_to_point
{
static inline
typename strategy::distance::services::return_type<Strategy, P1, P2>::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<Range>::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<Range>::type
>::type cd_min;
std::pair
<
typename boost::range_iterator<Range const>::type,
typename boost::range_iterator<Range const>::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<Strategy>::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<Ring>::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<Ring>::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<Polygon>::type
>::type return_type;
private:
typedef point_to_range
<
Point, typename ring_type<Polygon>::type, Closure, Strategy
> per_ring;
struct distance_to_interior_rings
{
template <typename InteriorRingIterator>
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 <typename InteriorRings>
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<MultiGeometry>::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<MultiGeometry>::type
>::type return_type;
static inline return_type apply(Point const& point,
MultiGeometry const& multigeometry,
Strategy const& strategy)
{
typedef iterator_selector<MultiGeometry const> selector_type;
namespace sds = strategy::distance::services;
typename sds::return_type
<
typename sds::comparable_type<Strategy>::type,
Point,
typename point_type<MultiGeometry>::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<Strategy>::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 <typename Point, typename MultiPolygon, typename Strategy>
struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
{
typedef typename strategy::distance::services::return_type
<
Strategy,
Point,
typename point_type<MultiPolygon>::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 <typename P1, typename P2, typename Strategy>
struct distance
<
P1, P2, Strategy, point_tag, point_tag,
strategy_tag_distance_point_point, false
> : detail::distance::point_to_point<P1, P2, Strategy>
{};
// Point-line version 2, where point-segment strategy is specified
template <typename Point, typename Linestring, typename Strategy>
struct distance
<
Point, Linestring, Strategy, point_tag, linestring_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
{};
// Point-ring , where point-segment strategy is specified
template <typename Point, typename Ring, typename Strategy>
struct distance
<
Point, Ring, Strategy, point_tag, ring_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_ring
<
Point, Ring, closure<Ring>::value, Strategy
>
{};
// Point-polygon , where point-segment strategy is specified
template <typename Point, typename Polygon, typename Strategy>
struct distance
<
Point, Polygon, Strategy, point_tag, polygon_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_polygon
<
Point, Polygon, closure<Polygon>::value, Strategy
>
{};
// Point-segment version 2, with point-segment strategy
template <typename Point, typename Segment, typename Strategy>
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<Segment>::type
>::type apply(Point const& point,
Segment const& segment,
Strategy const& strategy)
{
typename point_type<Segment>::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 <typename Point, typename Box, typename Strategy>
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<Box>::type
>::type
apply(Point const& point, Box const& box, Strategy const& strategy)
{
boost::ignore_unused(strategy);
return strategy.apply(point, box);
}
};
template<typename Point, typename MultiPoint, typename Strategy>
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<typename Point, typename MultiLinestring, typename Strategy>
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<typename Point, typename MultiPolygon, typename Strategy>
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 <typename Point, typename Linear, typename Strategy>
struct distance
<
Point, Linear, Strategy, point_tag, linear_tag,
strategy_tag_distance_point_segment, false
> : distance
<
Point, Linear, Strategy,
point_tag, typename tag<Linear>::type,
strategy_tag_distance_point_segment, false
>
{};
template <typename Point, typename Areal, typename Strategy>
struct distance
<
Point, Areal, Strategy, point_tag, areal_tag,
strategy_tag_distance_point_segment, false
> : distance
<
Point, Areal, Strategy,
point_tag, typename tag<Areal>::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
@@ -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 <iterator>
#include <utility>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/iterators/has_one_element.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
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<Geometry const> 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<point_or_segment_type>::type,
typename point_type<Geometry>::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<Strategy>::type,
typename point_type<point_or_segment_type>::type,
typename point_type<Geometry>::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<Strategy>::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
@@ -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 <cstddef>
#include <functional>
#include <vector>
#include <boost/core/ignore_unused.hpp>
#include <boost/mpl/if.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/calculation_type.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
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<Segment>::type segment_point;
typedef typename point_type<Box>::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<box_point>,
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_point> box_points(4);
detail::assign_box_corners_oriented<true>(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<box_point>::const_iterator,
typename std::vector<box_point>::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<Strategy>::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<Segment, Box, Strategy, true>
{
private:
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::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_point> box_points(4);
detail::assign_box_corners_oriented<true>(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<Strategy>::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 <typename Result>
struct cast_to_result
{
template <typename T>
static inline Result apply(T const& t)
{
return boost::numeric_cast<Result>(t);
}
};
template <typename T, bool IsLess /* true */>
struct compare_less_equal
{
typedef compare_less_equal<T, !IsLess> other;
template <typename T1, typename T2>
inline bool operator()(T1 const& t1, T2 const& t2) const
{
return std::less_equal<T>()(cast_to_result<T>::apply(t1),
cast_to_result<T>::apply(t2));
}
};
template <typename T>
struct compare_less_equal<T, false>
{
typedef compare_less_equal<T, true> other;
template <typename T1, typename T2>
inline bool operator()(T1 const& t1, T2 const& t2) const
{
return std::greater_equal<T>()(cast_to_result<T>::apply(t1),
cast_to_result<T>::apply(t2));
}
};
template <typename LessEqual>
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 <typename LessEqual>
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<ReturnType> 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 <typename LessEqual>
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<ReturnType> 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 <typename LessEqual>
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<LessEqual>::type
>::apply(p1, p0, top_left, bottom_left,
pp_strategy, ps_strategy);
return true;
}
return false;
}
};
template <typename LessEqual>
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<LessEqual>::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<ReturnType> 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<ReturnType, true> 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<ReturnType, false> 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<SegmentPoint>()(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<Segment, Box>
{};
template
<
typename Segment,
typename Box,
typename PPStrategy,
typename PSStrategy
>
class segment_to_box<Segment, Box, 2, PPStrategy, PSStrategy>
{
private:
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::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<segment_point>()(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 <typename Segment, typename Box, typename Strategy>
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<Segment>::type,
typename point_type<Box>::type
>::type return_type;
static inline return_type apply(Segment const& segment,
Box const& box,
Strategy const& strategy)
{
assert_dimension_equal<Segment, Box>();
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<Segment>::type,
typename point_type<Box>::type
>::type
>::type,
typename detail::distance::default_strategy
<
typename point_type<Segment>::type,
typename point_type<Box>::type
>::type
>::type pp_strategy_type;
return detail::distance::segment_to_box
<
Segment,
Box,
dimension<Segment>::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
@@ -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 <algorithm>
#include <iterator>
#include <boost/core/addressof.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// compute segment-segment distance
template<typename Segment1, typename Segment2, typename Strategy>
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<Segment1>::type,
typename point_type<Segment2>::type
>::type comparable_return_type;
public:
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Segment1>::type,
typename point_type<Segment2>::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<Segment1>::type p[2];
detail::assign_point_from_index<0>(segment1, p[0]);
detail::assign_point_from_index<1>(segment1, p[1]);
typename point_type<Segment2>::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<Strategy>::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 <typename Segment1, typename Segment2, typename Strategy>
struct distance
<
Segment1, Segment2, Strategy, segment_tag, segment_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::segment_to_segment<Segment1, Segment2, Strategy>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
@@ -0,0 +1,172 @@
// 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 Vissarion Fysikopoulos, on behalf of Oracle
// 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 <cstddef>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
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 <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
Dimension,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
template
<
std::size_t Index,
std::size_t DimensionCount
>
struct envelope_indexed_box_on_spheroid
{
template <typename BoxIn, typename BoxOut>
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<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> 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<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
2,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
struct envelope_box
{
template<typename BoxIn, typename BoxOut, typename Strategy>
static inline void apply(BoxIn const& box_in,
BoxOut& mbr,
Strategy const&)
{
envelope_indexed_box
<
min_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
envelope_indexed_box
<
max_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
}
};
struct envelope_box_on_spheroid
{
template <typename BoxIn, typename BoxOut, typename Strategy>
static inline void apply(BoxIn const& box_in,
BoxOut& mbr,
Strategy const&)
{
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
envelope_indexed_box_on_spheroid
<
min_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
envelope_indexed_box_on_spheroid
<
max_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Box, typename CS_Tag>
struct envelope<Box, box_tag, CS_Tag>
: detail::envelope::envelope_box
{};
template <typename Box>
struct envelope<Box, box_tag, spherical_equatorial_tag>
: detail::envelope::envelope_box_on_spheroid
{};
template <typename Box>
struct envelope<Box, box_tag, geographic_tag>
: detail::envelope::envelope_box_on_spheroid
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
@@ -0,0 +1,107 @@
// 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 Vissarion Fysikopoulos, 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.
// 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 <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
struct envelope_polygon
{
template <typename Polygon, typename Box, typename Strategy>
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
{
typename ring_return_type<Polygon const>::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, strategy);
}
else
{
// otherwise, consider only the exterior ring
envelope_range::apply(ext_ring, mbr, strategy);
}
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Ring>
struct envelope<Ring, ring_tag>
: detail::envelope::envelope_range
{};
template <typename Polygon>
struct envelope<Polygon, polygon_tag>
: detail::envelope::envelope_polygon
{};
template <typename MultiPolygon>
struct envelope<MultiPolygon, multi_polygon_tag>
: 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
@@ -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 <cstddef>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct initialize_loop
{
template <typename Box, typename CoordinateType>
static inline void apply(Box& box,
CoordinateType min_value,
CoordinateType max_value)
{
geometry::set<min_corner, Dimension>(box, min_value);
geometry::set<max_corner, Dimension>(box, max_value);
initialize_loop
<
Dimension + 1, DimensionCount
>::apply(box, min_value, max_value);
}
};
template <std::size_t DimensionCount>
struct initialize_loop<DimensionCount, DimensionCount>
{
template <typename Box, typename CoordinateType>
static inline void apply(Box&, CoordinateType, CoordinateType)
{
}
};
template
<
typename Box,
std::size_t Dimension = 0,
std::size_t DimensionCount = dimension<Box>::value
>
struct initialize
{
typedef typename coordinate_type<Box>::type coordinate_type;
static inline void apply(Box& box,
coordinate_type min_value
= boost::numeric::bounds<coordinate_type>::highest(),
coordinate_type max_value
= boost::numeric::bounds<coordinate_type>::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
@@ -0,0 +1,224 @@
// 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, 2017.
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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.
// 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 <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
template <typename Geometry>
struct envelope
{
template <typename Box, typename Strategy>
static inline void apply(Geometry const& geometry,
Box& box,
Strategy const& strategy)
{
dispatch::envelope<Geometry>::apply(geometry, box, strategy);
}
template <typename Box>
static inline void apply(Geometry const& geometry,
Box& box,
default_strategy)
{
typedef typename point_type<Geometry>::type point_type;
typedef typename coordinate_type<point_type>::type coordinate_type;
typedef typename strategy::envelope::services::default_strategy
<
typename cs_tag<point_type>::type,
coordinate_type
>::type strategy_type;
dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry>
struct envelope
{
template <typename Box, typename Strategy>
static inline void apply(Geometry const& geometry,
Box& box,
Strategy const& strategy)
{
concepts::check<Geometry const>();
concepts::check<Box>();
resolve_strategy::envelope<Geometry>::apply(geometry, box, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
Strategy const& m_strategy;
visitor(Box& box, Strategy const& strategy)
: m_box(box)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
envelope<Geometry>::apply(geometry, m_box, m_strategy);
}
};
template <typename Box, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Box& box,
Strategy const& strategy)
{
boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
}
};
} // namespace resolve_variant
/*!
\brief \brief_calc{envelope (with strategy)}
\ingroup envelope
\details \details_calc{envelope,\det_envelope}.
\tparam Geometry \tparam_geometry
\tparam Box \tparam_box
\tparam Strategy \tparam_strategy{Envelope}
\param geometry \param_geometry
\param mbr \param_box \param_set{envelope}
\param strategy \param_strategy{envelope}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/envelope.qbk]}
\qbk{
[heading Example]
[envelope] [envelope_output]
}
*/
template<typename Geometry, typename Box, typename Strategy>
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
{
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
}
/*!
\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<typename Geometry, typename Box>
inline void envelope(Geometry const& geometry, Box& mbr)
{
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
}
/*!
\brief \brief_calc{envelope}
\ingroup envelope
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
\tparam Box \tparam_box
\tparam Geometry \tparam_geometry
\tparam Strategy \tparam_strategy{Envelope}
\param geometry \param_geometry
\param strategy \param_strategy{envelope}
\return \return_calc{envelope}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/envelope.qbk]}
\qbk{
[heading Example]
[return_envelope] [return_envelope_output]
}
*/
template<typename Box, typename Geometry, typename Strategy>
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
{
Box mbr;
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
return 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<typename Box, typename Geometry>
inline Box return_envelope(Geometry const& geometry)
{
Box mbr;
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
return mbr;
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_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 <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
namespace boost { namespace geometry
{
namespace detail { namespace envelope
{
struct intersects_antimeridian
{
template <typename Units, typename CoordinateType>
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 <typename Segment>
static inline bool apply(Segment const& segment)
{
return apply(detail::indexed_point_view<Segment, 0>(segment),
detail::indexed_point_view<Segment, 1>(segment));
}
template <typename Point>
static inline bool apply(Point const& p1, Point const& p2)
{
Point p1_normalized = detail::return_normalized<Point>(p1);
Point p2_normalized = detail::return_normalized<Point>(p2);
return apply
<
typename coordinate_system<Point>::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
@@ -0,0 +1,114 @@
// 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 Vissarion Fysikopoulos, on behalf of Oracle
// 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 <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
struct envelope_linestring_on_spheroid
{
template <typename Linestring, typename Box, typename Strategy>
static inline void apply(Linestring const& linestring,
Box& mbr,
Strategy const& strategy)
{
envelope_range::apply(geometry::segments_begin(linestring),
geometry::segments_end(linestring),
mbr,
strategy);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring, typename CS_Tag>
struct envelope<Linestring, linestring_tag, CS_Tag>
: detail::envelope::envelope_range
{};
template <typename Linestring>
struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
: detail::envelope::envelope_linestring_on_spheroid
{};
template <typename Linestring>
struct envelope<Linestring, linestring_tag, geographic_tag>
: detail::envelope::envelope_linestring_on_spheroid
{};
template <typename MultiLinestring, typename CS_Tag>
struct envelope
<
MultiLinestring, multi_linestring_tag, CS_Tag
> : detail::envelope::envelope_multi_range
<
detail::envelope::envelope_range
>
{};
template <typename MultiLinestring>
struct envelope
<
MultiLinestring, multi_linestring_tag, spherical_equatorial_tag
> : detail::envelope::envelope_multi_range_on_spheroid
<
detail::envelope::envelope_linestring_on_spheroid
>
{};
template <typename MultiLinestring>
struct envelope
<
MultiLinestring, multi_linestring_tag, geographic_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
@@ -0,0 +1,379 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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 <cstddef>
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
class envelope_multipoint_on_spheroid
{
private:
template <std::size_t Dim>
struct coordinate_less
{
template <typename Point>
inline bool operator()(Point const& point1, Point const& point2) const
{
return math::smaller(geometry::get<Dim>(point1),
geometry::get<Dim>(point2));
}
};
template <typename Constants, typename MultiPoint, typename OutputIterator>
static inline void analyze_point_coordinates(MultiPoint const& multipoint,
bool& has_south_pole,
bool& has_north_pole,
OutputIterator oit)
{
typedef typename boost::range_value<MultiPoint>::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<point_type>(*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 <typename SortedRange, typename Value>
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<iterator_type, iterator_type> 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<Iterator, Iterator> 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 <typename MultiPoint, typename Box, typename Strategy>
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy)
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef math::detail::constants_on_spheroid
<
coordinate_type,
typename coordinate_system<MultiPoint>::type::units
> constants;
if (boost::empty(multipoint))
{
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
return;
}
initialize<Box, 0, 2>::apply(mbr);
if (boost::size(multipoint) == 1)
{
return dispatch::envelope
<
typename boost::range_value<MultiPoint>::type
>::apply(range::front(multipoint), mbr, strategy);
}
// analyze the points and put the non-pole ones in the
// points vector
std::vector<point_type> points;
bool has_north_pole = false, has_south_pole = false;
analyze_point_coordinates<constants>(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<constants>(points,
coordinate_less<0>(),
lon_min,
lon_max);
get_min_max_latitudes<constants>(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<MultiPoint>::type::units
>::type helper_box_type;
helper_box_type helper_mbr;
geometry::set<min_corner, 0>(helper_mbr, lon_min);
geometry::set<min_corner, 1>(helper_mbr, lat_min);
geometry::set<max_corner, 0>(helper_mbr, lon_max);
geometry::set<max_corner, 1>(helper_mbr, lat_max);
// now transform to output MBR (per index)
envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy);
for (++it; it != boost::end(multipoint); ++it)
{
detail::expand::point_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
2, dimension<Box>::value
>::apply(mbr, *it, strategy);
}
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename MultiPoint, typename CSTag>
struct envelope<MultiPoint, multi_point_tag, CSTag>
: detail::envelope::envelope_range
{};
template <typename MultiPoint>
struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag>
: detail::envelope::envelope_multipoint_on_spheroid
{};
template <typename MultiPoint>
struct envelope<MultiPoint, multi_point_tag, geographic_tag>
: detail::envelope::envelope_multipoint_on_spheroid
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_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.
// This file was modified by Oracle on 2015, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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 <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_point
{
template <std::size_t Index, typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
detail::indexed_point_view<Box, Index> box_corner(mbr);
detail::conversion::point_to_point
<
Point,
detail::indexed_point_view<Box, Index>,
Dimension,
DimensionCount
>::apply(point, box_corner);
}
template <typename Point, typename Box, typename Strategy>
static inline void apply(Point const& point, Box& mbr, Strategy const&)
{
apply<min_corner>(point, mbr);
apply<max_corner>(point, mbr);
}
};
struct envelope_point_on_spheroid
{
template<typename Point, typename Box, typename Strategy>
static inline void apply(Point const& point, Box& mbr, Strategy const& strategy)
{
Point normalized_point = detail::return_normalized<Point>(point);
typename point_type<Box>::type box_point;
// transform units of input point to units of a box point
transform_units(normalized_point, box_point);
geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
envelope_one_point
<
2, dimension<Point>::value
>::apply(normalized_point, mbr, strategy);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point, typename CS_Tag>
struct envelope<Point, point_tag, CS_Tag>
: detail::envelope::envelope_one_point<0, dimension<Point>::value>
{};
template <typename Point>
struct envelope<Point, point_tag, spherical_equatorial_tag>
: detail::envelope::envelope_point_on_spheroid
{};
template <typename Point>
struct envelope<Point, point_tag, geographic_tag>
: detail::envelope::envelope_point_on_spheroid
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
@@ -0,0 +1,187 @@
// 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 Vissarion Fysikopoulos, 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.
// 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 <iterator>
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/expand/box.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/detail/expand/segment.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
// implementation for simple ranges
struct envelope_range
{
template <typename Iterator, typename Box, typename Strategy>
static inline void apply(Iterator first,
Iterator last,
Box& mbr,
Strategy const& strategy)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
// initialize MBR
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
Iterator it = first;
if (it != last)
{
// initialize box with first element in range
dispatch::envelope<value_type>::apply(*it, mbr, strategy);
// consider now the remaining elements in the range (if any)
for (++it; it != last; ++it)
{
dispatch::expand<Box, value_type>::apply(mbr, *it, strategy);
}
}
}
template <typename Range, typename Box, typename Strategy>
static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
{
return apply(boost::begin(range), boost::end(range), mbr, strategy);
}
};
// implementation for multi-ranges
template <typename EnvelopePolicy>
struct envelope_multi_range
{
template <typename MultiRange, typename Box, typename Strategy>
static inline void apply(MultiRange const& multirange,
Box& mbr,
Strategy const& strategy)
{
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, strategy);
dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy);
}
else
{
// compute the initial envelope
EnvelopePolicy::apply(*it, mbr, strategy);
initialized = true;
}
}
}
if (! initialized)
{
// if not already initialized, initialize MBR
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
}
}
};
// implementation for multi-range on a spheroid (longitude is periodic)
template <typename EnvelopePolicy>
struct envelope_multi_range_on_spheroid
{
template <typename MultiRange, typename Box, typename Strategy>
static inline void apply(MultiRange const& multirange,
Box& mbr,
Strategy const& strategy)
{
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<Box> 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, strategy);
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, strategy);
}
else
{
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
}
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
@@ -0,0 +1,331 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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 <cstddef>
#include <algorithm>
#include <vector>
#include <boost/range.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <typename T>
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 <std::size_t Index>
reference_type get() const
{
return m_end[Index];
}
difference_type length() const
{
return get<1>() - get<0>();
}
private:
T m_end[2];
};
template <typename Units>
struct envelope_range_of_longitudes
{
template <std::size_t Index>
struct longitude_less
{
template <typename Interval>
inline bool operator()(Interval const& i1, Interval const& i2) const
{
return math::smaller(i1.template get<Index>(),
i2.template get<Index>());
}
};
template <typename RangeOfLongitudeIntervals, typename Longitude>
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 <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_range_of_boxes_by_expansion
{
template <typename RangeOfBoxes, typename Box, typename Strategy>
static inline void apply(RangeOfBoxes const& range_of_boxes,
Box& mbr,
Strategy const& strategy)
{
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
typedef typename boost::range_iterator
<
RangeOfBoxes const
>::type iterator_type;
// first initialize MBR
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
detail::indexed_point_view<box_type const, min_corner>
first_box_min(range::front(range_of_boxes));
detail::indexed_point_view<box_type const, max_corner>
first_box_max(range::front(range_of_boxes));
detail::conversion::point_to_point
<
detail::indexed_point_view<box_type const, min_corner>,
detail::indexed_point_view<Box, min_corner>,
Dimension,
DimensionCount
>::apply(first_box_min, mbr_min);
detail::conversion::point_to_point
<
detail::indexed_point_view<box_type const, max_corner>,
detail::indexed_point_view<Box, max_corner>,
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, strategy);
detail::expand::indexed_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
max_corner,
Dimension,
DimensionCount
>::apply(mbr, *it, strategy);
}
}
};
struct envelope_range_of_boxes
{
template <std::size_t Index>
struct latitude_less
{
template <typename Box>
inline bool operator()(Box const& box1, Box const& box2) const
{
return math::smaller(geometry::get<Index, 1>(box1),
geometry::get<Index, 1>(box2));
}
};
template <typename RangeOfBoxes, typename Box, typename Strategy>
static inline void apply(RangeOfBoxes const& range_of_boxes,
Box& mbr,
Strategy const& strategy)
{
// boxes in the range are assumed to be normalized already
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
typedef typename coordinate_type<box_type>::type coordinate_type;
typedef typename coordinate_system<box_type>::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<coordinate_type> interval_type;
typedef std::vector<interval_type> 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<min_corner>());
iterator_type it_max = std::max_element(boost::begin(range_of_boxes),
boost::end(range_of_boxes),
latitude_less<max_corner>());
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<min_corner, 1>(*it);
coordinate_type lat_max = geometry::get<max_corner, 1>(*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<min_corner, 0>(*it);
coordinate_type lon_right = geometry::get<max_corner, 0>(*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<Box, min_corner> mbr_min(mbr);
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
geometry::set<0>(mbr_min, lon_min);
geometry::set<1>(mbr_min, geometry::get<min_corner, 1>(*it_min));
geometry::set<0>(mbr_max, lon_max);
geometry::set<1>(mbr_max, geometry::get<max_corner, 1>(*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<Box>::value
>::apply(range_of_boxes, mbr, strategy);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
@@ -0,0 +1,385 @@
// 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-2017.
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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 <cstddef>
#include <utility>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/srs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/formulas/vertex_latitude.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <typename CalculationType, typename CS_Tag>
struct envelope_segment_call_vertex_latitude
{
template <typename T1, typename T2, typename Strategy>
static inline CalculationType apply(T1 const& lat1,
T2 const& alp1,
Strategy const& )
{
return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
::apply(lat1, alp1);
}
};
template <typename CalculationType>
struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
{
template <typename T1, typename T2, typename Strategy>
static inline CalculationType apply(T1 const& lat1,
T2 const& alp1,
Strategy const& strategy)
{
return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
::apply(lat1, alp1, strategy.model());
}
};
template <typename CS_Tag>
class envelope_segment_impl
{
private:
// degrees or radians
template <typename CalculationType>
static inline void swap(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2)
{
std::swap(lon1, lon2);
std::swap(lat1, lat2);
}
// radians
template <typename CalculationType>
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<CalculationType>();
return (a1 < a2)
? (a1 < pi_half && pi_half < a2)
: (a1 > pi_half && pi_half > a2);
}
// radians or degrees
template <typename Units, typename CoordinateType>
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
}
// degrees or radians
template <typename Units, typename CalculationType, typename Strategy>
static inline void compute_box_corners(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
Strategy const& strategy)
{
// coordinates are assumed to be in radians
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
CalculationType lon1_rad = math::as_radian<Units>(lon1);
CalculationType lat1_rad = math::as_radian<Units>(lat1);
CalculationType lon2_rad = math::as_radian<Units>(lon2);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
CalculationType a1, a2;
strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
if (lat1 > lat2)
{
std::swap(lat1, lat2);
std::swap(lat1_rad, lat2_rad);
std::swap(a1, a2);
}
if (math::equals(a1, a2))
{
// the segment must lie on the equator or is very short
return;
}
if (contains_pi_half(a1, a2))
{
CalculationType p_max = envelope_segment_call_vertex_latitude
<CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
CalculationType const mid_lat = lat1 + lat2;
if (mid_lat < 0)
{
// update using min latitude
CalculationType const lat_min_rad = -p_max;
CalculationType const lat_min
= math::from_radian<Units>(lat_min_rad);
if (lat1 > lat_min)
{
lat1 = lat_min;
}
}
else if (mid_lat > 0)
{
// update using max latitude
CalculationType const lat_max_rad = p_max;
CalculationType const lat_max
= math::from_radian<Units>(lat_max_rad);
if (lat2 < lat_max)
{
lat2 = lat_max;
}
}
}
}
template <typename Units, typename CalculationType, typename Strategy>
static inline void apply(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
Strategy const& strategy)
{
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<Units>(lon1, lon2))
{
lon1 += constants::period();
swap(lon1, lat1, lon2, lat2);
}
compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy);
}
public:
template <
typename Units,
typename CalculationType,
typename Box,
typename Strategy
>
static inline void apply(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
Box& mbr,
Strategy const& strategy)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename helper_geometry
<
Box, box_coordinate_type, Units
>::type helper_box_type;
helper_box_type radian_mbr;
apply<Units>(lon1, lat1, lon2, lat2, strategy);
geometry::set
<
min_corner, 0
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
geometry::set
<
min_corner, 1
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
geometry::set
<
max_corner, 0
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
geometry::set
<
max_corner, 1
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
transform_units(radian_mbr, mbr);
}
};
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_segment
{
template<typename Point, typename Box, typename Strategy>
static inline void apply(Point const& p1,
Point const& p2,
Box& mbr,
Strategy const& strategy)
{
envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy);
detail::expand::point_loop
<
strategy::compare::default_strategy,
strategy::compare::default_strategy,
Dimension,
DimensionCount
>::apply(mbr, p2, strategy);
}
};
template <std::size_t DimensionCount>
struct envelope_segment
{
template <typename Point, typename Box, typename Strategy>
static inline void apply(Point const& p1,
Point const& p2,
Box& mbr,
Strategy const& strategy)
{
// first compute the envelope range for the first two coordinates
strategy.apply(p1, p2, mbr);
// now compute the envelope range for coordinates of
// dimension 2 and higher
envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy);
}
template <typename Segment, typename Box>
static inline void apply(Segment const& segment, Box& mbr)
{
typename point_type<Segment>::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);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Segment>
struct envelope<Segment, segment_tag>
{
template <typename Box, typename Strategy>
static inline void apply(Segment const& segment,
Box& mbr,
Strategy const& strategy)
{
typename point_type<Segment>::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<Segment>::value
>::apply(p[0], p[1], mbr, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_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 <cstddef>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/strategy_transform.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/views/detail/two_dimensional_view.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/transform.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template
<
typename GeometryIn,
typename GeometryOut,
typename TagIn = typename tag<GeometryIn>::type,
typename TagOut = typename tag<GeometryOut>::type
>
struct transform_units_impl
: not_implemented<TagIn, TagOut>
{};
template <typename PointIn, typename PointOut>
struct transform_units_impl<PointIn, PointOut, point_tag, point_tag>
{
static inline void apply(PointIn const& point_in, PointOut& point_out)
{
detail::two_dimensional_view<PointIn const> view_in(point_in);
detail::two_dimensional_view<PointOut> view_out(point_out);
geometry::transform(view_in, view_out);
}
};
template <typename BoxIn, typename BoxOut>
struct transform_units_impl<BoxIn, BoxOut, box_tag, box_tag>
{
template <std::size_t Index>
static inline void apply(BoxIn const& box_in, BoxOut& box_out)
{
typedef detail::indexed_point_view<BoxIn const, Index> view_in_type;
typedef detail::indexed_point_view<BoxOut, Index> 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<min_corner>(box_in, box_out);
apply<max_corner>(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 <typename GeometryIn, typename GeometryOut>
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
@@ -0,0 +1,575 @@
// 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-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// 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_DETAIL_EQUALS_COLLECT_VECTORS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
namespace boost { namespace geometry
{
// TODO: dispatch only by SideStrategy instead of Geometry/CSTag?
// 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 side strategy.
template
<
typename T,
typename Geometry,
typename SideStrategy,
typename CSTag = typename cs_tag<Geometry>::type
>
struct collected_vector
: nyi::not_implemented_tag
{};
// compatible with side_by_triangle cartesian strategy
template <typename T, typename Geometry, typename CT, typename CSTag>
struct collected_vector
<
T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
>
{
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 <typename Point>
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<T>(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;
};
// Compatible with spherical_side_formula which currently
// is the default spherical and geographical strategy
template <typename T, typename Geometry, typename CT, typename CSTag>
struct collected_vector
<
T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
>
{
typedef T type;
typedef typename coordinate_system<Geometry>::type cs_type;
typedef model::point<T, 2, cs_type> point_type;
typedef model::point<T, 3, cs::cartesian> vector_type;
collected_vector()
{}
template <typename Point>
collected_vector(Point const& p1, Point const& p2)
: origin(get<0>(p1), get<1>(p1))
{
origin = detail::return_normalized<point_type>(origin);
using namespace geometry::formula;
prev = sph_to_cart3d<vector_type>(p1);
next = sph_to_cart3d<vector_type>(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
};
// Specialization for spherical polar
template <typename T, typename Geometry, typename CT>
struct collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_polar_tag
>
: public collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_equatorial_tag
>
{
typedef collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_equatorial_tag
> base_type;
collected_vector() {}
template <typename Point>
collected_vector(Point const& p1, Point const& p2)
: base_type(to_equatorial(p1), to_equatorial(p2))
{}
private:
template <typename Point>
Point polar_to_equatorial(Point const& p)
{
typedef typename coordinate_type<Point>::type coord_type;
typedef math::detail::constants_on_spheroid
<
coord_type,
typename coordinate_system<Point>::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;
}
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace collect_vectors
{
template <typename Range, typename Collection>
struct range_collect_vectors
{
typedef typename boost::range_value<Collection>::type item_type;
typedef typename item_type::type calculation_type;
static inline void apply(Collection& collection, Range const& range)
{
typedef geometry::detail::normalized_view
<
Range const
> normalized_range_type;
apply_impl(collection, normalized_range_type(range));
}
private:
template <typename NormalizedRange>
static inline void apply_impl(Collection& collection, NormalizedRange const& range)
{
if (boost::size(range) < 2)
{
return;
}
typedef typename boost::range_size<Collection>::type collection_size_t;
collection_size_t c_old_size = boost::size(collection);
typedef typename boost::range_iterator<NormalizedRange const>::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<Collection>::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<Collection>::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 <typename Box, typename Collection, typename CSTag = typename cs_tag<Box>::type>
struct box_collect_vectors
{
// Calculate on coordinate type, but if it is integer,
// then use double
typedef typename boost::range_value<Collection>::type item_type;
typedef typename item_type::type calculation_type;
static inline void apply(Collection& collection, Box const& box)
{
typename point_type<Box>::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<Collection>::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 <typename Box, typename Collection>
struct box_collect_vectors<Box, Collection, spherical_equatorial_tag>
{
static inline void apply(Collection& collection, Box const& box)
{
typename point_type<Box>::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<Collection>::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 <typename Box, typename Collection>
struct box_collect_vectors<Box, Collection, spherical_polar_tag>
: box_collect_vectors<Box, Collection, spherical_equatorial_tag>
{};
template <typename Box, typename Collection>
struct box_collect_vectors<Box, Collection, geographic_tag>
: box_collect_vectors<Box, Collection, spherical_equatorial_tag>
{};
template <typename Polygon, typename Collection>
struct polygon_collect_vectors
{
static inline void apply(Collection& collection, Polygon const& polygon)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef range_collect_vectors<ring_type, Collection> per_range;
per_range::apply(collection, exterior_ring(polygon));
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_range::apply(collection, *it);
}
}
};
template <typename MultiGeometry, typename Collection, typename SinglePolicy>
struct multi_collect_vectors
{
static inline void apply(Collection& collection, MultiGeometry const& multi)
{
for (typename boost::range_iterator<MultiGeometry const>::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 <typename Collection, typename Box>
struct collect_vectors<box_tag, Collection, Box>
: detail::collect_vectors::box_collect_vectors<Box, Collection>
{};
template <typename Collection, typename Ring>
struct collect_vectors<ring_tag, Collection, Ring>
: detail::collect_vectors::range_collect_vectors<Ring, Collection>
{};
template <typename Collection, typename LineString>
struct collect_vectors<linestring_tag, Collection, LineString>
: detail::collect_vectors::range_collect_vectors<LineString, Collection>
{};
template <typename Collection, typename Polygon>
struct collect_vectors<polygon_tag, Collection, Polygon>
: detail::collect_vectors::polygon_collect_vectors<Polygon, Collection>
{};
template <typename Collection, typename MultiPolygon>
struct collect_vectors<multi_polygon_tag, Collection, MultiPolygon>
: detail::collect_vectors::multi_collect_vectors
<
MultiPolygon,
Collection,
detail::collect_vectors::polygon_collect_vectors
<
typename boost::range_value<MultiPolygon>::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 <typename Collection, typename Geometry>
inline void collect_vectors(Collection& collection, Geometry const& geometry)
{
concepts::check<Geometry const>();
dispatch::collect_vectors
<
typename tag<Geometry>::type,
Collection,
Geometry
>::apply(collection, geometry);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_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 <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
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 <typename Point1, typename Point2>
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
@@ -0,0 +1,129 @@
// 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, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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 <cstddef>
#include <algorithm>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace expand
{
struct box_on_spheroid
{
template <typename BoxOut, typename BoxIn, typename Strategy>
static inline void apply(BoxOut& box_out,
BoxIn const& box_in,
Strategy const& strategy)
{
// 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], strategy);
detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy);
// compute the envelope of the two boxes
detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy);
}
};
}} // 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<BoxIn>::value, StrategyLess, StrategyGreater
>
{
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
(types<CSTagOut, CSTag>()));
};
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
@@ -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 <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/algorithms/detail/expand/segment.hpp>
#include <boost/geometry/algorithms/detail/expand/box.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_IMPLEMENTATION_HPP
@@ -0,0 +1,147 @@
// 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, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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.
// 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 <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
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 <typename Box, typename Geometry, typename Strategy>
static inline void apply(Box& box, Geometry const& source, Strategy const& strategy)
{
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<Index, Dimension>(source);
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
}
if (greater(coord, get<max_corner, Dimension>(box)))
{
set<max_corner, Dimension>(box, coord);
}
indexed_loop
<
StrategyLess, StrategyGreater,
Index, Dimension + 1, DimensionCount
>::apply(box, source, strategy);
}
};
template
<
typename StrategyLess, typename StrategyGreater,
std::size_t Index, std::size_t DimensionCount
>
struct indexed_loop
<
StrategyLess, StrategyGreater,
Index, DimensionCount, DimensionCount
>
{
template <typename Box, typename Geometry, typename Strategy>
static inline void apply(Box&, Geometry const&, Strategy 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 <typename Box, typename Geometry, typename Strategy>
static inline void apply(Box& box,
Geometry const& geometry,
Strategy const& strategy)
{
indexed_loop
<
StrategyLess, StrategyGreater,
0, Dimension, DimensionCount
>::apply(box, geometry, strategy);
indexed_loop
<
StrategyLess, StrategyGreater,
1, Dimension, DimensionCount
>::apply(box, geometry, strategy);
}
};
}} // namespace detail::expand
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
@@ -0,0 +1,199 @@
// 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, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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.
// 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 <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
namespace boost { namespace geometry
{
namespace resolve_strategy
{
template <typename Geometry>
struct expand
{
template <typename Box, typename Strategy>
static inline void apply(Box& box,
Geometry const& geometry,
Strategy const& strategy)
{
dispatch::expand<Box, Geometry>::apply(box, geometry, strategy);
}
template <typename Box>
static inline void apply(Box& box,
Geometry const& geometry,
default_strategy)
{
typedef typename point_type<Geometry>::type point_type;
typedef typename coordinate_type<point_type>::type coordinate_type;
typedef typename strategy::envelope::services::default_strategy
<
typename cs_tag<point_type>::type,
coordinate_type
>::type strategy_type;
dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type());
}
};
} //namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry>
struct expand
{
template <typename Box, typename Strategy>
static inline void apply(Box& box,
Geometry const& geometry,
Strategy const& strategy)
{
concepts::check<Box>();
concepts::check<Geometry const>();
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
resolve_strategy::expand<Geometry>::apply(box, geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
Strategy const& m_strategy;
visitor(Box& box, Strategy const& strategy)
: m_box(box)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
return expand<Geometry>::apply(m_box, geometry, m_strategy);
}
};
template <class Box, typename Strategy>
static inline void
apply(Box& box,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
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<Box, Geometry const>();
dispatch::expand<Box, Geometry>::apply(box, geometry);
}
***/
/*!
\brief Expands (with strategy)
\ingroup expand
\tparam Box type of the box
\tparam Geometry \tparam_geometry
\tparam Strategy \tparam_strategy{expand}
\param box box to be expanded using another geometry, mutable
\param geometry \param_geometry geometry which envelope (bounding box)
\param strategy \param_strategy{expand}
will be added to the box
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/expand.qbk]}
*/
template <typename Box, typename Geometry, typename Strategy>
inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
{
resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
}
/*!
\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 <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& geometry)
{
resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
@@ -0,0 +1,308 @@
// 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, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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.
// 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 <cstddef>
#include <algorithm>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
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 <typename Box, typename Point, typename Strategy>
static inline void apply(Box& box, Point const& source, Strategy const& strategy)
{
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<Dimension>(source);
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
}
if (greater(coord, get<max_corner, Dimension>(box)))
{
set<max_corner, Dimension>(box, coord);
}
point_loop
<
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
>::apply(box, source, strategy);
}
};
template
<
typename StrategyLess,
typename StrategyGreater,
std::size_t DimensionCount
>
struct point_loop
<
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
>
{
template <typename Box, typename Point, typename Strategy>
static inline void apply(Box&, Point const&, Strategy 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 <typename Box, typename Point, typename Strategy>
static inline void apply(Box& box,
Point const& point,
Strategy const& strategy)
{
typedef typename point_type<Box>::type box_point_type;
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef math::detail::constants_on_spheroid
<
box_coordinate_type,
typename coordinate_system<Box>::type::units
> constants;
// normalize input point and input box
Point p_normalized = detail::return_normalized<Point>(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<Box>::type
b_lon_min = geometry::get<min_corner, 0>(box),
b_lat_min = geometry::get<min_corner, 1>(box),
b_lon_max = geometry::get<max_corner, 0>(box),
b_lat_max = geometry::get<max_corner, 1>(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<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 1>(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<min_corner, 0>(box, p_lon);
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 0>(box, p_lon);
geometry::set<max_corner, 1>(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<min_corner, 0>(box, b_lon_min);
geometry::set<min_corner, 1>(box, b_lat_min);
geometry::set<max_corner, 0>(box, b_lon_max);
geometry::set<max_corner, 1>(box, b_lat_max);
point_loop
<
StrategyLess, StrategyGreater, 2, DimensionCount
>::apply(box, point, strategy);
}
};
}} // 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<Point>::value
>
{
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
(types<CSTagOut, CSTag>()));
};
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<Point>::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<Point>::value
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
@@ -0,0 +1,133 @@
// 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, 2016.
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// 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 <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace expand
{
struct segment
{
template <typename Box, typename Segment, typename Strategy>
static inline void apply(Box& box,
Segment const& segment,
Strategy const& strategy)
{
Box mbrs[2];
// compute the envelope of the segment
typename point_type<Segment>::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<Segment>::value
>::apply(p[0], p[1], mbrs[0], strategy);
// normalize the box
detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy);
// compute the envelope of the two boxes
detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy);
}
};
}} // 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<Segment>::value, StrategyLess, StrategyGreater
>
{
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
(types<CSTagOut, CSTag>()));
};
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
{};
template
<
typename Box, typename Segment,
typename StrategyLess, typename StrategyGreater
>
struct expand
<
Box, Segment,
StrategyLess, StrategyGreater,
box_tag, segment_tag,
geographic_tag, geographic_tag
> : detail::expand::segment
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_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 <cstddef>
#include <algorithm>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace expand
{
template
<
typename Point,
template <typename> class PlusOrMinus,
std::size_t I = 0,
std::size_t D = dimension<Point>::value,
bool Enable = boost::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>
struct corner_by_epsilon
{
static inline void apply(Point & point)
{
typedef typename coordinate_type<Point>::type coord_type;
coord_type const coord = get<I>(point);
coord_type const eps = math::scaled_epsilon(coord);
set<I>(point, PlusOrMinus<coord_type>()(coord, eps));
corner_by_epsilon<Point, PlusOrMinus, I+1>::apply(point);
}
};
template
<
typename Point,
template <typename> class PlusOrMinus,
std::size_t I,
std::size_t D
>
struct corner_by_epsilon<Point, PlusOrMinus, I, D, false>
{
static inline void apply(Point const&) {}
};
template
<
typename Point,
template <typename> class PlusOrMinus,
std::size_t D,
bool Enable
>
struct corner_by_epsilon<Point, PlusOrMinus, D, D, Enable>
{
static inline void apply(Point const&) {}
};
template
<
typename Point,
template <typename> class PlusOrMinus,
std::size_t D
>
struct corner_by_epsilon<Point, PlusOrMinus, D, D, false>
{
static inline void apply(Point const&) {}
};
} // namespace expand
template <typename Box>
inline void expand_by_epsilon(Box & box)
{
typedef detail::indexed_point_view<Box, min_corner> min_type;
min_type min_point(box);
expand::corner_by_epsilon<min_type, std::minus>::apply(min_point);
typedef detail::indexed_point_view<Box, max_corner> max_type;
max_type max_point(box);
expand::corner_by_epsilon<max_type, std::plus>::apply(max_point);
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_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 <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace extreme_points
{
template <std::size_t Dimension>
struct compare
{
template <typename Point>
inline bool operator()(Point const& lhs, Point const& rhs)
{
return geometry::get<Dimension>(lhs) < geometry::get<Dimension>(rhs);
}
};
template <std::size_t Dimension, typename PointType, typename CoordinateType>
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<Dimension>(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<Dimension>(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<Dimension>(extreme);
multiply_value(vector, base_diff);
divide_value(vector, diff);
// The real move:
point = extreme;
add_point(point, vector);
}
template <std::size_t Dimension, typename Range, typename CoordinateType>
inline void move_along_vector(Range& range, CoordinateType const& base_value)
{
if (range.size() >= 3)
{
move_along_vector<Dimension>(range.front(), *(range.begin() + 1), base_value);
move_along_vector<Dimension>(range.back(), *(range.rbegin() + 1), base_value);
}
}
template<typename Ring, std::size_t Dimension>
struct extreme_points_on_ring
{
typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
typedef typename boost::range_iterator<Ring const>::type range_iterator;
typedef typename geometry::point_type<Ring>::type point_type;
typedef typename geometry::strategy::side::services::default_strategy
<
typename geometry::cs_tag<point_type>::type
>::type side_strategy;
template <typename CirclingIterator, typename Points>
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<Dimension>(*it), max_coordinate_value));
return true;
}
// Overload without adding to poinst
template <typename CirclingIterator>
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<Dimension>(*it), max_coordinate_value));
return true;
}
template <typename CirclingIterator>
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<Dimension>(extreme);
if (! extend(left, n, max_coordinate_value, -1))
{
return false;
}
if (! extend(right, n, max_coordinate_value, +1))
{
return false;
}
return true;
}
template <typename Collection, typename CirclingIterator>
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<Dimension>(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 <typename Extremes, typename Intruders, typename CirclingIterator>
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<Dimension>(*std::min_element(boost::begin(extremes), boost::end(extremes), compare<Dimension>()));
// 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<Dimension>(*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<Ring>::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<Intruders>::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<Dimension>(intruder, min_value);
intruders.push_back(intruder);
--right;
}
}
++right;
defensive_check_index++;
}
}
template <typename Extremes, typename Intruders>
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<Ring const> left(ring);
geometry::ever_circling_range_iterator<Ring const> right(ring);
++right;
get_intruders(ring, left, right, extremes, intruders);
}
}
template <typename Iterator>
static inline bool right_turn(Ring const& ring, Iterator it)
{
typename std::iterator_traits<Iterator>::difference_type const index
= std::distance(boost::begin(ring), it);
geometry::ever_circling_range_iterator<Ring const> left(ring);
geometry::ever_circling_range_iterator<Ring const> right(ring);
left += index;
right += index;
if (! extent_both_sides(ring, *it, left, right))
{
return false;
}
int const factor = geometry::point_order<Ring>::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 <typename Extremes, typename Intruders>
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<Dimension> 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<range_iterator>::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<Ring const> left(ring);
geometry::ever_circling_range_iterator<Ring const> right(ring);
left += index;
right += index;
// Collect all points (often 3) in a temporary vector
std::vector<point_type> 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<Dimension>(points.front());
coordinate_type const back_value = geometry::get<Dimension>(points.back());
coordinate_type const base_value = (std::max)(front_value, back_value);
if (front_value < back_value)
{
move_along_vector<Dimension>(points.front(), *(points.begin() + 1), base_value);
}
else
{
move_along_vector<Dimension>(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<Geometry>::type
>
struct extreme_points
{};
template<typename Ring, std::size_t Dimension>
struct extreme_points<Ring, Dimension, ring_tag>
: detail::extreme_points::extreme_points_on_ring<Ring, Dimension>
{};
template<typename Polygon, std::size_t Dimension>
struct extreme_points<Polygon, Dimension, polygon_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders)
{
typedef typename geometry::ring_type<Polygon>::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<Polygon const>::type
rings = interior_rings(polygon);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
{
ring_implementation::get_intruders(*it, extremes, intruders);
}
return true;
}
};
template<typename Box>
struct extreme_points<Box, 1, box_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
{
extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
// ll,ul,ur,lr, contains too exactly the right info
return true;
}
};
template<typename Box>
struct extreme_points<Box, 0, box_tag>
{
template <typename Extremes, typename Intruders>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
{
extremes.resize(4);
geometry::detail::assign_box_corners_oriented<false>(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<typename MultiPolygon, std::size_t Dimension>
struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
{
template <typename Extremes, typename Intruders>
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<MultiPolygon const>::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 <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders>
inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders)
{
concepts::check<Geometry const>();
// 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<typename boost::range_value<Extremes>::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<Intruders>::type
>::type
const
>();
return dispatch::extreme_points<Geometry, Edge>::apply(geometry, extremes, intruders);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_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 <boost/mpl/assert.hpp>
#include <boost/concept/requires.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/add_const_if_c.hpp>
#include <boost/geometry/views/box_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace for_each
{
template <typename Range, typename Actor>
struct fe_range_range
{
static inline void apply(Range & range, Actor & actor)
{
actor.apply(range);
}
};
template <typename Polygon, typename Actor>
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 <typename Box, typename Actor>
struct fe_range_box
{
static inline void apply(Box & box, Actor & actor)
{
actor.apply(box_view<typename boost::remove_const<Box>::type>(box));
}
};
template <typename Multi, typename Actor, typename SinglePolicy>
struct fe_range_multi
{
static inline void apply(Multi & multi, Actor & actor)
{
for ( typename boost::range_iterator<Multi>::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<Geometry>::type
>
struct for_each_range
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
, (types<Geometry>)
);
};
template <typename Linestring, typename Actor>
struct for_each_range<Linestring, Actor, linestring_tag>
: detail::for_each::fe_range_range<Linestring, Actor>
{};
template <typename Ring, typename Actor>
struct for_each_range<Ring, Actor, ring_tag>
: detail::for_each::fe_range_range<Ring, Actor>
{};
template <typename Polygon, typename Actor>
struct for_each_range<Polygon, Actor, polygon_tag>
: detail::for_each::fe_range_polygon<Polygon, Actor>
{};
template <typename Box, typename Actor>
struct for_each_range<Box, Actor, box_tag>
: detail::for_each::fe_range_box<Box, Actor>
{};
template <typename MultiPoint, typename Actor>
struct for_each_range<MultiPoint, Actor, multi_point_tag>
: detail::for_each::fe_range_range<MultiPoint, Actor>
{};
template <typename Geometry, typename Actor>
struct for_each_range<Geometry, Actor, multi_linestring_tag>
: detail::for_each::fe_range_multi
<
Geometry,
Actor,
detail::for_each::fe_range_range
<
typename add_const_if_c
<
boost::is_const<Geometry>::value,
typename boost::range_value<Geometry>::type
>::type,
Actor
>
>
{};
template <typename Geometry, typename Actor>
struct for_each_range<Geometry, Actor, multi_polygon_tag>
: detail::for_each::fe_range_multi
<
Geometry,
Actor,
detail::for_each::fe_range_polygon
<
typename add_const_if_c
<
boost::is_const<Geometry>::value,
typename boost::range_value<Geometry>::type
>::type,
Actor
>
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace detail
{
template <typename Geometry, typename Actor>
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
@@ -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 <boost/geometry/core/assert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/iterators/closing_iterator.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// TODO: move this to /util/
template <typename T>
inline std::pair<T, T> 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 <typename Vector>
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 <typename Vector>
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 <typename Point>
struct angle_less
{
typedef Point vector_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side_strategy_type;
angle_less(Point const& origin)
: m_origin(origin)
{}
template <typename Angle>
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 <typename Point>
struct angle_equal_to
{
typedef Point vector_type;
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side_strategy_type;
inline angle_equal_to(Point const& origin)
: m_origin(origin)
{}
template <typename Angle>
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 <typename AngleCollection, typename Turns>
inline void get_left_turns(AngleCollection const& sorted_angles,
Turns& turns)
{
std::set<std::size_t> good_incoming;
std::set<std::size_t> good_outgoing;
for (typename boost::range_iterator<AngleCollection const>::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<AngleCollection const>::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 <typename Point, typename AngleCollection>
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<Point> comparator(origin);
typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
std::size_t cluster_index = 0;
it->cluster_index = cluster_index;
typename boost::range_iterator<AngleCollection>::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 <typename AngleCollection>
inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)
{
BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0);
std::vector<std::pair<bool, bool> > directions;
for (std::size_t i = 0; i < cluster_size; i++)
{
directions.push_back(std::make_pair(false, false));
}
for (typename boost::range_iterator<AngleCollection const>::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<AngleCollection>::type it = sorted.begin();
it != sorted.end(); ++it)
{
signed_size_type cluster_index = static_cast<signed_size_type>(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<signed_size_type>(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 <typename AngleCollection, typename Point>
inline bool has_rounding_issues(AngleCollection const& angles, Point const& origin)
{
for (typename boost::range_iterator<AngleCollection const>::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
@@ -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 <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Box, std::size_t Dimension>
struct get_max_size_box
{
static inline typename coordinate_type<Box>::type apply(Box const& box)
{
typename coordinate_type<Box>::type s
= geometry::math::abs(geometry::get<1, Dimension>(box) - geometry::get<0, Dimension>(box));
return (std::max)(s, get_max_size_box<Box, Dimension - 1>::apply(box));
}
};
template <typename Box>
struct get_max_size_box<Box, 0>
{
static inline typename coordinate_type<Box>::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 <typename Box>
inline typename coordinate_type<Box>::type get_max_size(Box const& box)
{
return get_max_size_box<Box, dimension<Box>::value - 1>::apply(box);
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
@@ -0,0 +1,164 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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_HAS_SELF_INTERSECTIONS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
#include <deque>
#include <boost/range.hpp>
#include <boost/throw_exception.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
# include <boost/geometry/io/dsv/write.hpp>
#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 <typename Geometry, typename Strategy, typename RobustPolicy>
inline bool has_self_intersections(Geometry const& geometry,
Strategy const& strategy,
RobustPolicy const& robust_policy,
bool throw_on_self_intersection = true)
{
typedef typename point_type<Geometry>::type point_type;
typedef turn_info
<
point_type,
typename segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
std::deque<turn_info> turns;
detail::disjoint::disjoint_interrupt_policy policy;
geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
bool first = true;
#endif
for(typename std::deque<turn_info>::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)
{
BOOST_THROW_EXCEPTION(overlay_invalid_input_exception());
}
#endif
return true;
}
}
return false;
}
// For backward compatibility
template <typename Geometry>
inline bool has_self_intersections(Geometry const& geometry,
bool throw_on_self_intersection = true)
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename geometry::rescale_policy_type<point_type>::type
rescale_policy_type;
typename strategy::intersection::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
return has_self_intersections(geometry, strategy, 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
@@ -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 <boost/range/iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/interior_type.hpp>
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 <typename Geometry>
struct interior_iterator
{
typedef typename boost::range_iterator
<
typename geometry::interior_type<Geometry>::type
>::type type;
};
template <typename BaseT, typename T>
struct copy_const
{
typedef T type;
};
template <typename BaseT, typename T>
struct copy_const<BaseT const, T>
{
typedef T const type;
};
template <typename Geometry>
struct interior_ring_iterator
{
typedef typename boost::range_iterator
<
typename copy_const
<
typename geometry::interior_type<Geometry>::type,
typename boost::range_value
<
typename geometry::interior_type<Geometry>::type
>::type
>::type
>::type type;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_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 <boost/geometry/algorithms/detail/intersection/interface.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp>
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<Box1>::value
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_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 <boost/geometry/algorithms/detail/intersection/box_box.hpp>
#include <boost/geometry/algorithms/detail/intersection/multi.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP
@@ -0,0 +1,398 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014-2017, 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
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/range.hpp>
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<Geometry1>::type,
typename Tag2 = typename geometry::tag<Geometry2>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct intersection
{
template <typename RobustPolicy, typename GeometryOut, typename Strategy>
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<GeometryOut>::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<Geometry2, Geometry1, Tag2, Tag1, false>
{
template <typename RobustPolicy, typename GeometryOut, typename Strategy>
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_strategy {
struct intersection
{
template
<
typename Geometry1,
typename Geometry2,
typename RobustPolicy,
typename GeometryOut,
typename Strategy
>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
GeometryOut & geometry_out,
Strategy const& strategy)
{
return dispatch::intersection
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, robust_policy, geometry_out,
strategy);
}
template
<
typename Geometry1,
typename Geometry2,
typename RobustPolicy,
typename GeometryOut
>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
GeometryOut & geometry_out,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
<
Geometry1, Geometry2
>::type strategy_type;
return dispatch::intersection
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, robust_policy, geometry_out,
strategy_type());
}
};
} // resolve_strategy
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct intersection
{
template <typename GeometryOut, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
typedef typename geometry::rescale_overlay_policy_type
<
Geometry1,
Geometry2
>::type rescale_policy_type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
geometry2);
return resolve_strategy::intersection::apply(geometry1,
geometry2,
robust_policy,
geometry_out,
strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
GeometryOut& m_geometry_out;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
: m_geometry2(geometry2)
, m_geometry_out(geometry_out)
, m_strategy(strategy)
{}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return intersection
<
Geometry1,
Geometry2
>::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
}
};
template <typename GeometryOut, typename Strategy>
static inline bool
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
geometry_out,
strategy),
geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
GeometryOut& m_geometry_out;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1,
GeometryOut& geometry_out,
Strategy const& strategy)
: m_geometry1(geometry1)
, m_geometry_out(geometry_out)
, m_strategy(strategy)
{}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return intersection
<
Geometry1,
Geometry2
>::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
}
};
template <typename GeometryOut, typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
geometry_out,
strategy),
geometry2);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
template <typename GeometryOut, typename Strategy>
struct visitor: static_visitor<bool>
{
GeometryOut& m_geometry_out;
Strategy const& m_strategy;
visitor(GeometryOut& geometry_out, Strategy const& strategy)
: m_geometry_out(geometry_out)
, m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return intersection
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, m_geometry_out, m_strategy);
}
};
template <typename GeometryOut, typename Strategy>
static inline bool
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
strategy),
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)
\tparam Strategy \tparam_strategy{Intersection}
\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)
\param strategy \param_strategy{intersection}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/intersection.qbk]}
*/
template
<
typename Geometry1,
typename Geometry2,
typename GeometryOut,
typename Strategy
>
inline bool intersection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
return resolve_variant::intersection
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, geometry_out, strategy);
}
/*!
\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
>::apply(geometry1, geometry2, geometry_out, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_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 <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/geometry_id.hpp>
#include <boost/geometry/core/is_areal.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
// TODO: those headers probably may be removed
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersection
{
template <typename PointOut>
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<PointOut>
::apply(*it1, *it2, robust_policy, out, strategy);
}
}
return out;
}
};
template <typename PointOut>
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<PointOut>
::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 <typename LinestringOut>
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<LinestringOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
for (typename boost::range_iterator<MultiLinestring const>::type it
= boost::begin(multi_linestring);
it != boost::end(multi_linestring); ++it)
{
out = detail::intersection::clip_range_with_box
<LinestringOut>(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
@@ -0,0 +1,85 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2017, 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_SIMPLE_ALWAYS_SIMPLE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace is_simple
{
template <typename Geometry>
struct always_simple
{
template <typename Strategy>
static inline bool apply(Geometry const&, Strategy const&)
{
return true;
}
};
}} // namespace detail::is_simple
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// A point is always simple
template <typename Point>
struct is_simple<Point, point_tag>
: detail::is_simple::always_simple<Point>
{};
// 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 <typename Segment>
struct is_simple<Segment, segment_tag>
: detail::is_simple::always_simple<Segment>
{};
// 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 <typename Box>
struct is_simple<Box, box_tag>
: detail::is_simple::always_simple<Box>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP

Some files were not shown because too many files have changed in this diff Show More