add boost on mac

This commit is contained in:
Bassem Girgis
2019-08-10 16:38:17 -05:00
parent 861b918727
commit be945cb63b
14105 changed files with 2714968 additions and 0 deletions

View File

@@ -0,0 +1,378 @@
// 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;
typedef typename ring_return_type<Polygon>::type exterior_ring_type;
typedef typename interior_return_type<Polygon>::type interior_ring_range_type;
static inline void apply(Polygon& polygon, Point const& point,
int ring_index, int = 0)
{
if (ring_index == -1)
{
exterior_ring_type ext_ring = exterior_ring(polygon);
append_point<ring_type, Point>::apply(
ext_ring, point);
}
else if (ring_index < int(num_interior_rings(polygon)))
{
interior_ring_range_type int_rings = interior_rings(polygon);
append_point<ring_type, Point>::apply(
range::at(int_rings, ring_index), point);
}
}
};
template <typename Polygon, typename Range>
struct range_to_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
typedef typename ring_return_type<Polygon>::type exterior_ring_type;
typedef typename interior_return_type<Polygon>::type interior_ring_range_type;
static inline void apply(Polygon& polygon, Range const& range,
int ring_index, int = 0)
{
if (ring_index == -1)
{
exterior_ring_type ext_ring = exterior_ring(polygon);
append_range<ring_type, Range>::apply(
ext_ring, range);
}
else if (ring_index < int(num_interior_rings(polygon)))
{
interior_ring_range_type int_rings = interior_rings(polygon);
append_range<ring_type, Range>::apply(
range::at(int_rings, 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

View File

@@ -0,0 +1,369 @@
// 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) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018 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/core/ignore_unused.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/area_result.hpp>
#include <boost/geometry/strategies/default_area_result.hpp>
#include <boost/geometry/strategies/default_strategy.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 area_result<Ring, Strategy>::type
apply(Ring const& ring, Strategy const& strategy)
{
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Ring, Strategy>) );
assert_dimension<Ring, 2>();
// Ignore warning (because using static method sometimes) on strategy
boost::ignore_unused(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 area_result<Ring, Strategy>::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::template state<Ring> 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 area_result<Geometry, Strategy>::type
apply(Geometry const& geometry, Strategy const& strategy)
{
return calculate_null::apply
<
typename area_result<Geometry, Strategy>::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 area_result<Polygon, Strategy>::type
apply(Polygon const& polygon, Strategy const& strategy)
{
return calculate_polygon_sum::apply<
typename area_result<Polygon, Strategy>::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 area_result<MultiGeometry, Strategy>::type
apply(MultiGeometry const& multi, Strategy const& strategy)
{
return multi_sum::apply
<
typename area_result<MultiGeometry, Strategy>::type,
area<typename boost::range_value<MultiGeometry>::type>
>(multi, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
template <typename Strategy>
struct area
{
template <typename Geometry>
static inline typename area_result<Geometry, Strategy>::type
apply(Geometry const& geometry, Strategy const& strategy)
{
return dispatch::area<Geometry>::apply(geometry, strategy);
}
};
template <>
struct area<default_strategy>
{
template <typename Geometry>
static inline typename area_result<Geometry>::type
apply(Geometry const& geometry, default_strategy)
{
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy_type;
return dispatch::area<Geometry>::apply(geometry, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry>
struct area
{
template <typename Strategy>
static inline typename area_result<Geometry, Strategy>::type
apply(Geometry const& geometry, Strategy const& strategy)
{
return resolve_strategy::area<Strategy>::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
template <typename Strategy>
struct visitor
: boost::static_visitor<typename area_result<variant_type, Strategy>::type>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
typename area_result<variant_type, Strategy>::type
operator()(Geometry const& geometry) const
{
return area<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline typename area_result<variant_type, Strategy>::type
apply(variant_type 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 area_result<Geometry>::type
area(Geometry const& geometry)
{
concepts::check<Geometry const>();
// detail::throw_on_empty_input(geometry);
return resolve_variant::area<Geometry>::apply(geometry, default_strategy());
}
/*!
\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 Available Strategies]
\* [link geometry.reference.strategies.strategy_area_cartesian Cartesian]
\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
\* [link geometry.reference.strategies.strategy_area_geographic Geographic]
[heading Example]
[area_with_strategy]
[area_with_strategy_output]
}
*/
template <typename Geometry, typename Strategy>
inline typename area_result<Geometry, Strategy>::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

View File

@@ -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

View File

@@ -0,0 +1,262 @@
// 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_box.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
namespace boost { namespace geometry
{
#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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,581 @@
// 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 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_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/clear.hpp>
#include <boost/geometry/algorithms/for_each.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;
struct default_policy
{
template <typename Point1, typename Point2>
static inline void apply(Point1 const& point1, Point2 & point2)
{
geometry::detail::conversion::convert_point_to_point(point1, point2);
}
};
static inline void apply(Range1 const& source, Range2& destination)
{
apply(source, destination, default_policy());
}
template <typename ConvertPointPolicy>
static inline ConvertPointPolicy apply(Range1 const& source, Range2& destination,
ConvertPointPolicy convert_point)
{
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)
{
typename boost::range_value<Range2>::type point;
convert_point.apply(*it, point);
range::push_back(destination, point);
}
return convert_point;
}
};
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

View File

@@ -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

View File

@@ -0,0 +1,360 @@
// 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-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_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/correct_closure.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/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
{
template <typename Strategy>
static inline void apply(Geometry& , Strategy const& )
{}
};
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
{
template <typename Strategy>
static inline void apply(Box& box, Strategy const& )
{
// 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, template <typename> class Predicate>
struct correct_ring
{
typedef typename point_type<Ring>::type point_type;
typedef typename coordinate_type<Ring>::type coordinate_type;
typedef detail::area::ring_area
<
order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value
> ring_area_type;
template <typename Strategy>
static inline void apply(Ring& r, Strategy const& strategy)
{
// Correct closure if necessary
detail::correct_closure::close_or_open_ring<Ring>::apply(r);
// Check area
typedef typename area_result<Ring, Strategy>::type area_result_type;
Predicate<area_result_type> predicate;
area_result_type const zero = 0;
if (predicate(ring_area_type::apply(r, strategy), 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;
template <typename Strategy>
static inline void apply(Polygon& poly, Strategy const& strategy)
{
correct_ring
<
ring_type,
std::less
>::apply(exterior_ring(poly), strategy);
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
>::apply(*it, strategy);
}
}
};
}} // 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
>
{};
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
{
template <typename Strategy>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
dispatch::correct<Geometry>::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<void>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
void operator()(Geometry& geometry) const
{
correct<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
{
boost::apply_visitor(visitor<Strategy>(strategy), 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)
{
typedef typename point_type<Geometry>::type point_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type
>::type strategy_type;
resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
}
/*!
\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
\tparam Strategy \tparam_strategy{Area}
\param geometry \param_geometry which will be corrected if necessary
\param strategy \param_strategy{area}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/correct.qbk]}
*/
template <typename Geometry, typename Strategy>
inline void correct(Geometry& geometry, Strategy const& strategy)
{
resolve_variant::correct<Geometry>::apply(geometry, strategy);
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP

View File

@@ -0,0 +1,235 @@
// Boost.Geometry
// Copyright (c) 2017 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_CORRECT_CLOSURE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
#include <cstddef>
#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/detail/interior_iterator.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/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.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_closure
{
template <typename Geometry>
struct nop
{
static inline void apply(Geometry& )
{}
};
// Close a ring, if not closed, or open it
template <typename Ring>
struct close_or_open_ring
{
static inline void apply(Ring& r)
{
if (boost::size(r) <= 2)
{
return;
}
bool const disjoint = geometry::disjoint(*boost::begin(r),
*(boost::end(r) - 1));
closure_selector const s = geometry::closure<Ring>::value;
if (disjoint && s == closed)
{
// Close it by adding first point
geometry::append(r, *boost::begin(r));
}
else if (! disjoint && s != closed)
{
// Open it by removing last point
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
}
}
};
// Close/open exterior ring and all its interior rings
template <typename Polygon>
struct close_or_open_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
static inline void apply(Polygon& poly)
{
close_or_open_ring<ring_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)
{
close_or_open_ring<ring_type>::apply(*it);
}
}
};
}} // namespace detail::correct_closure
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct correct_closure: not_implemented<Tag>
{};
template <typename Point>
struct correct_closure<Point, point_tag>
: detail::correct_closure::nop<Point>
{};
template <typename LineString>
struct correct_closure<LineString, linestring_tag>
: detail::correct_closure::nop<LineString>
{};
template <typename Segment>
struct correct_closure<Segment, segment_tag>
: detail::correct_closure::nop<Segment>
{};
template <typename Box>
struct correct_closure<Box, box_tag>
: detail::correct_closure::nop<Box>
{};
template <typename Ring>
struct correct_closure<Ring, ring_tag>
: detail::correct_closure::close_or_open_ring<Ring>
{};
template <typename Polygon>
struct correct_closure<Polygon, polygon_tag>
: detail::correct_closure::close_or_open_polygon<Polygon>
{};
template <typename MultiPoint>
struct correct_closure<MultiPoint, multi_point_tag>
: detail::correct_closure::nop<MultiPoint>
{};
template <typename MultiLineString>
struct correct_closure<MultiLineString, multi_linestring_tag>
: detail::correct_closure::nop<MultiLineString>
{};
template <typename Geometry>
struct correct_closure<Geometry, multi_polygon_tag>
: detail::multi_modify
<
Geometry,
detail::correct_closure::close_or_open_polygon
<
typename boost::range_value<Geometry>::type
>
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant
{
template <typename Geometry>
struct correct_closure
{
static inline void apply(Geometry& geometry)
{
concepts::check<Geometry const>();
dispatch::correct_closure<Geometry>::apply(geometry);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct_closure<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: boost::static_visitor<void>
{
template <typename Geometry>
void operator()(Geometry& geometry) const
{
correct_closure<Geometry>::apply(geometry);
}
};
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
{
visitor vis;
boost::apply_visitor(vis, geometry);
}
};
} // namespace resolve_variant
/*!
\brief Closes or opens a geometry, according to its type
\details Corrects a geometry w.r.t. closure points to all rings which do not
have a closing point and are typed as they should have one, the first point
is appended.
\ingroup correct_closure
\tparam Geometry \tparam_geometry
\param geometry \param_geometry which will be corrected if necessary
*/
template <typename Geometry>
inline void correct_closure(Geometry& geometry)
{
resolve_variant::correct_closure<Geometry>::apply(geometry);
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP

View File

@@ -0,0 +1,27 @@
// 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 <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP

View File

@@ -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

View File

@@ -0,0 +1,432 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// 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_DENSIFY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/throw_exception.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace densify
{
template <typename Range>
struct push_back_policy
{
typedef typename boost::range_value<Range>::type point_type;
inline explicit push_back_policy(Range & rng)
: m_rng(rng)
{}
inline void apply(point_type const& p)
{
range::push_back(m_rng, p);
}
private:
Range & m_rng;
};
template <typename Range, typename Point>
inline void convert_and_push_back(Range & range, Point const& p)
{
typename boost::range_value<Range>::type p2;
geometry::detail::conversion::convert_point_to_point(p, p2);
range::push_back(range, p2);
}
template <bool AppendLastPoint = true>
struct densify_range
{
template <typename FwdRng, typename MutRng, typename T, typename Strategy>
static inline void apply(FwdRng const& rng, MutRng & rng_out,
T const& len, Strategy const& strategy)
{
typedef typename boost::range_iterator<FwdRng const>::type iterator_t;
typedef typename boost::range_value<FwdRng>::type point_t;
iterator_t it = boost::begin(rng);
iterator_t end = boost::end(rng);
if (it == end) // empty(rng)
{
return;
}
push_back_policy<MutRng> policy(rng_out);
iterator_t prev = it;
for ( ++it ; it != end ; prev = it++)
{
point_t const& p0 = *prev;
point_t const& p1 = *it;
convert_and_push_back(rng_out, p0);
strategy.apply(p0, p1, policy, len);
}
if (BOOST_GEOMETRY_CONDITION(AppendLastPoint))
{
convert_and_push_back(rng_out, *prev); // back(rng)
}
}
};
template <bool IsClosed1, bool IsClosed2> // false, X
struct densify_ring
{
template <typename Geometry, typename GeometryOut, typename T, typename Strategy>
static inline void apply(Geometry const& ring, GeometryOut & ring_out,
T const& len, Strategy const& strategy)
{
geometry::detail::densify::densify_range<true>
::apply(ring, ring_out, len, strategy);
if (boost::size(ring) <= 1)
return;
typedef typename point_type<Geometry>::type point_t;
point_t const& p0 = range::back(ring);
point_t const& p1 = range::front(ring);
push_back_policy<GeometryOut> policy(ring_out);
strategy.apply(p0, p1, policy, len);
if (BOOST_GEOMETRY_CONDITION(IsClosed2))
{
convert_and_push_back(ring_out, p1);
}
}
};
template <>
struct densify_ring<true, true>
: densify_range<true>
{};
template <>
struct densify_ring<true, false>
: densify_range<false>
{};
}} // namespace detail::densify
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry,
typename GeometryOut,
typename Tag1 = typename tag<Geometry>::type,
typename Tag2 = typename tag<GeometryOut>::type
>
struct densify
: not_implemented<Tag1, Tag2>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
: geometry::detail::densify::densify_range<>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, multi_linestring_tag, multi_linestring_tag>
{
template <typename T, typename Strategy>
static void apply(Geometry const& mls, GeometryOut & mls_out,
T const& len, Strategy const& strategy)
{
std::size_t count = boost::size(mls);
range::resize(mls_out, count);
for (std::size_t i = 0 ; i < count ; ++i)
{
geometry::detail::densify::densify_range<>
::apply(range::at(mls, i), range::at(mls_out, i),
len, strategy);
}
}
};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, ring_tag, ring_tag>
: geometry::detail::densify::densify_ring
<
geometry::closure<Geometry>::value != geometry::open,
geometry::closure<GeometryOut>::value != geometry::open
>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, polygon_tag, polygon_tag>
{
template <typename T, typename Strategy>
static void apply(Geometry const& poly, GeometryOut & poly_out,
T const& len, Strategy const& strategy)
{
apply_ring(exterior_ring(poly), exterior_ring(poly_out),
len, strategy);
std::size_t count = boost::size(interior_rings(poly));
range::resize(interior_rings(poly_out), count);
for (std::size_t i = 0 ; i < count ; ++i)
{
apply_ring(range::at(interior_rings(poly), i),
range::at(interior_rings(poly_out), i),
len, strategy);
}
}
template <typename Ring, typename RingOut, typename T, typename Strategy>
static void apply_ring(Ring const& ring, RingOut & ring_out,
T const& len, Strategy const& strategy)
{
densify<Ring, RingOut, ring_tag, ring_tag>
::apply(ring, ring_out, len, strategy);
}
};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, multi_polygon_tag, multi_polygon_tag>
{
template <typename T, typename Strategy>
static void apply(Geometry const& mpoly, GeometryOut & mpoly_out,
T const& len, Strategy const& strategy)
{
std::size_t count = boost::size(mpoly);
range::resize(mpoly_out, count);
for (std::size_t i = 0 ; i < count ; ++i)
{
apply_poly(range::at(mpoly, i),
range::at(mpoly_out, i),
len, strategy);
}
}
template <typename Poly, typename PolyOut, typename T, typename Strategy>
static void apply_poly(Poly const& poly, PolyOut & poly_out,
T const& len, Strategy const& strategy)
{
densify<Poly, PolyOut, polygon_tag, polygon_tag>::
apply(poly, poly_out, len, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct densify
{
template <typename Geometry, typename Distance, typename Strategy>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
dispatch::densify<Geometry, Geometry>
::apply(geometry, out, max_distance, strategy);
}
template <typename Geometry, typename Distance>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
default_strategy)
{
typedef typename strategy::densify::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy_type;
/*BOOST_CONCEPT_ASSERT(
(concepts::DensifyStrategy<strategy_type>)
);*/
apply(geometry, out, max_distance, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry>
struct densify
{
template <typename Distance, typename Strategy>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
resolve_strategy::densify::apply(geometry, out, max_distance, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Distance, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Distance const& m_max_distance;
Strategy const& m_strategy;
visitor(Distance const& max_distance, Strategy const& strategy)
: m_max_distance(max_distance)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry, Geometry& out) const
{
densify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
}
};
template <typename Distance, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
Distance const& max_distance,
Strategy const& strategy)
{
boost::apply_visitor(
visitor<Distance, Strategy>(max_distance, strategy),
geometry,
out
);
}
};
} // namespace resolve_variant
/*!
\brief Densify a geometry using a specified strategy
\ingroup densify
\tparam Geometry \tparam_geometry
\tparam Distance A numerical distance measure
\tparam Strategy A type fulfilling a DensifyStrategy concept
\param geometry Input geometry, to be densified
\param out Output geometry, densified version of the input geometry
\param max_distance Distance threshold (in units depending on strategy)
\param strategy Densify strategy to be used for densification
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/densify.qbk]}
\qbk{
[heading Available Strategies]
\* [link geometry.reference.strategies.strategy_densify_cartesian Cartesian]
\* [link geometry.reference.strategies.strategy_densify_spherical Spherical]
\* [link geometry.reference.strategies.strategy_densify_geographic Geographic]
[heading Example]
[densify_strategy]
[densify_strategy_output]
[heading See also]
\* [link geometry.reference.algorithms.line_interpolate line_interpolate]
}
*/
template <typename Geometry, typename Distance, typename Strategy>
inline void densify(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
concepts::check<Geometry>();
if (max_distance <= Distance(0))
{
BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
}
geometry::clear(out);
resolve_variant::densify
<
Geometry
>::apply(geometry, out, max_distance, strategy);
}
/*!
\brief Densify a geometry
\ingroup densify
\tparam Geometry \tparam_geometry
\tparam Distance A numerical distance measure
\param geometry Input geometry, to be densified
\param out Output geometry, densified version of the input geometry
\param max_distance Distance threshold (in units depending on coordinate system)
\qbk{[include reference/algorithms/densify.qbk]}
\qbk{
[heading Example]
[densify]
[densify_output]
[heading See also]
\* [link geometry.reference.algorithms.line_interpolate line_interpolate]
}
*/
template <typename Geometry, typename Distance>
inline void densify(Geometry const& geometry,
Geometry& out,
Distance const& max_distance)
{
densify(geometry, out, max_distance, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,343 @@
// 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.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, 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_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/is_inverse_spheroidal_coordinates.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, geometry::bounds<bound_type>::highest()
);
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, geometry::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

View File

@@ -0,0 +1,152 @@
// 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/algorithms/not_implemented.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/formulas/spherical.hpp>
#include <boost/geometry/formulas/vincenty_inverse.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/util/math.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

View File

@@ -0,0 +1,62 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.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
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018, 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
#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/traversal_info.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 )
{}
template <typename Rings>
void visit_generated_rings(Rings const& )
{}
};
// 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;
robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
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;
std::size_t count_within_near_offsetted;
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)
, count_within_near_offsetted(0)
, 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

View File

@@ -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

View File

@@ -0,0 +1,337 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018 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/core/ignore_unused.hpp>
#include <boost/range.hpp>
#include <boost/geometry/core/assert.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
{
// Implements a unique_sub_range for a buffered piece,
// the range can return subsequent points
// known as "i", "j" and "k" (and further), indexed as 0,1,2,3
template <typename Ring>
struct unique_sub_range_from_piece
{
typedef typename boost::range_iterator<Ring const>::type iterator_type;
typedef typename geometry::point_type<Ring const>::type point_type;
unique_sub_range_from_piece(Ring const& ring,
iterator_type iterator_at_i, iterator_type iterator_at_j)
: m_ring(ring)
, m_iterator_at_i(iterator_at_i)
, m_iterator_at_j(iterator_at_j)
, m_point_retrieved(false)
{}
static inline bool is_first_segment() { return false; }
static inline bool is_last_segment() { return false; }
static inline std::size_t size() { return 3u; }
inline point_type const& at(std::size_t index) const
{
BOOST_GEOMETRY_ASSERT(index < size());
switch (index)
{
case 0 : return *m_iterator_at_i;
case 1 : return *m_iterator_at_j;
case 2 : return get_point_k();
default : return *m_iterator_at_i;
}
}
private :
inline point_type const& get_point_k() const
{
if (! m_point_retrieved)
{
m_iterator_at_k = advance_one(m_iterator_at_j);
m_point_retrieved = true;
}
return *m_iterator_at_k;
}
inline void circular_advance_one(iterator_type& next) const
{
++next;
if (next == boost::end(m_ring))
{
next = boost::begin(m_ring) + 1;
}
}
inline iterator_type advance_one(iterator_type it) const
{
iterator_type result = it;
circular_advance_one(result);
// TODO: we could also use piece-boundaries
// to check if the point equals the last one
while (geometry::equals(*it, *result))
{
circular_advance_one(result);
}
return result;
}
Ring const& m_ring;
iterator_type m_iterator_at_i;
iterator_type m_iterator_at_j;
mutable iterator_type m_iterator_at_k;
mutable bool m_point_retrieved;
};
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 <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& this_bounding_box,
Box const& other_bounding_box)
{
for(; it_begin != it_beyond
&& it_begin + 1 != it_beyond
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
this_bounding_box,
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& this_bounding_box,
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),
this_bounding_box, 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], section1.bounding_box, section2.bounding_box);
move_end_iterator<0>(it1_first, it1_beyond,
section1.directions[0], section1.bounding_box, section2.bounding_box);
move_begin_iterator<1>(it1_first, it1_beyond, index1,
section1.directions[1], section1.bounding_box, section2.bounding_box);
move_end_iterator<1>(it1_first, it1_beyond,
section1.directions[1], section1.bounding_box, section2.bounding_box);
signed_size_type index2 = sec2_first_index;
move_begin_iterator<0>(it2_first, it2_beyond, index2,
section2.directions[0], section2.bounding_box, section1.bounding_box);
move_end_iterator<0>(it2_first, it2_beyond,
section2.directions[0], section2.bounding_box, section1.bounding_box);
move_begin_iterator<1>(it2_first, it2_beyond, index2,
section2.directions[1], section2.bounding_box, section1.bounding_box);
move_end_iterator<1>(it2_first, it2_beyond,
section2.directions[1], section2.bounding_box, 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
geometry::recalculate(the_model.rob_pi, *prev1, m_robust_policy);
geometry::recalculate(the_model.rob_pj, *it1, m_robust_policy);
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
iterator it2 = it2_first;
for (iterator prev2 = it2++;
it2 != it2_beyond;
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
{
unique_sub_range_from_piece<ring_type> unique_sub_range2(ring2, prev2, it2);
geometry::recalculate(the_model.rob_qi, *prev2, m_robust_policy);
geometry::recalculate(the_model.rob_qj, *it2, m_robust_policy);
// 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
<
detail::overlay::assign_null_policy
> turn_policy;
turn_policy::apply(unique_sub_range1, unique_sub_range2,
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 bool apply(Section const& section1, Section const& section2,
bool first = true)
{
boost::ignore_unused(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,
m_intersection_strategy.get_disjoint_box_box_strategy()) )
{
return true;
}
calculate_turns(piece1, piece2, section1, section2);
return true;
}
};
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,281 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2016, 2018.
// Modifications copyright (c) 2016-2018 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/detail/buffer/buffer_policies.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);
}
};
template <typename DisjointBoxBoxStrategy>
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,
DisjointBoxBoxStrategy());
}
};
struct include_turn_policy
{
template <typename Turn>
static inline bool apply(Turn const& turn)
{
return turn.location == location_ok;
}
};
template <typename DisjointPointBoxStrategy>
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, DisjointPointBoxStrategy());
}
};
//! 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 bool apply(Turn const& turn, Original const& original, bool first = true)
{
boost::ignore_unused(first);
if (turn.location != location_ok || turn.within_original)
{
// Skip all points already processed
return true;
}
if (geometry::disjoint(turn.robust_point, original.m_box))
{
// Skip all disjoint
return true;
}
int const code = point_in_original(turn.robust_point, original);
if (code == -1)
{
return true;
}
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;
}
return true;
}
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

View File

@@ -0,0 +1,931 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016, 2018.
// Modifications copyright (c) 2016-2018 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/core/config.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>
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
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);
}
};
template <typename DisjointBoxBoxStrategy>
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,
DisjointBoxBoxStrategy());
}
};
struct turn_get_box
{
template <typename Box, typename Turn>
static inline void apply(Box& total, Turn const& turn)
{
geometry::expand(total, turn.robust_point);
}
};
template <typename DisjointPointBoxStrategy>
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,
DisjointPointBoxStrategy());
}
};
enum analyse_result
{
analyse_unknown,
analyse_continue,
analyse_disjoint,
analyse_within,
analyse_on_original_boundary,
analyse_on_offsetted,
analyse_near_offsetted
};
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);
}
// meta-programming-structure defining if to use side-of-intersection
// (only for cartesian / only necessary with rescaling)
template <typename Tag>
struct use_side_of_intersection {};
#if defined(BOOST_GEOMETRY_USE_RESCALING)
// With rescaling, let Cartesian use side-of-intersection
template <>
struct use_side_of_intersection<cartesian_tag> { static bool const value = true; };
#else
template <>
struct use_side_of_intersection<cartesian_tag> { static bool const value = false; };
#endif
template <>
struct use_side_of_intersection<spherical_tag> { static bool const value = false; };
template <>
struct use_side_of_intersection<geographic_tag> { static bool const value = false; };
template <bool UseSideOfIntersection>
struct check_segment {};
// Implementation using side-of-intersection
template <>
struct check_segment<true>
{
template <typename Point, typename Turn>
static inline analyse_result apply(Point const& previous,
Point const& current, Turn const& turn,
bool from_monotonic)
{
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;
}
};
template <>
struct check_segment<false>
{
template <typename Point, typename Turn>
static inline analyse_result apply(Point const& previous,
Point const& current, Turn const& turn,
bool from_monotonic)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type side_strategy;
int const side = side_strategy::apply(previous, current, turn.robust_point);
if (side == 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 (side == -1)
{
// It is in the triangle right-of the segment where the
// segment is the hypothenusa. Check if it is close
// (within rounding-area)
if (in_box(previous, current, turn.robust_point))
{
return analyse_near_offsetted;
}
else if (from_monotonic)
{
return analyse_within;
}
}
else if (from_monotonic)
{
// Left of segment
return analyse_disjoint;
}
// Not monotonic, on left or right side: continue analysing
return analyse_continue;
}
};
template <bool UseSideOfIntersection>
class analyse_turn_wrt_point_piece {};
template <>
class analyse_turn_wrt_point_piece<true>
{
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;
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);
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];
// 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;
}
}
}
}
}
// It is nowhere outside, and not on segment, so it is within
return analyse_within;
}
};
template <>
class analyse_turn_wrt_point_piece<false>
{
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;
typedef strategy::within::winding<point_type> strategy_type;
typename strategy_type::state_type state;
strategy_type strategy;
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];
analyse_result code = check_segment<false>::apply(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);
}
}
}
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;
}
};
template <bool UseSideOfIntersection>
struct check_helper_segment {};
template <>
struct check_helper_segment<true>
{
template <typename Point, typename Turn>
static inline analyse_result apply(Point const& s1,
Point const& s2, Turn const& turn,
bool is_original,
Point const& offsetted)
{
boost::ignore_unused(offsetted);
boost::ignore_unused(is_original);
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 (and not on its corners)
// are considered as within
return 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;
}
};
template <>
struct check_helper_segment<false>
{
template <typename Point, typename Turn>
static inline analyse_result apply(Point const& s1,
Point const& s2, Turn const& turn,
bool is_original,
Point const& offsetted)
{
boost::ignore_unused(offsetted);
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;
}
};
template <bool UseSideOfIntersection>
class analyse_turn_wrt_piece
{
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];
}
// 3--offsetted outline--0
// | |
// left | | right
// | |
// 2===>==original===>===1
}
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]))
{
// On original, right corner
return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary;
}
if (comparator(point, points[2]))
{
// On original, left corner
return piece.is_flat_start ? analyse_continue : analyse_on_original_boundary;
}
// Right side of the piece
analyse_result result
= check_helper_segment<UseSideOfIntersection>::apply(points[0], points[1], turn,
false, points[0]);
if (result != analyse_continue)
{
return result;
}
// Left side of the piece
result = check_helper_segment<UseSideOfIntersection>::apply(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<UseSideOfIntersection>::apply(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<UseSideOfIntersection>::apply(*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<UseSideOfIntersection>::apply(previous, current, turn, false);
if (code != analyse_continue)
{
return code;
}
}
}
return analyse_unknown;
}
};
// Helper Structure, of which the apply method returns a side value in {-1, 0, 1}
template <bool UseSideOfIntersection>
struct turn_in_piece {};
template <>
struct turn_in_piece<true>
{
private :
template <typename Turn, typename Piece>
static inline int 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
}
public :
template <typename Turn, typename Piece, typename Strategy>
static inline int apply(Turn const& turn, Piece const& piece,
Strategy const& strategy)
{
if (piece.is_convex)
{
return in_convex_piece(turn, piece);
}
else
{
// side-of-intersection only supported for convex pieces
// Call point_in_geometry, a performance-bottleneck
// TODO: might be replaced by extending analysing piece
return detail::within::point_in_geometry(turn.robust_point,
piece.robust_ring, strategy);
}
}
};
template <>
struct turn_in_piece<false>
{
public :
template <typename Turn, typename Piece, typename Strategy>
static inline int apply(Turn const& turn, Piece const& piece,
Strategy const& strategy)
{
return detail::within::point_in_geometry(turn.robust_point,
piece.robust_ring, strategy);
}
};
template
<
typename CsTag,
typename Turns,
typename Pieces,
typename PointInGeometryStrategy
>
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
PointInGeometryStrategy const& m_point_in_geometry_strategy;
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;
}
public:
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
PointInGeometryStrategy const& strategy)
: m_turns(turns)
, m_pieces(pieces)
, m_point_in_geometry_strategy(strategy)
{}
template <typename Turn, typename Piece>
inline bool apply(Turn const& turn, Piece const& piece, bool first = true)
{
boost::ignore_unused(first);
if (turn.count_within > 0)
{
// Already inside - no need to check again
return true;
}
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 true;
}
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 true;
}
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
{
return true;
}
// 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 true;
}
if (cd > piece.robust_max_comparable_radius)
{
return true;
}
}
static const bool use_soi = use_side_of_intersection<CsTag>::value;
boost::ignore_unused(use_soi);
analyse_result analyse_code =
piece.type == geometry::strategy::buffer::buffered_point
? analyse_turn_wrt_point_piece<use_soi>::apply(turn, piece)
: analyse_turn_wrt_piece<use_soi>::apply(turn, piece);
switch(analyse_code)
{
case analyse_disjoint :
return true;
case analyse_on_offsetted :
mutable_turn.count_on_offsetted++; // value is not used anymore
return true;
case analyse_on_original_boundary :
mutable_turn.count_on_original_boundary++;
return true;
case analyse_within :
mutable_turn.count_within++;
return true;
case analyse_near_offsetted :
mutable_turn.count_within_near_offsetted++;
return true;
default :
break;
}
int const geometry_code = turn_in_piece<use_soi>::apply(turn, piece,
m_point_in_geometry_strategy);
if (geometry_code == 1)
{
mutable_turn.count_within++;
}
return true;
}
};
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,279 @@
// 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, 2019.
// Modifications copyright (c) 2013-2019 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_COVERED_BY_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
#include <cstddef>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/within/implementation.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::covered_by_point_geometry(geometry1, geometry2, strategy);
}
};
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 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(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(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
{};
template <typename MultiPoint, typename Point>
struct covered_by<MultiPoint, Point, multi_point_tag, point_tag>
: public detail::within::multi_point_point
{};
template <typename MultiPoint1, typename MultiPoint2>
struct covered_by<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
: public detail::within::multi_point_multi_point
{};
// 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
{};
template <typename MultiPoint, typename Segment>
struct covered_by<MultiPoint, Segment, multi_point_tag, segment_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename Linestring>
struct covered_by<MultiPoint, Linestring, multi_point_tag, linestring_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename MultiLinestring>
struct covered_by<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
: public detail::within::multi_point_multi_geometry<false>
{};
// 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
{};
template <typename MultiPoint, typename Ring>
struct covered_by<MultiPoint, Ring, multi_point_tag, ring_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename Polygon>
struct covered_by<MultiPoint, Polygon, multi_point_tag, polygon_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename MultiPolygon>
struct covered_by<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
: public detail::within::multi_point_multi_geometry<false>
{};
// 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 boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP

View File

@@ -0,0 +1,255 @@
// 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, 2018.
// Modifications copyright (c) 2013-2018 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_COVERED_BY_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_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/within/interface.hpp>
#include <boost/geometry/algorithms/not_implemented.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_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>
{};
} // 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<Geometry1, Geometry2, 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_DETAIL_COVERED_BY_INTERFACE_HPP

View File

@@ -0,0 +1,255 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015-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
// 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>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// TODO: remove
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);
}
template <typename Point, typename CSTag = typename cs_tag<Point>::type>
struct direction_code_impl
{
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag));
};
template <typename Point>
struct direction_code_impl<Point, cartesian_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
Point2 const& p)
{
typedef typename geometry::select_coordinate_type
<
Point1, Point2
>::type calc_t;
if ( (math::equals(geometry::get<0>(segment_b), geometry::get<0>(segment_a))
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(segment_a)))
|| (math::equals(geometry::get<0>(segment_b), geometry::get<0>(p))
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(p))) )
{
return 0;
}
calc_t x1 = geometry::get<0>(segment_b) - geometry::get<0>(segment_a);
calc_t y1 = geometry::get<1>(segment_b) - geometry::get<1>(segment_a);
calc_t x2 = geometry::get<0>(segment_b) - geometry::get<0>(p);
calc_t y2 = geometry::get<1>(segment_b) - geometry::get<1>(p);
calc_t ax = (std::min)(math::abs(x1), math::abs(x2));
calc_t ay = (std::min)(math::abs(y1), math::abs(y2));
int s1 = 0, s2 = 0;
if (ax >= ay)
{
s1 = x1 > 0 ? 1 : -1;
s2 = x2 > 0 ? 1 : -1;
}
else
{
s1 = y1 > 0 ? 1 : -1;
s2 = y2 > 0 ? 1 : -1;
}
return s1 == s2 ? -1 : 1;
}
};
template <typename Point>
struct direction_code_impl<Point, spherical_equatorial_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
Point2 const& p)
{
typedef typename coordinate_type<Point1>::type coord1_t;
typedef typename coordinate_type<Point2>::type coord2_t;
typedef typename coordinate_system<Point1>::type::units units_t;
typedef typename coordinate_system<Point2>::type::units units2_t;
BOOST_MPL_ASSERT_MSG((boost::is_same<units_t, units2_t>::value),
NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS,
(units_t, units2_t));
typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
static coord1_t const pi_half1 = constants1::max_latitude();
static coord2_t const pi_half2 = constants2::max_latitude();
static calc_t const c0 = 0;
coord1_t const a0 = geometry::get<0>(segment_a);
coord1_t const a1 = geometry::get<1>(segment_a);
coord1_t const b0 = geometry::get<0>(segment_b);
coord1_t const b1 = geometry::get<1>(segment_b);
coord2_t const p0 = geometry::get<0>(p);
coord2_t const p1 = geometry::get<1>(p);
if ( (math::equals(b0, a0) && math::equals(b1, a1))
|| (math::equals(b0, p0) && math::equals(b1, p1)) )
{
return 0;
}
bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
|| (is_p_pole && math::sign(b1) == math::sign(p1))) )
{
return 0;
}
// NOTE: as opposed to the implementation for cartesian CS
// here point b is the origin
calc_t const dlon1 = math::longitude_distance_signed<units_t, calc_t>(b0, a0);
calc_t const dlon2 = math::longitude_distance_signed<units_t, calc_t>(b0, p0);
bool is_antilon1 = false, is_antilon2 = false;
calc_t const dlat1 = latitude_distance_signed<units_t, calc_t>(b1, a1, dlon1, is_antilon1);
calc_t const dlat2 = latitude_distance_signed<units_t, calc_t>(b1, p1, dlon2, is_antilon2);
calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
c0 :
(std::min)(is_antilon1 ? c0 : math::abs(dlon1),
is_antilon2 ? c0 : math::abs(dlon2));
calc_t my = (std::min)(math::abs(dlat1),
math::abs(dlat2));
int s1 = 0, s2 = 0;
if (mx >= my)
{
s1 = dlon1 > 0 ? 1 : -1;
s2 = dlon2 > 0 ? 1 : -1;
}
else
{
s1 = dlat1 > 0 ? 1 : -1;
s2 = dlat2 > 0 ? 1 : -1;
}
return s1 == s2 ? -1 : 1;
}
template <typename Units, typename T>
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
{
typedef math::detail::constants_on_spheroid<T, Units> constants;
static T const pi = constants::half_period();
static T const c0 = 0;
T res = lat2 - lat1;
is_antilon = math::equals(math::abs(lon_ds), pi);
if (is_antilon)
{
res = lat2 + lat1;
if (res >= c0)
res = pi - res;
else
res = -pi - res;
}
return res;
}
};
template <typename Point>
struct direction_code_impl<Point, spherical_polar_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 segment_a, Point1 segment_b,
Point2 p)
{
typedef math::detail::constants_on_spheroid
<
typename coordinate_type<Point1>::type,
typename coordinate_system<Point1>::type::units
> constants1;
typedef math::detail::constants_on_spheroid
<
typename coordinate_type<Point2>::type,
typename coordinate_system<Point2>::type::units
> constants2;
geometry::set<1>(segment_a,
constants1::max_latitude() - geometry::get<1>(segment_a));
geometry::set<1>(segment_b,
constants1::max_latitude() - geometry::get<1>(segment_b));
geometry::set<1>(p,
constants2::max_latitude() - geometry::get<1>(p));
return direction_code_impl
<
Point, spherical_equatorial_tag
>::apply(segment_a, segment_b, p);
}
};
template <typename Point>
struct direction_code_impl<Point, geographic_tag>
: direction_code_impl<Point, spherical_equatorial_tag>
{};
// 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,
Point2 const& p)
{
return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
}
} // namespace detail
#endif //DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP

View File

@@ -0,0 +1,213 @@
// 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-2019.
// Modifications copyright (c) 2013-2019, 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>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool point_on_border_covered_by(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
typename geometry::point_type<Geometry1>::type pt;
return geometry::point_on_border(pt, geometry1)
&& geometry::covered_by(pt, geometry2, strategy);
}
/*!
\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)
{
not_disjoint = not_disjoint
|| point_on_border_covered_by(range, 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 areal_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;
}
};
template <typename Areal, typename Box>
struct areal_box
{
/*!
\tparam Strategy relate (segments intersection) strategy
*/
template <typename Strategy>
static inline bool apply(Areal const& areal,
Box const& box,
Strategy const& strategy)
{
if ( ! for_each_segment(geometry::segments_begin(areal),
geometry::segments_end(areal),
box,
strategy.get_disjoint_segment_box_strategy()) )
{
return false;
}
// If there is no intersection of any segment and box,
// the box might be located inside areal geometry
if ( point_on_border_covered_by(box, areal,
strategy.template get_point_in_geometry_strategy<Box, Areal>()) )
{
return false;
}
return true;
}
private:
template <typename SegIter, typename Strategy>
static inline bool for_each_segment(SegIter first,
SegIter last,
Box const& box,
Strategy const& strategy)
{
for ( ; first != last ; ++first)
{
if (! disjoint_segment_box::apply(*first, box, strategy))
{
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::areal_areal<Areal1, Areal2>
{};
template <typename Areal, typename Box>
struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>
: detail::disjoint::areal_box<Areal, Box>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP

View File

@@ -0,0 +1,80 @@
// 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-2018.
// Modifications copyright (c) 2013-2018, 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/algorithms/dispatch/disjoint.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
/*!
\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, typename Strategy>
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&)
{
return Strategy::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>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
{
return Strategy::apply(box1, box2);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP

View File

@@ -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-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_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

View File

@@ -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

View File

@@ -0,0 +1,302 @@
// 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-2018.
// Modifications copyright (c) 2013-2018, 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/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.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

View File

@@ -0,0 +1,179 @@
// 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;
};
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

View File

@@ -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

View File

@@ -0,0 +1,554 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2014-2018, 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/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/policies/compare.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
: geometry::less<>
{
private:
typedef geometry::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(), geometry::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);
}
};
template <typename EnvelopeStrategy>
struct expand_box_segment
{
explicit expand_box_segment(EnvelopeStrategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Segment>
inline void apply(Box& total, Segment const& segment) const
{
geometry::expand(total,
geometry::return_envelope<Box>(segment, m_strategy));
}
EnvelopeStrategy const& m_strategy;
};
template <typename DisjointPointBoxStrategy>
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
return ! detail::disjoint::disjoint_point_box(point, box,
DisjointPointBoxStrategy());
}
};
template <typename DisjointStrategy>
struct overlaps_box_segment
{
explicit overlaps_box_segment(DisjointStrategy const& strategy)
: m_strategy(strategy)
{}
template <typename Box, typename Segment>
inline bool apply(Box const& box, Segment const& segment) const
{
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
}
DisjointStrategy const& m_strategy;
};
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 bool apply(Item1 const& item1, Item2 const& item2)
{
if (! m_intersection_found
&& ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
{
m_intersection_found = true;
return false;
}
return 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);
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type;
// TODO: disjoint Segment/Box may be called in partition multiple times
// possibly for non-cartesian segments which could be slow. We should consider
// passing a range of bounding boxes of segments after calculating them once.
// Alternatively instead of a range of segments a range of Segment/Envelope pairs
// should be passed, where envelope would be lazily calculated when needed the first time
geometry::partition
<
geometry::model::box<typename point_type<MultiPoint>::type>
>::apply(multipoint, segment_range(linear), visitor,
expand_box_point(),
overlaps_box_point<disjoint_pb_strategy_type>(),
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
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);
}
};
template <typename MultiPoint, typename SingleGeometry>
class multi_point_single_geometry
{
public:
template <typename Strategy>
static inline bool apply(MultiPoint const& multi_point,
SingleGeometry const& single_geometry,
Strategy const& strategy)
{
typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type;
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
box2_type box2;
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
geometry::detail::expand_by_epsilon(box2);
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
// The default strategy is enough for Point/Box
if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())
&& ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
{
return false;
}
}
return true;
}
template <typename Strategy>
static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy)
{
return apply(multi_point, single_geometry, strategy);
}
};
template <typename MultiPoint, typename MultiGeometry>
class multi_point_multi_geometry
{
private:
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
geometry::expand(total, point);
}
};
struct expand_box_box_pair
{
template <typename Box, typename BoxPair>
inline void apply(Box& total, BoxPair const& box_pair) const
{
geometry::expand(total, box_pair.first);
}
};
template <typename DisjointPointBoxStrategy>
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough for Point/Box
return ! detail::disjoint::disjoint_point_box(point, box,
DisjointPointBoxStrategy());
}
};
template <typename DisjointBoxBoxStrategy>
struct overlaps_box_box_pair
{
template <typename Box, typename BoxPair>
inline bool apply(Box const& box, BoxPair const& box_pair) const
{
// The default strategy is enough for Box/Box
return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
DisjointBoxBoxStrategy());
}
};
template <typename PtSegStrategy>
class item_visitor_type
{
public:
item_visitor_type(MultiGeometry const& multi_geometry,
PtSegStrategy const& strategy)
: m_intersection_found(false)
, m_multi_geometry(multi_geometry)
, m_strategy(strategy)
{}
template <typename Point, typename BoxPair>
inline bool apply(Point const& point, BoxPair const& box_pair)
{
typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type;
typedef typename boost::range_value<MultiGeometry>::type single_type;
// The default strategy is enough for Point/Box
if (! m_intersection_found
&& ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type())
&& ! dispatch::disjoint<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
{
m_intersection_found = true;
return false;
}
return true;
}
inline bool intersection_found() const { return m_intersection_found; }
private:
bool m_intersection_found;
MultiGeometry const& m_multi_geometry;
PtSegStrategy const& m_strategy;
};
// structs for partition -- end
public:
template <typename Strategy>
static inline bool apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, Strategy const& strategy)
{
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<MultiGeometry>::type point2_type;
typedef model::box<point1_type> box1_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
typename Strategy::envelope_strategy_type const
envelope_strategy = strategy.get_envelope_strategy();
std::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i)
{
geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i;
}
item_visitor_type<Strategy> visitor(multi_geometry, strategy);
typedef overlaps_box_point
<
typename Strategy::disjoint_point_box_strategy_type
> overlaps_box_point_type;
typedef overlaps_box_box_pair
<
typename Strategy::disjoint_box_box_strategy_type
> overlaps_box_box_pair_type;
geometry::partition
<
box1_type
>::apply(multi_point, boxes, visitor,
expand_box_point(),
overlaps_box_point_type(),
expand_box_box_pair(),
overlaps_box_box_pair_type());
return ! visitor.intersection_found();
}
template <typename Strategy>
static inline bool apply(MultiGeometry const& multi_geometry, MultiPoint const& multi_point, Strategy const& strategy)
{
return apply(multi_point, multi_geometry, strategy);
}
};
template <typename MultiPoint, typename Areal, typename Tag = typename tag<Areal>::type>
struct multipoint_areal
: multi_point_single_geometry<MultiPoint, Areal>
{};
template <typename MultiPoint, typename Areal>
struct multipoint_areal<MultiPoint, Areal, multi_polygon_tag>
: multi_point_multi_geometry<MultiPoint, Areal>
{};
}} // 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>
{};
template <typename Areal, typename MultiPoint, std::size_t DimensionCount>
struct disjoint
<
Areal, MultiPoint, DimensionCount, areal_tag, multi_point_tag, false
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
{};
template <typename MultiPoint, typename Areal, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Areal, DimensionCount, multi_point_tag, areal_tag, false
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP

View File

@@ -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

View File

@@ -0,0 +1,78 @@
// 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-2018.
// Modifications copyright (c) 2013-2018, 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, typename Strategy>
inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& )
{
// ! covered_by(point, box)
return ! Strategy::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

View File

@@ -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

View File

@@ -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, 2014, 2015, 2017, 2018.
// Modifications copyright (c) 2013-2018, 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/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
// For backward compatibility
#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
/*!
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2, typename Strategy>
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2,
Strategy const& )
{
return ! Strategy::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>
{
template <typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2,
Strategy const& )
{
return ! Strategy::apply(point1, point2);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP

View File

@@ -0,0 +1,276 @@
// 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-2019.
// Modifications copyright (c) 2013-2019, 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.
// 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/core/radian_access.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_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/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/formulas/vertex_longitude.hpp>
#include <boost/geometry/geometries/box.hpp>
// Temporary, for envelope_segment_impl
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename CS_Tag>
struct disjoint_segment_box_sphere_or_spheroid
{
struct disjoint_info
{
enum type
{
intersect,
disjoint_no_vertex,
disjoint_vertex
};
disjoint_info(type t) : m_(t){}
operator type () const {return m_;}
type m_;
private :
//prevent automatic conversion for any other built-in types
template <typename T>
operator T () const;
};
template
<
typename Segment, typename Box,
typename AzimuthStrategy,
typename NormalizeStrategy,
typename DisjointPointBoxStrategy,
typename DisjointBoxBoxStrategy
>
static inline bool apply(Segment const& segment,
Box const& box,
AzimuthStrategy const& azimuth_strategy,
NormalizeStrategy const& normalize_strategy,
DisjointPointBoxStrategy const& disjoint_point_box_strategy,
DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
{
typedef typename point_type<Segment>::type segment_point;
segment_point vertex;
return apply(segment, box, vertex,
azimuth_strategy,
normalize_strategy,
disjoint_point_box_strategy,
disjoint_box_box_strategy) != disjoint_info::intersect;
}
template
<
typename Segment, typename Box,
typename P,
typename AzimuthStrategy,
typename NormalizeStrategy,
typename DisjointPointBoxStrategy,
typename DisjointBoxBoxStrategy
>
static inline disjoint_info apply(Segment const& segment,
Box const& box,
P& vertex,
AzimuthStrategy const& azimuth_strategy,
NormalizeStrategy const& ,
DisjointPointBoxStrategy const& disjoint_point_box_strategy,
DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
{
assert_dimension_equal<Segment, Box>();
typedef typename point_type<Segment>::type segment_point_type;
segment_point_type p0, p1;
geometry::detail::assign_point_from_index<0>(segment, p0);
geometry::detail::assign_point_from_index<1>(segment, p1);
//vertex not computed here
disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex;
// Simplest cases first
// Case 1: if box contains one of segment's endpoints then they are not disjoint
if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy)
|| ! disjoint_point_box(p1, box, disjoint_point_box_strategy) )
{
return disjoint_info::intersect;
}
// Case 2: disjoint if bounding boxes are disjoint
typedef typename coordinate_type<segment_point_type>::type CT;
segment_point_type p0_normalized;
NormalizeStrategy::apply(p0, p0_normalized);
segment_point_type p1_normalized;
NormalizeStrategy::apply(p1, p1_normalized);
CT lon1 = geometry::get_as_radian<0>(p0_normalized);
CT lat1 = geometry::get_as_radian<1>(p0_normalized);
CT lon2 = geometry::get_as_radian<0>(p1_normalized);
CT lat2 = geometry::get_as_radian<1>(p1_normalized);
if (lon1 > lon2)
{
std::swap(lon1, lon2);
std::swap(lat1, lat2);
}
geometry::model::box<segment_point_type> box_seg;
strategy::envelope::detail::envelope_segment_impl
<
CS_Tag
>::template apply<geometry::radian>(lon1, lat1,
lon2, lat2,
box_seg,
azimuth_strategy);
if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy))
{
return disjoint_return_value;
}
// Case 3: test intersection by comparing angles
CT alp1, a_b0, a_b1, a_b2, a_b3;
CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
bool b0 = formula::azimuth_side_value(alp1, a_b0) > 0;
bool b1 = formula::azimuth_side_value(alp1, a_b1) > 0;
bool b2 = formula::azimuth_side_value(alp1, a_b2) > 0;
bool b3 = formula::azimuth_side_value(alp1, a_b3) > 0;
if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3))
{
return disjoint_info::intersect;
}
// Case 4: The only intersection case not covered above is when all four
// points of the box are above (below) the segment in northern (southern)
// hemisphere. Then we have to compute the vertex of the segment
CT vertex_lat;
CT lat_sum = lat1 + lat2;
if ((lat1 < b_lat_min && lat_sum > CT(0))
|| (lat1 > b_lat_max && lat_sum < CT(0)))
{
CT b_lat_below; //latitude of box closest to equator
if (lat_sum > CT(0))
{
vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
b_lat_below = b_lat_min;
} else {
vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg);
b_lat_below = b_lat_max;
}
//optimization TODO: computing the spherical longitude should suffice for
// the majority of cases
CT vertex_lon = geometry::formula::vertex_longitude<CT, CS_Tag>
::apply(lon1, lat1,
lon2, lat2,
vertex_lat,
alp1,
azimuth_strategy);
geometry::set_from_radian<0>(vertex, vertex_lon);
geometry::set_from_radian<1>(vertex, vertex_lat);
disjoint_return_value = disjoint_info::disjoint_vertex; //vertex_computed
// Check if the vertex point is within the band defined by the
// minimum and maximum longitude of the box; if yes, then return
// false if the point is above the min latitude of the box; return
// true in all other cases
if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
&& std::abs(vertex_lat) > std::abs(b_lat_below))
{
return disjoint_info::intersect;
}
}
return disjoint_return_value;
}
};
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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,157 @@
// 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
>
{};
template <typename Linear, typename Box>
struct default_strategy<Linear, Box, segment_tag, box_tag, false>
: strategy::distance::services::default_strategy
<
segment_tag, box_tag,
typename point_type<Linear>::type,
typename point_type<Box>::type
>
{};
template <typename Linear, typename Box>
struct default_strategy<Linear, Box, linear_tag, box_tag, false>
: strategy::distance::services::default_strategy
<
segment_tag, box_tag,
typename point_type<Linear>::type,
typename point_type<Box>::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

View File

@@ -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

View File

@@ -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 2014, 2018.
// Modifications copyright (c) 2014-2018, 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.
// 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/linear_to_box.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

View File

@@ -0,0 +1,412 @@
// 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, 2018.
// Modifications copyright (c) 2014-2018, 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_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
{
template <typename Strategy>
struct distance
{
template <typename Geometry1, typename Geometry2>
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 <>
struct distance<default_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
<
Strategy
>::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 Calculate the distance between two geometries \brief_strategy
\ingroup distance
\details
\details The free function distance calculates the distance between two geometries \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 Calculate the distance between two geometries.
\ingroup distance
\details The free function distance calculates the distance between two geometries. \details_default_strategy
\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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,144 @@
// 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

View File

@@ -0,0 +1,123 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Linear, typename Box, typename Strategy>
struct linear_to_box
{
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type<Linear>::type,
typename point_type<Box>::type
>::type return_type;
template <typename Iterator>
static inline return_type apply(Box const& box,
Iterator begin,
Iterator end,
Strategy const& strategy)
{
bool first = true;
return_type d_min(0);
for (Iterator it = begin; it != end; ++it, first = false)
{
typedef typename std::iterator_traits<Iterator>::value_type
Segment;
return_type d = dispatch::distance<Segment, Box, Strategy>
::apply(*it, box, strategy);
if ( first || d < d_min )
{
d_min = d;
}
}
return d_min;
}
static inline return_type apply(Linear const& linear,
Box const& box,
Strategy const& strategy)
{
if ( geometry::intersects(linear, box) )
{
return 0;
}
return apply(box,
geometry::segments_begin(linear),
geometry::segments_end(linear),
strategy);
}
static inline return_type apply(Box const& box,
Linear const& linear,
Strategy const& strategy)
{
return apply(linear, box, strategy);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Box, typename Strategy>
struct distance
<
Linear, Box, Strategy,
linear_tag, box_tag,
strategy_tag_distance_segment_box, false
>
: detail::distance::linear_to_box
<
Linear, Box, Strategy
>
{};
template <typename Areal, typename Box, typename Strategy>
struct distance
<
Areal, Box, Strategy,
areal_tag, box_tag,
strategy_tag_distance_segment_box, false
>
: detail::distance::linear_to_box
<
Areal, Box, Strategy
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP

View File

@@ -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

View File

@@ -0,0 +1,240 @@
// 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

View File

@@ -0,0 +1,522 @@
// 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, 2019.
// Modifications copyright (c) 2014-2019, 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_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/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/detail/within/point_in_geometry.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)
{
// TODO: pass strategy
if (within::within_point_geometry(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)
{
// TODO: pass strategy
if (within::within_point_geometry(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)
{
// TODO: pass strategy
if (! within::covered_by_point_geometry(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)
{
// TODO: pass strategy
if (within::covered_by_point_geometry(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

View File

@@ -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

View File

@@ -0,0 +1,889 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2019 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
// 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/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/util/calculation_type.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/tags.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
// TODO: Take strategy
template <typename Segment, typename Box>
inline bool intersects_segment_box(Segment const& segment, Box const& box)
{
typedef typename strategy::disjoint::services::default_strategy
<
Segment, Box
>::type strategy_type;
return ! detail::disjoint::disjoint_segment_box::apply(segment, box,
strategy_type());
}
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
<
typename Strategy::distance_ps_strategy::type
>::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 && intersects_segment_box(segment, box))
{
return 0;
}
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
typename Strategy::distance_ps_strategy::type
>::apply(strategy.get_distance_ps_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.get_distance_ps_strategy().apply(box_points[imin], p[0], p[1]);
}
else
{
unsigned int bimin = imin - 4;
return strategy.get_distance_ps_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 && intersects_segment_box(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 SBStrategy
>
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,
SBStrategy const& sb_strategy)
{
boost::ignore_unused(sb_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;
typename SBStrategy::distance_ps_strategy::type ps_strategy =
sb_strategy.get_distance_ps_strategy();
if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
{
//if p0 is in box's band
if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right)))
{
// segment & crosses band (TODO:merge with box-box dist)
if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1)))
{
SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0;
if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right)))
{
return cast::apply(ps_strategy.apply(high, bottom_right, top_right));
}
return cast::apply(ps_strategy.apply(top_right, p0, p1));
}
return cast::apply(ps_strategy.apply(p0, bottom_right, top_right));
}
// distance is realized between the top-right
// corner of the box and the segment
return cast::apply(ps_strategy.apply(top_right, p0, p1));
}
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,
SBStrategy const& sb_strategy)
{
boost::ignore_unused(sb_strategy);
return apply(p0, p1, p0, top_left, sb_strategy);
}
static inline ReturnType apply(SegmentPoint const& p0,
SegmentPoint const& p1,
SegmentPoint const& p_max,
BoxPoint const& top_left,
SBStrategy const& sb_strategy)
{
boost::ignore_unused(sb_strategy);
typedef cast_to_result<ReturnType> cast;
LessEqual less_equal;
// p0 is above the upper segment of the box (and inside its band)
// then compute the vertical (i.e. meridian for spherical) distance
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
{
ReturnType diff =
sb_strategy.get_distance_ps_strategy().vertical_or_meridian(
geometry::get_as_radian<1>(p_max),
geometry::get_as_radian<1>(top_left));
return strategy::distance::services::result_from_distance
<
SBStrategy, SegmentPoint, BoxPoint
>::apply(sb_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(sb_strategy.get_distance_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,
SBStrategy const& sb_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,
sb_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,
sb_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,
SBStrategy const& sb_strategy,
ReturnType& result)
{
typedef compare_less_equal<ReturnType, false> GreaterEqual;
// the segment lies below the box
if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
{
result = sb_strategy.template segment_below_of_box
<
LessEqual,
ReturnType
>(p0, p1,
top_left, top_right,
bottom_left, bottom_right);
return true;
}
// the segment lies above the box
if (geometry::get<1>(p0) > geometry::get<1>(top_right))
{
result = (std::min)(above_of_box
<
LessEqual
>::apply(p0, p1, top_left, sb_strategy),
above_of_box
<
GreaterEqual
>::apply(p1, p0, top_right, sb_strategy));
return true;
}
return false;
}
};
struct check_generic_position
{
static inline bool apply(SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const& corner1,
BoxPoint const& corner2,
SBStrategy const& sb_strategy,
ReturnType& result)
{
typedef typename geometry::strategy::side::services::default_strategy
<
typename geometry::cs_tag<SegmentPoint>::type
>::type side;
typedef cast_to_result<ReturnType> cast;
ReturnType diff1 = cast::apply(geometry::get<1>(p1))
- cast::apply(geometry::get<1>(p0));
typename SBStrategy::distance_ps_strategy::type ps_strategy =
sb_strategy.get_distance_ps_strategy();
int sign = diff1 < 0 ? -1 : 1;
if (side::apply(p0, p1, corner1) * sign < 0)
{
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
return true;
}
if (side::apply(p0, p1, corner2) * sign > 0)
{
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,
SBStrategy const& sb_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,
sb_strategy, result))
{
return result;
}
if (check_above_below_of_box
<
less_equal
>::apply(p0, p1,
top_left, top_right, bottom_left, bottom_right,
sb_strategy, result))
{
return result;
}
if (check_generic_position::apply(p0, p1,
top_left, bottom_right,
sb_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,
SBStrategy const& sb_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,
sb_strategy, result))
{
return result;
}
if (check_above_below_of_box
<
greater_equal
>::apply(p1, p0,
top_right, top_left, bottom_right, bottom_left,
sb_strategy, result))
{
return result;
}
if (check_generic_position::apply(p0, p1,
bottom_left, top_right,
sb_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,
SBStrategy const& sb_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,
sb_strategy);
}
return non_negative_slope_segment(p0, p1,
top_left, top_right,
bottom_left, bottom_right,
sb_strategy);
}
template <typename LessEqual>
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
SegmentPoint const& p1,
SegmentPoint const& p_max,
BoxPoint const& top_left,
SBStrategy const& sb_strategy)
{
return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, sb_strategy);
}
template <typename LessEqual>
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const& top_left,
SBStrategy const& sb_strategy)
{
return above_of_box<LessEqual>::apply(p0, p1, top_left, sb_strategy);
}
};
//=========================================================================
template
<
typename Segment,
typename Box,
typename std::size_t Dimension,
typename SBStrategy
>
class segment_to_box
: not_implemented<Segment, Box>
{};
template
<
typename Segment,
typename Box,
typename SBStrategy
>
class segment_to_box<Segment, Box, 2, SBStrategy>
{
private:
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::type box_point;
typedef typename strategy::distance::services::comparable_type
<
SBStrategy
>::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
<
SBStrategy, segment_point, box_point
>::type return_type;
static inline return_type apply(Segment const& segment,
Box const& box,
SBStrategy const& sb_strategy)
{
segment_point p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
if (detail::equals::equals_point_point(p[0], p[1],
sb_strategy.get_equals_point_point_strategy()))
{
typedef typename boost::mpl::if_
<
boost::is_same
<
ps_comparable_strategy,
SBStrategy
>,
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);
SBStrategy::mirror(p[0], p[1],
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,
SBStrategy
>::apply(p[0], p[1],
top_left, top_right, bottom_left, bottom_right,
sb_strategy);
}
else
{
return segment_to_box_2D
<
return_type,
segment_point,
box_point,
SBStrategy
>::apply(p[1], p[0],
top_left, top_right, bottom_left, bottom_right,
sb_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_segment_box, 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>();
return detail::distance::segment_to_box
<
Segment,
Box,
dimension<Segment>::value,
Strategy
>::apply(segment, box, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP

View File

@@ -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

View File

@@ -0,0 +1,90 @@
// Boost.Geometry
// Copyright (c) 2018 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_ENVELOPE_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_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/detail/envelope/linear.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_AREAL_HPP

View File

@@ -0,0 +1,54 @@
// 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-2018.
// Modifications copyright (c) 2015-2018, 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_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
#include <boost/geometry/core/tags.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
#include <boost/geometry/strategies/spherical/envelope_box.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Box>
struct envelope<Box, box_tag>
{
template<typename BoxIn, typename BoxOut, typename Strategy>
static inline void apply(BoxIn const& box_in, BoxOut& mbr, Strategy const& )
{
Strategy::apply(box_in, mbr);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,39 @@
// 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/areal.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>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP

View File

@@ -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

View File

@@ -0,0 +1,231 @@
// 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, 2018.
// Modifications copyright (c) 2015-2018, 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/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/envelope.hpp>
#include <boost/geometry/util/select_most_precise.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 strategy::envelope::services::default_strategy
<
typename tag<Geometry>::type,
typename cs_tag<Geometry>::type,
typename select_most_precise
<
typename coordinate_type<Geometry>::type,
typename coordinate_type<Box>::type
>::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

View File

@@ -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

View File

@@ -0,0 +1,62 @@
// 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, 2018.
// Modifications copyright (c) 2015-2018, 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_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/envelope.hpp>
#include <boost/geometry/strategies/spherical/envelope.hpp>
#include <boost/geometry/strategies/geographic/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linestring>
struct envelope<Linestring, linestring_tag>
: detail::envelope::envelope_range
{};
template <typename MultiLinestring>
struct envelope<MultiLinestring, multi_linestring_tag>
: detail::envelope::envelope_multi_range
<
detail::envelope::envelope_range
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP

View File

@@ -0,0 +1,49 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2018, 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_MULTIPOINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/envelope_multipoint.hpp>
#include <boost/geometry/strategies/spherical/envelope_multipoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename MultiPoint>
struct envelope<MultiPoint, multi_point_tag>
{
template <typename Box, typename Strategy>
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& )
{
Strategy::apply(multipoint, mbr);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP

View File

@@ -0,0 +1,67 @@
// 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, 2018.
// Modifications copyright (c) 2015-2018, 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_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
#include <boost/geometry/strategies/spherical/envelope_point.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
struct envelope_point
{
template <typename Point, typename Box, typename Strategy>
static inline void apply(Point const& point, Box& mbr, Strategy const& )
{
Strategy::apply(point, mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point>
struct envelope<Point, point_tag>
: detail::envelope::envelope_point
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP

View File

@@ -0,0 +1,127 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 2016, 2018.
// Modifications copyright (c) 2015-2018, 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_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
#include <iterator>
#include <vector>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.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/core/coordinate_dimension.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 it,
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);
if (it != last)
{
// initialize box with first element in range
dispatch::envelope
<
value_type
>::apply(*it, mbr, strategy.get_element_envelope_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.get_element_expand_strategy());
}
}
}
template <typename Range, typename Box, typename Strategy>
static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
{
return apply(Strategy::begin(range), Strategy::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)
{
apply(boost::begin(multirange), boost::end(multirange), mbr, strategy);
}
template <typename Iter, typename Box, typename Strategy>
static inline void apply(Iter it,
Iter last,
Box& mbr,
Strategy const& strategy)
{
typename Strategy::template multi_state<Box> state;
for (; it != last; ++it)
{
if (! geometry::is_empty(*it))
{
Box helper_mbr;
EnvelopePolicy::apply(*it, helper_mbr, strategy);
state.apply(helper_mbr);
}
}
state.result(mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP

View File

@@ -0,0 +1,338 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2018, 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_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/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.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/normalize_spheroidal_coordinates.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/indexed_point_view.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>
static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
{
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
<
min_corner,
Dimension,
DimensionCount
>::apply(mbr, *it);
detail::expand::indexed_loop
<
max_corner,
Dimension,
DimensionCount
>::apply(mbr, *it);
}
}
};
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>
static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
{
// boxes in the range are assumed to be normalized already
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
typedef typename coordinate_type<box_type>::type coordinate_type;
typedef typename detail::cs_angular_units<box_type>::type units_type;
typedef typename boost::range_iterator
<
RangeOfBoxes const
>::type iterator_type;
static const bool is_equatorial = ! boost::is_same
<
typename cs_tag<box_type>::type,
spherical_polar_tag
>::value;
typedef math::detail::constants_on_spheroid
<
coordinate_type, units_type, is_equatorial
> 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)
{
if (is_inverse_spheroidal_coordinates(*it))
{
continue;
}
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);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP

View File

@@ -0,0 +1,95 @@
// 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-2018.
// Modifications copyright (c) 2015-2018, 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 <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
// For backward compatibility
#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
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
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)
{
strategy.apply(p1, p2, mbr);
}
template <typename Segment, 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]);
apply(p[0], p[1], mbr, strategy);
}
};
}} // 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,401 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2014-2018 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_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
#include <cstddef>
#include <vector>
#include <boost/range.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
// For trivial checks
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/length.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace equals
{
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct point_point
{
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
{
return Strategy::apply(point1, point2);
}
};
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
|| !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
{
return false;
}
return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
}
};
template <std::size_t DimensionCount>
struct box_box<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
{
return true;
}
};
struct segment_segment
{
template <typename Segment1, typename Segment2, typename Strategy>
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
Strategy const& strategy)
{
typename Strategy::point_in_point_strategy_type const&
pt_pt_strategy = strategy.get_point_in_point_strategy();
return equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 0>(segment2),
pt_pt_strategy)
? equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 1>(segment2),
pt_pt_strategy)
: ( equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 1>(segment2),
pt_pt_strategy)
&& equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 0>(segment2),
pt_pt_strategy)
);
}
};
struct area_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::area(geometry1,
strategy.template get_area_strategy<Geometry1>()),
geometry::area(geometry2,
strategy.template get_area_strategy<Geometry2>()));
}
};
struct length_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::length(geometry1,
strategy.template get_distance_strategy<Geometry1>()),
geometry::length(geometry2,
strategy.template get_distance_strategy<Geometry2>()));
}
};
template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
struct collected_vector
{
typedef typename geometry::select_most_precise
<
typename select_coordinate_type
<
Geometry1, Geometry2
>::type,
double
>::type calculation_type;
typedef geometry::collected_vector
<
calculation_type,
Geometry1,
typename IntersectionStrategy::side_strategy_type
> type;
};
template <typename TrivialCheck>
struct equals_by_collection
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
{
return false;
}
typedef typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type collected_vector_type;
std::vector<collected_vector_type> c1, c2;
geometry::collect_vectors(c1, geometry1);
geometry::collect_vectors(c2, geometry2);
if (boost::size(c1) != boost::size(c2))
{
return false;
}
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
// Just check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin());
}
};
template<typename Geometry1, typename Geometry2>
struct equals_by_relate
: detail::relate::relate_impl
<
detail::de9im::static_mask_equals_type,
Geometry1,
Geometry2
>
{};
// If collect_vectors which is a SideStrategy-dispatched optimization
// is implemented in a way consistent with the Intersection/Side Strategy
// then collect_vectors is used, otherwise relate is used.
// NOTE: the result could be conceptually different for invalid
// geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently.
template<typename TrivialCheck>
struct equals_by_collection_or_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
typedef typename boost::is_base_of
<
nyi::not_implemented_tag,
typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type
>::type enable_relate_type;
return apply(geometry1, geometry2, strategy, enable_relate_type());
}
private:
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::false_type /*enable_relate*/)
{
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::true_type /*enable_relate*/)
{
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
};
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
: detail::equals::point_point<0, DimensionCount>
{};
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
{};
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<Point, MultiPoint>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
: detail::equals::box_box<0, DimensionCount>
{};
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Ring, typename Box, bool Reverse>
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon, typename Box, bool Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
: detail::equals::segment_segment
{};
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
template <typename LineString, typename MultiLineString, bool Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, MultiLineString>
{};
template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
{};
template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename MultiPolygon, bool Reverse>
struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename MultiPolygon, typename Ring, bool Reverse>
struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP

View File

@@ -0,0 +1,317 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017.
// Modifications copyright (c) 2014-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_EQUALS_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_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/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.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,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct equals: not_implemented<Tag1, Tag2>
{};
// If reversal is needed, perform it
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
std::size_t DimensionCount
>
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return equals
<
Geometry2, Geometry1,
Tag2, Tag1,
DimensionCount,
false
>::apply(g2, g1, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct equals
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::equals
<
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 dispatch::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct equals
{
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::equals
::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct equals<boost::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>
inline bool operator()(Geometry1 const& geometry1) const
{
return equals<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 equals<Geometry1, boost::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>
inline bool operator()(Geometry2 const& geometry2) const
{
return equals<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 equals<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::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>
inline bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return equals<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_check{are spatially equal}
\details \details_check12{equals, is spatially equal}. Spatially equal means
that the same point set is included. A box can therefore be spatially equal
to a ring or a polygon, or a linestring can be spatially equal to a
multi-linestring or a segment. This only works theoretically, not all
combinations are implemented yet.
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Equals}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{equals}
\return \return_check2{are spatially equal}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool equals(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check{are spatially equal}
\details \details_check12{equals, is spatially equal}. Spatially equal means
that the same point set is included. A box can therefore be spatially equal
to a ring or a polygon, or a linestring can be spatially equal to a
multi-linestring or a segment. This only works theoretically, not all
combinations are implemented yet.
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{are spatially equal}
\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP

View File

@@ -0,0 +1,48 @@
// 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-2018.
// Modifications copyright (c) 2013-2018, 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
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, typename Strategy>
inline bool equals_point_point(Point1 const& point1, Point2 const& point2,
Strategy const& )
{
return Strategy::apply(point1, point2);
}
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP

View File

@@ -0,0 +1,67 @@
// 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, 2017, 2018.
// Modifications copyright (c) 2015-2018, 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_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/tags.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/expand_box.hpp>
#include <boost/geometry/strategies/spherical/expand_box.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// Box + box -> new box containing two input boxes
template
<
typename BoxOut, typename BoxIn
>
struct expand
<
BoxOut, BoxIn,
box_tag, box_tag
>
{
template <typename Strategy>
static inline void apply(BoxOut& box_out,
BoxIn const& box_in,
Strategy const& )
{
Strategy::apply(box_out, box_in);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP

View File

@@ -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

View File

@@ -0,0 +1,121 @@
// 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, 2017, 2018.
// Modifications copyright (c) 2015-2018, 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_EXPAND_INDEXED_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace expand
{
template
<
std::size_t Index,
std::size_t Dimension, std::size_t DimensionCount
>
struct indexed_loop
{
template <typename Box, typename Geometry>
static inline void apply(Box& box, Geometry const& source)
{
typedef typename select_coordinate_type
<
Box,
Geometry
>::type coordinate_type;
coordinate_type const coord = get<Index, Dimension>(source);
std::less<coordinate_type> less;
std::greater<coordinate_type> greater;
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
<
Index, Dimension + 1, DimensionCount
>::apply(box, source);
}
};
template <std::size_t Index, std::size_t DimensionCount>
struct indexed_loop
<
Index, DimensionCount, DimensionCount
>
{
template <typename Box, typename Geometry>
static inline void apply(Box&, Geometry const&) {}
};
// Changes a box such that the other box is also contained by the box
template <std::size_t Dimension, std::size_t DimensionCount>
struct expand_indexed
{
template <typename Box, typename Geometry>
static inline void apply(Box& box, Geometry const& geometry)
{
indexed_loop
<
0, Dimension, DimensionCount
>::apply(box, geometry);
indexed_loop
<
1, Dimension, DimensionCount
>::apply(box, geometry);
}
};
}} // namespace detail::expand
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP

View File

@@ -0,0 +1,198 @@
// 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, 2018.
// Modifications copyright (c) 2015-2018, 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_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/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.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/expand.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 strategy::expand::services::default_strategy
<
typename tag<Geometry>::type,
typename cs_tag<Geometry>::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

View File

@@ -0,0 +1,70 @@
// 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-2018.
// Modifications copyright (c) 2015-2018, 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_EXPAND_POINT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/tags.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/expand_point.hpp>
#include <boost/geometry/strategies/spherical/expand_point.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// Box + point -> new box containing also point
template
<
typename BoxOut, typename Point
>
struct expand
<
BoxOut, Point,
box_tag, point_tag
>
{
template <typename Strategy>
static inline void apply(BoxOut& box,
Point const& point,
Strategy const& )
{
Strategy::apply(box, point);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP

View File

@@ -0,0 +1,69 @@
// 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, 2017, 2018.
// Modifications copyright (c) 2015-2018, 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_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/tags.hpp>
// For backward compatibility
#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
#include <boost/geometry/strategies/geographic/expand_segment.hpp>
#include <boost/geometry/strategies/spherical/expand_segment.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Box, typename Segment
>
struct expand
<
Box, Segment,
box_tag, segment_tag
>
{
template <typename Strategy>
static inline void apply(Box& box,
Segment const& segment,
Strategy const& strategy)
{
boost::ignore_unused(strategy);
strategy.apply(box, segment);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP

View File

@@ -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

View File

@@ -0,0 +1,562 @@
// 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-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018 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_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_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/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;
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, typename SideStrategy>
static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right,
Extremes const& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{
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 = strategy.apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
int const last_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, typename SideStrategy>
static inline void get_intruders(Ring const& ring,
Extremes const& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{
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, strategy);
}
}
template <typename Iterator, typename SideStrategy>
static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
{
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 = strategy.apply(*(right - 1), *right, *left) * factor;
int const last_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, typename SideStrategy>
static inline bool apply(Ring const& ring,
Extremes& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{
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, strategy))
{
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, strategy);
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, typename SideStrategy>
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders,
SideStrategy const& strategy)
{
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, strategy))
{
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, strategy);
}
return true;
}
};
template<typename Box>
struct extreme_points<Box, 1, box_tag>
{
template <typename Extremes, typename Intruders, typename SideStrategy>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
SideStrategy const& )
{
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, typename SideStrategy>
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
SideStrategy const& )
{
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, typename SideStrategy>
static inline bool apply(MultiPolygon const& multi, Extremes& extremes,
Intruders& intruders, SideStrategy const& strategy)
{
// 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, strategy);
}
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,
typename SideStrategy
>
inline bool extreme_points(Geometry const& geometry,
Extremes& extremes,
Intruders& intruders,
SideStrategy const& strategy)
{
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, strategy);
}
template
<
std::size_t Edge,
typename Geometry,
typename Extremes,
typename Intruders
>
inline bool extreme_points(Geometry const& geometry,
Extremes& extremes,
Intruders& intruders)
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Geometry>::type
>::type strategy_type;
return geometry::extreme_points<Edge>(geometry,extremes, intruders, strategy_type());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP

View File

@@ -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

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