stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
|
||||
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/mutable_range.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/geometries/variant.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace append
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_no_action
|
||||
{
|
||||
static inline void apply(Geometry& , Point const& ,
|
||||
int = 0, int = 0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point
|
||||
{
|
||||
static inline void apply(Geometry& geometry, Point const& point,
|
||||
int = 0, int = 0)
|
||||
{
|
||||
typename geometry::point_type<Geometry>::type copy;
|
||||
geometry::detail::conversion::convert_point_to_point(point, copy);
|
||||
traits::push_back<Geometry>::apply(geometry, copy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range
|
||||
{
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
|
||||
static inline void apply(Geometry& geometry, Range const& range,
|
||||
int = 0, int = 0)
|
||||
{
|
||||
for (typename boost::range_iterator<Range const>::type
|
||||
it = boost::begin(range);
|
||||
it != boost::end(range);
|
||||
++it)
|
||||
{
|
||||
append_point<Geometry, point_type>::apply(geometry, *it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon, typename Point>
|
||||
struct point_to_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
static inline void apply(Polygon& polygon, Point const& point,
|
||||
int ring_index, int = 0)
|
||||
{
|
||||
if (ring_index == -1)
|
||||
{
|
||||
append_point<ring_type, Point>::apply(
|
||||
exterior_ring(polygon), point);
|
||||
}
|
||||
else if (ring_index < int(num_interior_rings(polygon)))
|
||||
{
|
||||
append_point<ring_type, Point>::apply(
|
||||
range::at(interior_rings(polygon), ring_index), point);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon, typename Range>
|
||||
struct range_to_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
static inline void apply(Polygon& polygon, Range const& range,
|
||||
int ring_index, int = 0)
|
||||
{
|
||||
if (ring_index == -1)
|
||||
{
|
||||
append_range<ring_type, Range>::apply(
|
||||
exterior_ring(polygon), range);
|
||||
}
|
||||
else if (ring_index < int(num_interior_rings(polygon)))
|
||||
{
|
||||
append_range<ring_type, Range>::apply(
|
||||
range::at(interior_rings(polygon), ring_index), range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::append
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
namespace splitted_dispatch
|
||||
{
|
||||
|
||||
template <typename Tag, typename Geometry, typename Point>
|
||||
struct append_point
|
||||
: detail::append::append_no_action<Geometry, Point>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point<linestring_tag, Geometry, Point>
|
||||
: detail::append::append_point<Geometry, Point>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point<ring_tag, Geometry, Point>
|
||||
: detail::append::append_point<Geometry, Point>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename Point>
|
||||
struct append_point<polygon_tag, Polygon, Point>
|
||||
: detail::append::point_to_polygon<Polygon, Point>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Tag, typename Geometry, typename Range>
|
||||
struct append_range
|
||||
: detail::append::append_no_action<Geometry, Range>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range<linestring_tag, Geometry, Range>
|
||||
: detail::append::append_range<Geometry, Range>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range<ring_tag, Geometry, Range>
|
||||
: detail::append::append_range<Geometry, Range>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename Range>
|
||||
struct append_range<polygon_tag, Polygon, Range>
|
||||
: detail::append::range_to_polygon<Polygon, Range>
|
||||
{};
|
||||
|
||||
} // namespace splitted_dispatch
|
||||
|
||||
|
||||
// Default: append a range (or linestring or ring or whatever) to any geometry
|
||||
template
|
||||
<
|
||||
typename Geometry, typename RangeOrPoint,
|
||||
typename TagRangeOrPoint = typename tag<RangeOrPoint>::type
|
||||
>
|
||||
struct append
|
||||
: splitted_dispatch::append_range<typename tag<Geometry>::type, Geometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
// Specialization for point to append a point to any geometry
|
||||
template <typename Geometry, typename RangeOrPoint>
|
||||
struct append<Geometry, RangeOrPoint, point_tag>
|
||||
: splitted_dispatch::append_point<typename tag<Geometry>::type, Geometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace append
|
||||
{
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_to_multigeometry
|
||||
{
|
||||
static inline void apply(MultiGeometry& multigeometry,
|
||||
RangeOrPoint const& range_or_point,
|
||||
int ring_index, int multi_index)
|
||||
{
|
||||
|
||||
dispatch::append
|
||||
<
|
||||
typename boost::range_value<MultiGeometry>::type,
|
||||
RangeOrPoint
|
||||
>::apply(range::at(multigeometry, multi_index), range_or_point, ring_index);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::append
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
namespace splitted_dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point<multi_point_tag, Geometry, Point>
|
||||
: detail::append::append_point<Geometry, Point>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range<multi_point_tag, Geometry, Range>
|
||||
: detail::append::append_range<Geometry, Range>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_point<multi_linestring_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_range<multi_linestring_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_point<multi_polygon_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_range<multi_polygon_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
} // namespace splitted_dispatch
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct append
|
||||
{
|
||||
template <typename RangeOrPoint>
|
||||
static inline void apply(Geometry& geometry,
|
||||
RangeOrPoint const& range_or_point,
|
||||
int ring_index,
|
||||
int multi_index)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
dispatch::append<Geometry, RangeOrPoint>::apply(geometry,
|
||||
range_or_point,
|
||||
ring_index,
|
||||
multi_index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename RangeOrPoint>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
RangeOrPoint const& m_range_or_point;
|
||||
int m_ring_index;
|
||||
int m_multi_index;
|
||||
|
||||
visitor(RangeOrPoint const& range_or_point,
|
||||
int ring_index,
|
||||
int multi_index):
|
||||
m_range_or_point(range_or_point),
|
||||
m_ring_index(ring_index),
|
||||
m_multi_index(multi_index)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry& geometry) const
|
||||
{
|
||||
append<Geometry>::apply(geometry,
|
||||
m_range_or_point,
|
||||
m_ring_index,
|
||||
m_multi_index);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RangeOrPoint>
|
||||
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& variant_geometry,
|
||||
RangeOrPoint const& range_or_point,
|
||||
int ring_index,
|
||||
int multi_index)
|
||||
{
|
||||
boost::apply_visitor(
|
||||
visitor<RangeOrPoint>(
|
||||
range_or_point,
|
||||
ring_index,
|
||||
multi_index
|
||||
),
|
||||
variant_geometry
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant;
|
||||
|
||||
|
||||
/*!
|
||||
\brief Appends one or more points to a linestring, ring, polygon, multi-geometry
|
||||
\ingroup append
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam RangeOrPoint Either a range or a point, fullfilling Boost.Range concept or Boost.Geometry Point Concept
|
||||
\param geometry \param_geometry
|
||||
\param range_or_point The point or range to add
|
||||
\param ring_index The index of the ring in case of a polygon:
|
||||
exterior ring (-1, the default) or interior ring index
|
||||
\param multi_index The index of the geometry to which the points are appended
|
||||
|
||||
\qbk{[include reference/algorithms/append.qbk]}
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename RangeOrPoint>
|
||||
inline void append(Geometry& geometry, RangeOrPoint const& range_or_point,
|
||||
int ring_index = -1, int multi_index = 0)
|
||||
{
|
||||
resolve_variant::append<Geometry>
|
||||
::apply(geometry, range_or_point, ring_index, multi_index);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
|
||||
@@ -0,0 +1,329 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/range/functions.hpp>
|
||||
#include <boost/range/metafunctions.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/calculate_null.hpp>
|
||||
#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
|
||||
// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_sum.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
#include <boost/geometry/strategies/default_area_result.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/concepts/area_concept.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/order_as_direction.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace area
|
||||
{
|
||||
|
||||
struct box_area
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline typename coordinate_type<Box>::type
|
||||
apply(Box const& box, Strategy const&)
|
||||
{
|
||||
// Currently only works for 2D Cartesian boxes
|
||||
assert_dimension<Box, 2>();
|
||||
|
||||
return (get<max_corner, 0>(box) - get<min_corner, 0>(box))
|
||||
* (get<max_corner, 1>(box) - get<min_corner, 1>(box));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
iterate_direction Direction,
|
||||
closure_selector Closure
|
||||
>
|
||||
struct ring_area
|
||||
{
|
||||
template <typename Ring, typename Strategy>
|
||||
static inline typename Strategy::return_type
|
||||
apply(Ring const& ring, Strategy const& strategy)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Strategy>) );
|
||||
assert_dimension<Ring, 2>();
|
||||
|
||||
// Ignore warning (because using static method sometimes) on strategy
|
||||
boost::ignore_unused_variable_warning(strategy);
|
||||
|
||||
// An open ring has at least three points,
|
||||
// A closed ring has at least four points,
|
||||
// if not, there is no (zero) area
|
||||
if (boost::size(ring)
|
||||
< core_detail::closure::minimum_ring_size<Closure>::value)
|
||||
{
|
||||
return typename Strategy::return_type();
|
||||
}
|
||||
|
||||
typedef typename reversible_view<Ring const, Direction>::type rview_type;
|
||||
typedef typename closeable_view
|
||||
<
|
||||
rview_type const, Closure
|
||||
>::type view_type;
|
||||
typedef typename boost::range_iterator<view_type const>::type iterator_type;
|
||||
|
||||
rview_type rview(ring);
|
||||
view_type view(rview);
|
||||
typename Strategy::state_type state;
|
||||
iterator_type it = boost::begin(view);
|
||||
iterator_type end = boost::end(view);
|
||||
|
||||
for (iterator_type previous = it++;
|
||||
it != end;
|
||||
++previous, ++it)
|
||||
{
|
||||
strategy.apply(*previous, *it, state);
|
||||
}
|
||||
|
||||
return strategy.result(state);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::area
|
||||
|
||||
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
struct area : detail::calculate_null
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct area<Geometry, box_tag> : detail::area::box_area
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct area<Ring, ring_tag>
|
||||
: detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Ring>::value>::value,
|
||||
geometry::closure<Ring>::value
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon>
|
||||
struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)
|
||||
{
|
||||
return calculate_polygon_sum::apply<
|
||||
typename Strategy::return_type,
|
||||
detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Polygon>::value>::value,
|
||||
geometry::closure<Polygon>::value
|
||||
>
|
||||
>(polygon, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiGeometry>
|
||||
struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type
|
||||
apply(MultiGeometry const& multi, Strategy const& strategy)
|
||||
{
|
||||
return multi_sum::apply
|
||||
<
|
||||
typename Strategy::return_type,
|
||||
area<typename boost::range_value<MultiGeometry>::type>
|
||||
>(multi, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct area
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type apply(Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<typename Strategy::return_type>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry>
|
||||
typename Strategy::return_type operator()(Geometry const& geometry) const
|
||||
{
|
||||
return area<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{area}
|
||||
\ingroup area
|
||||
\details \details_calc{area}. \details_default_strategy
|
||||
|
||||
The area algorithm calculates the surface area of all geometries having a surface, namely
|
||||
box, polygon, ring, multipolygon. The units are the square of the units used for the points
|
||||
defining the surface. If subject geometry is defined in meters, then area is calculated
|
||||
in square meters.
|
||||
|
||||
The area calculation can be done in all three common coordinate systems, Cartesian, Spherical
|
||||
and Geographic as well.
|
||||
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_calc{area}
|
||||
|
||||
\qbk{[include reference/algorithms/area.qbk]}
|
||||
\qbk{[heading Examples]}
|
||||
\qbk{[area] [area_output]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline typename default_area_result<Geometry>::type area(Geometry const& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// TODO put this into a resolve_strategy stage
|
||||
// (and take the return type from resolve_variant)
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
point_type
|
||||
>::type strategy_type;
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_variant::area<Geometry>::apply(geometry, strategy_type());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{area} \brief_strategy
|
||||
\ingroup area
|
||||
\details \details_calc{area} \brief_strategy. \details_strategy_reasons
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Area}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{area}
|
||||
\return \return_calc{area}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{
|
||||
[include reference/algorithms/area.qbk]
|
||||
|
||||
[heading Example]
|
||||
[area_with_strategy]
|
||||
[area_with_strategy_output]
|
||||
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
|
||||
\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
|
||||
[/link geometry.reference.strategies.strategy_area_geographic Geographic]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline typename Strategy::return_type area(
|
||||
Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_variant::area<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
@@ -0,0 +1,379 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/concept/requires.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Assign a range of points to a linestring, ring or polygon
|
||||
\note The point-type of the range might be different from the point-type of the geometry
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Range \tparam_range_point
|
||||
\param geometry \param_geometry
|
||||
\param range \param_range_point
|
||||
|
||||
\qbk{
|
||||
[heading Notes]
|
||||
[note Assign automatically clears the geometry before assigning (use append if you don't want that)]
|
||||
[heading Example]
|
||||
[assign_points] [assign_points_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.append append]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Range>
|
||||
inline void assign_points(Geometry& geometry, Range const& range)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
clear(geometry);
|
||||
geometry::append(geometry, range, -1, 0);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief assign to a box inverse infinite
|
||||
\details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
|
||||
min corner is very large, the max corner is very small. This is a convenient starting point to
|
||||
collect the minimum bounding box of a geometry.
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_inverse] [assign_inverse_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.make.make_inverse make_inverse]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void assign_inverse(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign_inverse
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry
|
||||
>::apply(geometry);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief assign zero values to a box, point
|
||||
\ingroup assign
|
||||
\details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void assign_zero(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign_zero
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry
|
||||
>::apply(geometry);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign two coordinates to a geometry (usually a 2D point)
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Type \tparam_numeric to specify the coordinates
|
||||
\param geometry \param_geometry
|
||||
\param c1 \param_x
|
||||
\param c2 \param_y
|
||||
|
||||
\qbk{distinguish, 2 coordinate values}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_2d_point] [assign_2d_point_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Type>
|
||||
inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
geometry::dimension<Geometry>::type::value
|
||||
>::apply(geometry, c1, c2);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign three values to a geometry (usually a 3D point)
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Type \tparam_numeric to specify the coordinates
|
||||
\param geometry \param_geometry
|
||||
\param c1 \param_x
|
||||
\param c2 \param_y
|
||||
\param c3 \param_z
|
||||
|
||||
\qbk{distinguish, 3 coordinate values}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_3d_point] [assign_3d_point_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Type>
|
||||
inline void assign_values(Geometry& geometry,
|
||||
Type const& c1, Type const& c2, Type const& c3)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
geometry::dimension<Geometry>::type::value
|
||||
>::apply(geometry, c1, c2, c3);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign four values to a geometry (usually a box or segment)
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Type \tparam_numeric to specify the coordinates
|
||||
\param geometry \param_geometry
|
||||
\param c1 First coordinate (usually x1)
|
||||
\param c2 Second coordinate (usually y1)
|
||||
\param c3 Third coordinate (usually x2)
|
||||
\param c4 Fourth coordinate (usually y2)
|
||||
|
||||
\qbk{distinguish, 4 coordinate values}
|
||||
*/
|
||||
template <typename Geometry, typename Type>
|
||||
inline void assign_values(Geometry& geometry,
|
||||
Type const& c1, Type const& c2, Type const& c3, Type const& c4)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
geometry::dimension<Geometry>::type::value
|
||||
>::apply(geometry, c1, c2, c3, c4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct assign
|
||||
{
|
||||
static inline void
|
||||
apply(Geometry1& geometry1, const Geometry2& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1>();
|
||||
concepts::check<Geometry2 const>();
|
||||
concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
|
||||
|
||||
static bool const same_point_order
|
||||
= point_order<Geometry1>::value == point_order<Geometry2>::value;
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
(same_point_order),
|
||||
ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER,
|
||||
(types<Geometry1, Geometry2>)
|
||||
);
|
||||
static bool const same_closure
|
||||
= closure<Geometry1>::value == closure<Geometry2>::value;
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
(same_closure),
|
||||
ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE,
|
||||
(types<Geometry1, Geometry2>)
|
||||
);
|
||||
|
||||
dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
|
||||
visitor(Geometry2 const& geometry2)
|
||||
: m_geometry2(geometry2)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
result_type operator()(Geometry1& geometry1) const
|
||||
{
|
||||
return assign
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply
|
||||
(geometry1, m_geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
return boost::apply_visitor(visitor(geometry2), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
Geometry1& m_geometry1;
|
||||
|
||||
visitor(Geometry1 const& geometry1)
|
||||
: m_geometry1(geometry1)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
result_type operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return assign
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply
|
||||
(m_geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(Geometry1& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
|
||||
{
|
||||
return boost::apply_visitor(visitor(geometry1), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
result_type operator()(
|
||||
Geometry1& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return assign
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply
|
||||
(geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
|
||||
{
|
||||
return boost::apply_visitor(visitor(), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Assigns one geometry to another geometry
|
||||
\details The assign algorithm assigns one geometry, e.g. a BOX, to another
|
||||
geometry, e.g. a RING. This only works if it is possible and applicable.
|
||||
\ingroup assign
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry (target)
|
||||
\param geometry2 \param_geometry (source)
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign] [assign_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.convert convert]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
resolve_variant::assign<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
|
||||
@@ -0,0 +1,302 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
|
||||
struct box_loop
|
||||
{
|
||||
typedef typename coordinate_type<BoxOut>::type coordinate_type;
|
||||
|
||||
static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
coordinate_type d = distance;
|
||||
set<C, D>(box_out, get<C, D>(box_in) + d);
|
||||
box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
|
||||
struct box_loop<BoxIn, BoxOut, T, C, N, N>
|
||||
{
|
||||
static inline void apply(BoxIn const&, T const&, BoxOut&) {}
|
||||
};
|
||||
|
||||
// Extends a box with the same amount in all directions
|
||||
template<typename BoxIn, typename BoxOut, typename T>
|
||||
inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
assert_dimension_equal<BoxIn, BoxOut>();
|
||||
|
||||
static const std::size_t N = dimension<BoxIn>::value;
|
||||
|
||||
box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
|
||||
box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Input,
|
||||
typename Output,
|
||||
typename TagIn = typename tag<Input>::type,
|
||||
typename TagOut = typename tag<Output>::type
|
||||
>
|
||||
struct buffer: not_implemented<TagIn, TagOut>
|
||||
{};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct buffer<BoxIn, BoxOut, box_tag, box_tag>
|
||||
{
|
||||
template <typename Distance>
|
||||
static inline void apply(BoxIn const& box_in, Distance const& distance,
|
||||
Distance const& , BoxOut& box_out)
|
||||
{
|
||||
detail::buffer::buffer_box(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct buffer
|
||||
{
|
||||
template <typename Distance, typename GeometryOut>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Distance const& distance,
|
||||
Distance const& chord_length,
|
||||
GeometryOut& out)
|
||||
{
|
||||
dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Distance, typename GeometryOut>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Distance const& m_distance;
|
||||
Distance const& m_chord_length;
|
||||
GeometryOut& m_out;
|
||||
|
||||
visitor(Distance const& distance,
|
||||
Distance const& chord_length,
|
||||
GeometryOut& out)
|
||||
: m_distance(distance),
|
||||
m_chord_length(chord_length),
|
||||
m_out(out)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry) const
|
||||
{
|
||||
buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Distance, typename GeometryOut>
|
||||
static inline void apply(
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Distance const& distance,
|
||||
Distance const& chord_length,
|
||||
GeometryOut& out
|
||||
)
|
||||
{
|
||||
boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{buffer, \det_buffer}.
|
||||
\tparam Input \tparam_geometry
|
||||
\tparam Output \tparam_geometry
|
||||
\tparam Distance \tparam_numeric
|
||||
\param geometry_in \param_geometry
|
||||
\param geometry_out \param_geometry
|
||||
\param distance The distance to be used for the buffer
|
||||
\param chord_length (optional) The length of the chord's in the generated arcs around points or bends
|
||||
|
||||
\qbk{[include reference/algorithms/buffer.qbk]}
|
||||
*/
|
||||
template <typename Input, typename Output, typename Distance>
|
||||
inline void buffer(Input const& geometry_in, Output& geometry_out,
|
||||
Distance const& distance, Distance const& chord_length = -1)
|
||||
{
|
||||
concepts::check<Input const>();
|
||||
concepts::check<Output>();
|
||||
|
||||
resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
|
||||
\tparam Input \tparam_geometry
|
||||
\tparam Output \tparam_geometry
|
||||
\tparam Distance \tparam_numeric
|
||||
\param geometry \param_geometry
|
||||
\param distance The distance to be used for the buffer
|
||||
\param chord_length (optional) The length of the chord's in the generated arcs
|
||||
around points or bends (RESERVED, NOT YET USED)
|
||||
\return \return_calc{buffer}
|
||||
*/
|
||||
template <typename Output, typename Input, typename Distance>
|
||||
Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
|
||||
{
|
||||
concepts::check<Input const>();
|
||||
concepts::check<Output>();
|
||||
|
||||
Output geometry_out;
|
||||
|
||||
resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);
|
||||
|
||||
return geometry_out;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{buffer, \det_buffer}.
|
||||
\tparam GeometryIn \tparam_geometry
|
||||
\tparam MultiPolygon \tparam_geometry{MultiPolygon}
|
||||
\tparam DistanceStrategy A strategy defining distance (or radius)
|
||||
\tparam SideStrategy A strategy defining creation along sides
|
||||
\tparam JoinStrategy A strategy defining creation around convex corners
|
||||
\tparam EndStrategy A strategy defining creation at linestring ends
|
||||
\tparam PointStrategy A strategy defining creation around points
|
||||
\param geometry_in \param_geometry
|
||||
\param geometry_out output multi polygon (or std:: collection of polygons),
|
||||
will contain a buffered version of the input geometry
|
||||
\param distance_strategy The distance strategy to be used
|
||||
\param side_strategy The side strategy to be used
|
||||
\param join_strategy The join strategy to be used
|
||||
\param end_strategy The end strategy to be used
|
||||
\param point_strategy The point strategy to be used
|
||||
|
||||
\qbk{distinguish,with strategies}
|
||||
\qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename GeometryIn,
|
||||
typename MultiPolygon,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy
|
||||
>
|
||||
inline void buffer(GeometryIn const& geometry_in,
|
||||
MultiPolygon& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
typedef typename boost::range_value<MultiPolygon>::type polygon_type;
|
||||
concepts::check<GeometryIn const>();
|
||||
concepts::check<polygon_type>();
|
||||
|
||||
typedef typename point_type<GeometryIn>::type point_type;
|
||||
typedef typename rescale_policy_type<point_type>::type rescale_policy_type;
|
||||
|
||||
geometry_out.clear();
|
||||
|
||||
if (geometry::is_empty(geometry_in))
|
||||
{
|
||||
// Then output geometry is kept empty as well
|
||||
return;
|
||||
}
|
||||
|
||||
model::box<point_type> box;
|
||||
geometry::envelope(geometry_in, box);
|
||||
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
|
||||
|
||||
typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<GeometryIn>::type
|
||||
>::type intersection_strategy;
|
||||
|
||||
rescale_policy_type rescale_policy
|
||||
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
|
||||
|
||||
detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
|
||||
distance_strategy,
|
||||
side_strategy,
|
||||
join_strategy,
|
||||
end_strategy,
|
||||
point_strategy,
|
||||
intersection_strategy,
|
||||
rescale_policy);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
@@ -0,0 +1,681 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015.
|
||||
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/strategies/centroid.hpp>
|
||||
#include <boost/geometry/strategies/concepts/centroid_concept.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
|
||||
|
||||
/*!
|
||||
\brief Centroid Exception
|
||||
\ingroup centroid
|
||||
\details The centroid_exception is thrown if the free centroid function is called with
|
||||
geometries for which the centroid cannot be calculated. For example: a linestring
|
||||
without points, a polygon without points, an empty multi-geometry.
|
||||
\qbk{
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.centroid the centroid function]
|
||||
}
|
||||
|
||||
*/
|
||||
class centroid_exception : public geometry::exception
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
\brief The default constructor
|
||||
*/
|
||||
inline centroid_exception() {}
|
||||
|
||||
/*!
|
||||
\brief Returns the explanatory string.
|
||||
\return Pointer to a null-terminated string with explanatory information.
|
||||
*/
|
||||
virtual char const* what() const throw()
|
||||
{
|
||||
return "Boost.Geometry Centroid calculation exception";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace centroid
|
||||
{
|
||||
|
||||
struct centroid_point
|
||||
{
|
||||
template<typename Point, typename PointCentroid, typename Strategy>
|
||||
static inline void apply(Point const& point, PointCentroid& centroid,
|
||||
Strategy const&)
|
||||
{
|
||||
geometry::convert(point, centroid);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Indexed,
|
||||
typename Point,
|
||||
std::size_t Dimension = 0,
|
||||
std::size_t DimensionCount = dimension<Indexed>::type::value
|
||||
>
|
||||
struct centroid_indexed_calculator
|
||||
{
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Indexed, Point
|
||||
>::type coordinate_type;
|
||||
static inline void apply(Indexed const& indexed, Point& centroid)
|
||||
{
|
||||
coordinate_type const c1 = get<min_corner, Dimension>(indexed);
|
||||
coordinate_type const c2 = get<max_corner, Dimension>(indexed);
|
||||
coordinate_type m = c1 + c2;
|
||||
coordinate_type const two = 2;
|
||||
m /= two;
|
||||
|
||||
set<Dimension>(centroid, m);
|
||||
|
||||
centroid_indexed_calculator
|
||||
<
|
||||
Indexed, Point, Dimension + 1
|
||||
>::apply(indexed, centroid);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Indexed, typename Point, std::size_t DimensionCount>
|
||||
struct centroid_indexed_calculator<Indexed, Point, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Indexed const& , Point& )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct centroid_indexed
|
||||
{
|
||||
template<typename Indexed, typename Point, typename Strategy>
|
||||
static inline void apply(Indexed const& indexed, Point& centroid,
|
||||
Strategy const&)
|
||||
{
|
||||
centroid_indexed_calculator
|
||||
<
|
||||
Indexed, Point
|
||||
>::apply(indexed, centroid);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// There is one thing where centroid is different from e.g. within.
|
||||
// If the ring has only one point, it might make sense that
|
||||
// that point is the centroid.
|
||||
template<typename Point, typename Range>
|
||||
inline bool range_ok(Range const& range, Point& centroid)
|
||||
{
|
||||
std::size_t const n = boost::size(range);
|
||||
if (n > 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (n <= 0)
|
||||
{
|
||||
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
|
||||
BOOST_THROW_EXCEPTION(centroid_exception());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else // if (n == 1)
|
||||
{
|
||||
// Take over the first point in a "coordinate neutral way"
|
||||
geometry::convert(*boost::begin(range), centroid);
|
||||
return false;
|
||||
}
|
||||
//return true; // unreachable
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Calculate the centroid of a Ring or a Linestring.
|
||||
*/
|
||||
template <closure_selector Closure>
|
||||
struct centroid_range_state
|
||||
{
|
||||
template<typename Ring, typename PointTransformer, typename Strategy>
|
||||
static inline void apply(Ring const& ring,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
typename Strategy::state_type& state)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
|
||||
typedef typename geometry::point_type<Ring const>::type point_type;
|
||||
typedef typename closeable_view<Ring const, Closure>::type view_type;
|
||||
|
||||
typedef typename boost::range_iterator<view_type const>::type iterator_type;
|
||||
|
||||
view_type view(ring);
|
||||
iterator_type it = boost::begin(view);
|
||||
iterator_type end = boost::end(view);
|
||||
|
||||
if (it != end)
|
||||
{
|
||||
typename PointTransformer::result_type
|
||||
previous_pt = transformer.apply(*it);
|
||||
|
||||
for ( ++it ; it != end ; ++it)
|
||||
{
|
||||
typename PointTransformer::result_type
|
||||
pt = transformer.apply(*it);
|
||||
|
||||
strategy.apply(static_cast<point_type const&>(previous_pt),
|
||||
static_cast<point_type const&>(pt),
|
||||
state);
|
||||
|
||||
previous_pt = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <closure_selector Closure>
|
||||
struct centroid_range
|
||||
{
|
||||
template<typename Range, typename Point, typename Strategy>
|
||||
static inline bool apply(Range const& range, Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (range_ok(range, centroid))
|
||||
{
|
||||
// prepare translation transformer
|
||||
translating_transformer<Range> transformer(*boost::begin(range));
|
||||
|
||||
typename Strategy::state_type state;
|
||||
centroid_range_state<Closure>::apply(range, transformer,
|
||||
strategy, state);
|
||||
|
||||
if ( strategy.result(state, centroid) )
|
||||
{
|
||||
// translate the result back
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Centroid of a polygon.
|
||||
\note Because outer ring is clockwise, inners are counter clockwise,
|
||||
triangle approach is OK and works for polygons with rings.
|
||||
*/
|
||||
struct centroid_polygon_state
|
||||
{
|
||||
template<typename Polygon, typename PointTransformer, typename Strategy>
|
||||
static inline void apply(Polygon const& poly,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
typename Strategy::state_type& state)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;
|
||||
|
||||
per_ring::apply(exterior_ring(poly), transformer, strategy, state);
|
||||
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(poly);
|
||||
|
||||
for (typename detail::interior_iterator<Polygon const>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
per_ring::apply(*it, transformer, strategy, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct centroid_polygon
|
||||
{
|
||||
template<typename Polygon, typename Point, typename Strategy>
|
||||
static inline bool apply(Polygon const& poly, Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (range_ok(exterior_ring(poly), centroid))
|
||||
{
|
||||
// prepare translation transformer
|
||||
translating_transformer<Polygon>
|
||||
transformer(*boost::begin(exterior_ring(poly)));
|
||||
|
||||
typename Strategy::state_type state;
|
||||
centroid_polygon_state::apply(poly, transformer, strategy, state);
|
||||
|
||||
if ( strategy.result(state, centroid) )
|
||||
{
|
||||
// translate the result back
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Building block of a multi-point, to be used as Policy in the
|
||||
more generec centroid_multi
|
||||
*/
|
||||
struct centroid_multi_point_state
|
||||
{
|
||||
template <typename Point, typename PointTransformer, typename Strategy>
|
||||
static inline void apply(Point const& point,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
typename Strategy::state_type& state)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
strategy.apply(static_cast<Point const&>(transformer.apply(point)),
|
||||
state);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Generic implementation which calls a policy to calculate the
|
||||
centroid of the total of its single-geometries
|
||||
\details The Policy is, in general, the single-version, with state. So
|
||||
detail::centroid::centroid_polygon_state is used as a policy for this
|
||||
detail::centroid::centroid_multi
|
||||
|
||||
*/
|
||||
template <typename Policy>
|
||||
struct centroid_multi
|
||||
{
|
||||
template <typename Multi, typename Point, typename Strategy>
|
||||
static inline bool apply(Multi const& multi,
|
||||
Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
|
||||
// If there is nothing in any of the ranges, it is not possible
|
||||
// to calculate the centroid
|
||||
if (geometry::is_empty(multi))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(centroid_exception());
|
||||
}
|
||||
#endif
|
||||
|
||||
// prepare translation transformer
|
||||
translating_transformer<Multi> transformer(multi);
|
||||
|
||||
typename Strategy::state_type state;
|
||||
|
||||
for (typename boost::range_iterator<Multi const>::type
|
||||
it = boost::begin(multi);
|
||||
it != boost::end(multi);
|
||||
++it)
|
||||
{
|
||||
Policy::apply(*it, transformer, strategy, state);
|
||||
}
|
||||
|
||||
if ( strategy.result(state, centroid) )
|
||||
{
|
||||
// translate the result back
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Algorithm>
|
||||
struct centroid_linear_areal
|
||||
{
|
||||
template <typename Geometry, typename Point, typename Strategy>
|
||||
static inline void apply(Geometry const& geom,
|
||||
Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( ! Algorithm::apply(geom, centroid, strategy) )
|
||||
{
|
||||
geometry::point_on_border(centroid, geom);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::centroid
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
struct centroid: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct centroid<Geometry, point_tag>
|
||||
: detail::centroid::centroid_point
|
||||
{};
|
||||
|
||||
template <typename Box>
|
||||
struct centroid<Box, box_tag>
|
||||
: detail::centroid::centroid_indexed
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct centroid<Segment, segment_tag>
|
||||
: detail::centroid::centroid_indexed
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct centroid<Ring, ring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_range<geometry::closure<Ring>::value>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Linestring>
|
||||
struct centroid<Linestring, linestring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_range<closed>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct centroid<Polygon, polygon_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct centroid<MultiLinestring, multi_linestring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_range_state<closed>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct centroid<MultiPolygon, multi_polygon_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_polygon_state
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct centroid<MultiPoint, multi_point_tag>
|
||||
: detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_multi_point_state
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
template <typename Geometry>
|
||||
struct centroid
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
|
||||
{
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategy);
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
static inline void apply(Geometry const& geometry, Point& out, default_strategy)
|
||||
{
|
||||
typedef typename strategy::centroid::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type,
|
||||
typename tag_cast
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
pointlike_tag,
|
||||
linear_tag,
|
||||
areal_tag
|
||||
>::type,
|
||||
dimension<Geometry>::type::value,
|
||||
Point,
|
||||
Geometry
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct centroid
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions<Point, Geometry const>();
|
||||
resolve_strategy::centroid<Geometry>::apply(geometry, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Point& m_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Point& out, Strategy const& strategy)
|
||||
: m_out(out), m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry) const
|
||||
{
|
||||
centroid<Geometry>::apply(geometry, m_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point, typename Strategy>
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Point& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Point, Strategy>(out, strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid} \brief_strategy
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_strategy_reasons
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Point \tparam_point
|
||||
\tparam Strategy \tparam_strategy{Centroid}
|
||||
\param geometry \param_geometry
|
||||
\param c \param_point \param_set{centroid}
|
||||
\param strategy \param_strategy{centroid}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
\qbk{[include reference/algorithms/centroid_strategies.qbk]}
|
||||
}
|
||||
|
||||
*/
|
||||
template<typename Geometry, typename Point, typename Strategy>
|
||||
inline void centroid(Geometry const& geometry, Point& c,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::centroid<Geometry>::apply(geometry, c, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid}
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_default_strategy
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Point \tparam_point
|
||||
\param geometry \param_geometry
|
||||
\param c The calculated centroid will be assigned to this point reference
|
||||
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[centroid]
|
||||
[centroid_output]
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Point>
|
||||
inline void centroid(Geometry const& geometry, Point& c)
|
||||
{
|
||||
geometry::centroid(geometry, c, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid}
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}.
|
||||
\tparam Point \tparam_point
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_calc{centroid}
|
||||
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
*/
|
||||
template<typename Point, typename Geometry>
|
||||
inline Point return_centroid(Geometry const& geometry)
|
||||
{
|
||||
Point c;
|
||||
geometry::centroid(geometry, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid} \brief_strategy
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. \details_strategy_reasons
|
||||
\tparam Point \tparam_point
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{centroid}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{centroid}
|
||||
\return \return_calc{centroid}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
\qbk{[include reference/algorithms/centroid_strategies.qbk]}
|
||||
*/
|
||||
template<typename Point, typename Geometry, typename Strategy>
|
||||
inline Point return_centroid(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
Point c;
|
||||
geometry::centroid(geometry, c, strategy);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
|
||||
@@ -0,0 +1,197 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
|
||||
|
||||
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/mutable_range.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace clear
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct collection_clear
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
{
|
||||
traits::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Polygon>
|
||||
struct polygon_clear
|
||||
{
|
||||
static inline void apply(Polygon& polygon)
|
||||
{
|
||||
traits::clear
|
||||
<
|
||||
typename boost::remove_reference
|
||||
<
|
||||
typename traits::interior_mutable_type<Polygon>::type
|
||||
>::type
|
||||
>::apply(interior_rings(polygon));
|
||||
traits::clear
|
||||
<
|
||||
typename boost::remove_reference
|
||||
<
|
||||
typename traits::ring_mutable_type<Polygon>::type
|
||||
>::type
|
||||
>::apply(exterior_ring(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct no_action
|
||||
{
|
||||
static inline void apply(Geometry& )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::clear
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
|
||||
>
|
||||
struct clear: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
// Point/box/segment do not have clear. So specialize to do nothing.
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, point_tag>
|
||||
: detail::clear::no_action<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, box_tag>
|
||||
: detail::clear::no_action<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, segment_tag>
|
||||
: detail::clear::no_action<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, linestring_tag>
|
||||
: detail::clear::collection_clear<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, ring_tag>
|
||||
: detail::clear::collection_clear<Geometry>
|
||||
{};
|
||||
|
||||
|
||||
// Polygon can (indirectly) use std for clear
|
||||
template <typename Polygon>
|
||||
struct clear<Polygon, polygon_tag>
|
||||
: detail::clear::polygon_clear<Polygon>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, multi_tag>
|
||||
: detail::clear::collection_clear<Geometry>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
{
|
||||
dispatch::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct clear<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
template <typename Geometry>
|
||||
inline void operator()(Geometry& geometry) const
|
||||
{
|
||||
clear<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
|
||||
{
|
||||
boost::apply_visitor(visitor(), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Clears a linestring, ring or polygon (exterior+interiors) or multi*
|
||||
\details Generic function to clear a geometry. All points will be removed from the collection or collections
|
||||
making up the geometry. In most cases this is equivalent to the .clear() method of a std::vector<...>. In
|
||||
the case of a polygon, this clear functionality is automatically called for the exterior ring, and for the
|
||||
interior ring collection. In the case of a point, boxes and segments, nothing will happen.
|
||||
\ingroup clear
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry which will be cleared
|
||||
\note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero"
|
||||
|
||||
\qbk{[include reference/algorithms/clear.qbk]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void clear(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
resolve_variant::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
|
||||
@@ -0,0 +1,559 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/for_each.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
// Silence warning C4512: assignment operator could not be generated
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127 4512)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace conversion
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Box,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_to_box
|
||||
{
|
||||
static inline void apply(Point const& point, Box& box)
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
set<Index, Dimension>(box,
|
||||
boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
|
||||
point_to_box
|
||||
<
|
||||
Point, Box,
|
||||
Index, Dimension + 1, DimensionCount
|
||||
>::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Box,
|
||||
std::size_t Index,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Point const& , Box& )
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename Box, typename Range, bool Close, bool Reverse>
|
||||
struct box_to_range
|
||||
{
|
||||
static inline void apply(Box const& box, Range& range)
|
||||
{
|
||||
traits::resize<Range>::apply(range, Close ? 5 : 4);
|
||||
assign_box_corners_oriented<Reverse>(box, range);
|
||||
if (Close)
|
||||
{
|
||||
range::at(range, 4) = range::at(range, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Segment, typename Range>
|
||||
struct segment_to_range
|
||||
{
|
||||
static inline void apply(Segment const& segment, Range& range)
|
||||
{
|
||||
traits::resize<Range>::apply(range, 2);
|
||||
|
||||
typename boost::range_iterator<Range>::type it = boost::begin(range);
|
||||
|
||||
assign_point_from_index<0>(segment, *it);
|
||||
++it;
|
||||
assign_point_from_index<1>(segment, *it);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Range1,
|
||||
typename Range2,
|
||||
bool Reverse = false
|
||||
>
|
||||
struct range_to_range
|
||||
{
|
||||
typedef typename reversible_view
|
||||
<
|
||||
Range1 const,
|
||||
Reverse ? iterate_reverse : iterate_forward
|
||||
>::type rview_type;
|
||||
typedef typename closeable_view
|
||||
<
|
||||
rview_type const,
|
||||
geometry::closure<Range1>::value
|
||||
>::type view_type;
|
||||
|
||||
static inline void apply(Range1 const& source, Range2& destination)
|
||||
{
|
||||
geometry::clear(destination);
|
||||
|
||||
rview_type rview(source);
|
||||
|
||||
// We consider input always as closed, and skip last
|
||||
// point for open output.
|
||||
view_type view(rview);
|
||||
|
||||
typedef typename boost::range_size<Range1>::type size_type;
|
||||
size_type n = boost::size(view);
|
||||
if (geometry::closure<Range2>::value == geometry::open)
|
||||
{
|
||||
n--;
|
||||
}
|
||||
|
||||
// If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()
|
||||
// but ok, sice below it == end()
|
||||
|
||||
size_type i = 0;
|
||||
for (typename boost::range_iterator<view_type const>::type it
|
||||
= boost::begin(view);
|
||||
it != boost::end(view) && i < n;
|
||||
++it, ++i)
|
||||
{
|
||||
geometry::append(destination, *it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct polygon_to_polygon
|
||||
{
|
||||
typedef range_to_range
|
||||
<
|
||||
typename geometry::ring_type<Polygon1>::type,
|
||||
typename geometry::ring_type<Polygon2>::type,
|
||||
geometry::point_order<Polygon1>::value
|
||||
!= geometry::point_order<Polygon2>::value
|
||||
> per_ring;
|
||||
|
||||
static inline void apply(Polygon1 const& source, Polygon2& destination)
|
||||
{
|
||||
// Clearing managed per ring, and in the resizing of interior rings
|
||||
|
||||
per_ring::apply(geometry::exterior_ring(source),
|
||||
geometry::exterior_ring(destination));
|
||||
|
||||
// Container should be resizeable
|
||||
traits::resize
|
||||
<
|
||||
typename boost::remove_reference
|
||||
<
|
||||
typename traits::interior_mutable_type<Polygon2>::type
|
||||
>::type
|
||||
>::apply(interior_rings(destination), num_interior_rings(source));
|
||||
|
||||
typename interior_return_type<Polygon1 const>::type
|
||||
rings_source = interior_rings(source);
|
||||
typename interior_return_type<Polygon2>::type
|
||||
rings_dest = interior_rings(destination);
|
||||
|
||||
typename detail::interior_iterator<Polygon1 const>::type
|
||||
it_source = boost::begin(rings_source);
|
||||
typename detail::interior_iterator<Polygon2>::type
|
||||
it_dest = boost::begin(rings_dest);
|
||||
|
||||
for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
|
||||
{
|
||||
per_ring::apply(*it_source, *it_dest);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Single, typename Multi, typename Policy>
|
||||
struct single_to_multi: private Policy
|
||||
{
|
||||
static inline void apply(Single const& single, Multi& multi)
|
||||
{
|
||||
traits::resize<Multi>::apply(multi, 1);
|
||||
Policy::apply(single, *boost::begin(multi));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename Multi1, typename Multi2, typename Policy>
|
||||
struct multi_to_multi: private Policy
|
||||
{
|
||||
static inline void apply(Multi1 const& multi1, Multi2& multi2)
|
||||
{
|
||||
traits::resize<Multi2>::apply(multi2, boost::size(multi1));
|
||||
|
||||
typename boost::range_iterator<Multi1 const>::type it1
|
||||
= boost::begin(multi1);
|
||||
typename boost::range_iterator<Multi2>::type it2
|
||||
= boost::begin(multi2);
|
||||
|
||||
for (; it1 != boost::end(multi1); ++it1, ++it2)
|
||||
{
|
||||
Policy::apply(*it1, *it2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::conversion
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
|
||||
typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
|
||||
std::size_t DimensionCount = dimension<Geometry1>::type::value,
|
||||
bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value
|
||||
&& !boost::is_array<Geometry1>::value
|
||||
>
|
||||
struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
|
||||
{
|
||||
// Same geometry type -> copy whole geometry
|
||||
static inline void apply(Geometry1 const& source, Geometry2& destination)
|
||||
{
|
||||
destination = source;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
|
||||
: detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
|
||||
: detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment1, typename Segment2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
|
||||
: detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment, typename LineString, std::size_t DimensionCount>
|
||||
struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
|
||||
: detail::conversion::segment_to_range<Segment, LineString>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring1, typename Ring2, std::size_t DimensionCount>
|
||||
struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
|
||||
: detail::conversion::range_to_range
|
||||
<
|
||||
Ring1,
|
||||
Ring2,
|
||||
geometry::point_order<Ring1>::value
|
||||
!= geometry::point_order<Ring2>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename LineString1, typename LineString2, std::size_t DimensionCount>
|
||||
struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
|
||||
: detail::conversion::range_to_range<LineString1, LineString2>
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
|
||||
struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
|
||||
: detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
|
||||
{};
|
||||
|
||||
template <typename Box, typename Ring>
|
||||
struct convert<Box, Ring, box_tag, ring_tag, 2, false>
|
||||
: detail::conversion::box_to_range
|
||||
<
|
||||
Box,
|
||||
Ring,
|
||||
geometry::closure<Ring>::value == closed,
|
||||
geometry::point_order<Ring>::value == counterclockwise
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box, typename Polygon>
|
||||
struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
|
||||
{
|
||||
static inline void apply(Box const& box, Polygon& polygon)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
convert
|
||||
<
|
||||
Box, ring_type,
|
||||
box_tag, ring_tag,
|
||||
2, false
|
||||
>::apply(box, exterior_ring(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Point, typename Box, std::size_t DimensionCount>
|
||||
struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
|
||||
{
|
||||
static inline void apply(Point const& point, Box& box)
|
||||
{
|
||||
detail::conversion::point_to_box
|
||||
<
|
||||
Point, Box, min_corner, 0, DimensionCount
|
||||
>::apply(point, box);
|
||||
detail::conversion::point_to_box
|
||||
<
|
||||
Point, Box, max_corner, 0, DimensionCount
|
||||
>::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring, typename Polygon, std::size_t DimensionCount>
|
||||
struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
|
||||
{
|
||||
static inline void apply(Ring const& ring, Polygon& polygon)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
convert
|
||||
<
|
||||
Ring, ring_type,
|
||||
ring_tag, ring_tag,
|
||||
DimensionCount, false
|
||||
>::apply(ring, exterior_ring(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon, typename Ring, std::size_t DimensionCount>
|
||||
struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
|
||||
{
|
||||
static inline void apply(Polygon const& polygon, Ring& ring)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
convert
|
||||
<
|
||||
ring_type, Ring,
|
||||
ring_tag, ring_tag,
|
||||
DimensionCount, false
|
||||
>::apply(exterior_ring(polygon), ring);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Dispatch for multi <-> multi, specifying their single-version as policy.
|
||||
// Note that, even if the multi-types are mutually different, their single
|
||||
// version types might be the same and therefore we call boost::is_same again
|
||||
|
||||
template <typename Multi1, typename Multi2, std::size_t DimensionCount>
|
||||
struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
|
||||
: detail::conversion::multi_to_multi
|
||||
<
|
||||
Multi1,
|
||||
Multi2,
|
||||
convert
|
||||
<
|
||||
typename boost::range_value<Multi1>::type,
|
||||
typename boost::range_value<Multi2>::type,
|
||||
typename single_tag_of
|
||||
<
|
||||
typename tag<Multi1>::type
|
||||
>::type,
|
||||
typename single_tag_of
|
||||
<
|
||||
typename tag<Multi2>::type
|
||||
>::type,
|
||||
DimensionCount
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>
|
||||
struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>
|
||||
: detail::conversion::single_to_multi
|
||||
<
|
||||
Single,
|
||||
Multi,
|
||||
convert
|
||||
<
|
||||
Single,
|
||||
typename boost::range_value<Multi>::type,
|
||||
typename tag<Single>::type,
|
||||
typename single_tag_of
|
||||
<
|
||||
typename tag<Multi>::type
|
||||
>::type,
|
||||
DimensionCount,
|
||||
false
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct convert
|
||||
{
|
||||
static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
|
||||
dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
Geometry2& m_geometry2;
|
||||
|
||||
visitor(Geometry2& geometry2)
|
||||
: m_geometry2(geometry2)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
inline void operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void apply(
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2& geometry2
|
||||
)
|
||||
{
|
||||
boost::apply_visitor(visitor(geometry2), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Converts one geometry to another geometry
|
||||
\details The convert algorithm converts one geometry, e.g. a BOX, to another
|
||||
geometry, e.g. a RING. This only works if it is possible and applicable.
|
||||
If the point-order is different, or the closure is different between two
|
||||
geometry types, it will be converted correctly by explicitly reversing the
|
||||
points or closing or opening the polygon rings.
|
||||
\ingroup convert
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry (source)
|
||||
\param geometry2 \param_geometry (target)
|
||||
|
||||
\qbk{[include reference/algorithms/convert.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
|
||||
{
|
||||
resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
||||
@@ -0,0 +1,375 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015.
|
||||
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
|
||||
|
||||
#include <boost/array.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/convex_hull.hpp>
|
||||
#include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/range_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
#include <boost/geometry/algorithms/detail/as_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace convex_hull
|
||||
{
|
||||
|
||||
template <order_selector Order, closure_selector Closure>
|
||||
struct hull_insert
|
||||
{
|
||||
|
||||
// Member template function (to avoid inconvenient declaration
|
||||
// of output-iterator-type, from hull_to_geometry)
|
||||
template <typename Geometry, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry const& geometry,
|
||||
OutputIterator out, Strategy const& strategy)
|
||||
{
|
||||
typename Strategy::state_type state;
|
||||
|
||||
strategy.apply(geometry, state);
|
||||
strategy.result(state, out, Order == clockwise, Closure != open);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
struct hull_to_geometry
|
||||
{
|
||||
template <typename Geometry, typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry, OutputGeometry& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
hull_insert
|
||||
<
|
||||
geometry::point_order<OutputGeometry>::value,
|
||||
geometry::closure<OutputGeometry>::value
|
||||
>::apply(geometry,
|
||||
range::back_inserter(
|
||||
// Handle linestring, ring and polygon the same:
|
||||
detail::as_range
|
||||
<
|
||||
typename range_type<OutputGeometry>::type
|
||||
>(out)), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::convex_hull
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
struct convex_hull
|
||||
: detail::convex_hull::hull_to_geometry
|
||||
{};
|
||||
|
||||
template <typename Box>
|
||||
struct convex_hull<Box, box_tag>
|
||||
{
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(Box const& box, OutputGeometry& out,
|
||||
Strategy const& )
|
||||
{
|
||||
static bool const Close
|
||||
= geometry::closure<OutputGeometry>::value == closed;
|
||||
static bool const Reverse
|
||||
= geometry::point_order<OutputGeometry>::value == counterclockwise;
|
||||
|
||||
// A hull for boxes is trivial. Any strategy is (currently) skipped.
|
||||
boost::array<typename point_type<Box>::type, 4> range;
|
||||
geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
|
||||
geometry::append(out, range);
|
||||
if (BOOST_GEOMETRY_CONDITION(Close))
|
||||
{
|
||||
geometry::append(out, *boost::begin(range));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <order_selector Order, closure_selector Closure>
|
||||
struct convex_hull_insert
|
||||
: detail::convex_hull::hull_insert<Order, Closure>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct convex_hull
|
||||
{
|
||||
template <typename Geometry, typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
|
||||
dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename OutputGeometry>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy_convex_hull<
|
||||
Geometry,
|
||||
typename point_type<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
apply(geometry, out, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
struct convex_hull_insert
|
||||
{
|
||||
template <typename Geometry, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry const& geometry,
|
||||
OutputIterator& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
|
||||
|
||||
return dispatch::convex_hull_insert<
|
||||
geometry::point_order<Geometry>::value,
|
||||
geometry::closure<Geometry>::value
|
||||
>::apply(geometry, out, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename OutputIterator>
|
||||
static inline OutputIterator apply(Geometry const& geometry,
|
||||
OutputIterator& out,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy_convex_hull<
|
||||
Geometry,
|
||||
typename point_type<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
return apply(geometry, out, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct convex_hull
|
||||
{
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions<
|
||||
const Geometry,
|
||||
OutputGeometry
|
||||
>();
|
||||
|
||||
resolve_strategy::convex_hull::apply(geometry, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
OutputGeometry& m_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(OutputGeometry& out, Strategy const& strategy)
|
||||
: m_out(out), m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry) const
|
||||
{
|
||||
convex_hull<Geometry>::apply(geometry, m_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct convex_hull_insert
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy)
|
||||
{
|
||||
// Concept: output point type = point type of input geometry
|
||||
concepts::check<Geometry const>();
|
||||
concepts::check<typename point_type<Geometry>::type>();
|
||||
|
||||
return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
struct visitor: boost::static_visitor<OutputIterator>
|
||||
{
|
||||
OutputIterator& m_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(OutputIterator& out, Strategy const& strategy)
|
||||
: m_out(out), m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
OutputIterator operator()(Geometry const& geometry) const
|
||||
{
|
||||
return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
OutputIterator& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
template<typename Geometry, typename OutputGeometry, typename Strategy>
|
||||
inline void convex_hull(Geometry const& geometry,
|
||||
OutputGeometry& out, Strategy const& strategy)
|
||||
{
|
||||
if (geometry::is_empty(geometry))
|
||||
{
|
||||
// Leave output empty
|
||||
return;
|
||||
}
|
||||
|
||||
resolve_variant::convex_hull<Geometry>::apply(geometry, out, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{convex hull}
|
||||
\ingroup convex_hull
|
||||
\details \details_calc{convex_hull,convex hull}.
|
||||
\tparam Geometry the input geometry type
|
||||
\tparam OutputGeometry the output geometry type
|
||||
\param geometry \param_geometry, input geometry
|
||||
\param hull \param_geometry \param_set{convex hull}
|
||||
|
||||
\qbk{[include reference/algorithms/convex_hull.qbk]}
|
||||
*/
|
||||
template<typename Geometry, typename OutputGeometry>
|
||||
inline void convex_hull(Geometry const& geometry,
|
||||
OutputGeometry& hull)
|
||||
{
|
||||
geometry::convex_hull(geometry, hull, default_strategy());
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace convex_hull
|
||||
{
|
||||
|
||||
|
||||
template<typename Geometry, typename OutputIterator, typename Strategy>
|
||||
inline OutputIterator convex_hull_insert(Geometry const& geometry,
|
||||
OutputIterator out, Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::convex_hull_insert<Geometry>
|
||||
::apply(geometry, out, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Calculate the convex hull of a geometry, output-iterator version
|
||||
\ingroup convex_hull
|
||||
\tparam Geometry the input geometry type
|
||||
\tparam OutputIterator: an output-iterator
|
||||
\param geometry the geometry to calculate convex hull from
|
||||
\param out an output iterator outputing points of the convex hull
|
||||
\note This overloaded version outputs to an output iterator.
|
||||
In this case, nothing is known about its point-type or
|
||||
about its clockwise order. Therefore, the input point-type
|
||||
and order are copied
|
||||
|
||||
*/
|
||||
template<typename Geometry, typename OutputIterator>
|
||||
inline OutputIterator convex_hull_insert(Geometry const& geometry,
|
||||
OutputIterator out)
|
||||
{
|
||||
return convex_hull_insert(geometry, out, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::convex_hull
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
|
||||
@@ -0,0 +1,338 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/mutable_range.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
|
||||
#include <boost/geometry/util/order_as_direction.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace correct
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_nop
|
||||
{
|
||||
static inline void apply(Geometry& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct correct_box_loop
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
static inline void apply(Box& box)
|
||||
{
|
||||
if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
|
||||
{
|
||||
// Swap the coordinates
|
||||
coordinate_type max_value = get<min_corner, Dimension>(box);
|
||||
coordinate_type min_value = get<max_corner, Dimension>(box);
|
||||
set<min_corner, Dimension>(box, min_value);
|
||||
set<max_corner, Dimension>(box, max_value);
|
||||
}
|
||||
|
||||
correct_box_loop
|
||||
<
|
||||
Box, Dimension + 1, DimensionCount
|
||||
>::apply(box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename Box, std::size_t DimensionCount>
|
||||
struct correct_box_loop<Box, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Box& )
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Correct a box: make min/max correct
|
||||
template <typename Box>
|
||||
struct correct_box
|
||||
{
|
||||
|
||||
static inline void apply(Box& box)
|
||||
{
|
||||
// Currently only for Cartesian coordinates
|
||||
// (or spherical without crossing dateline)
|
||||
// Future version: adapt using strategies
|
||||
correct_box_loop
|
||||
<
|
||||
Box, 0, dimension<Box>::type::value
|
||||
>::apply(box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Close a ring, if not closed
|
||||
template <typename Ring, typename Predicate>
|
||||
struct correct_ring
|
||||
{
|
||||
typedef typename point_type<Ring>::type point_type;
|
||||
typedef typename coordinate_type<Ring>::type coordinate_type;
|
||||
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
point_type
|
||||
>::type strategy_type;
|
||||
|
||||
typedef detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Ring>::value>::value,
|
||||
geometry::closure<Ring>::value
|
||||
> ring_area_type;
|
||||
|
||||
|
||||
static inline void apply(Ring& r)
|
||||
{
|
||||
// Check close-ness
|
||||
if (boost::size(r) > 2)
|
||||
{
|
||||
// check if closed, if not, close it
|
||||
bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
|
||||
closure_selector const s = geometry::closure<Ring>::value;
|
||||
|
||||
if (disjoint && (s == closed))
|
||||
{
|
||||
geometry::append(r, *boost::begin(r));
|
||||
}
|
||||
if (! disjoint && s != closed)
|
||||
{
|
||||
// Open it by removing last point
|
||||
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
|
||||
}
|
||||
}
|
||||
// Check area
|
||||
Predicate predicate;
|
||||
typedef typename default_area_result<Ring>::type area_result_type;
|
||||
area_result_type const zero = area_result_type();
|
||||
if (predicate(ring_area_type::apply(r, strategy_type()), zero))
|
||||
{
|
||||
std::reverse(boost::begin(r), boost::end(r));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all
|
||||
// inner rings counter clockwise (or vice versa depending on orientation)
|
||||
template <typename Polygon>
|
||||
struct correct_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef typename default_area_result<Polygon>::type area_result_type;
|
||||
|
||||
static inline void apply(Polygon& poly)
|
||||
{
|
||||
correct_ring
|
||||
<
|
||||
ring_type,
|
||||
std::less<area_result_type>
|
||||
>::apply(exterior_ring(poly));
|
||||
|
||||
typename interior_return_type<Polygon>::type
|
||||
rings = interior_rings(poly);
|
||||
for (typename detail::interior_iterator<Polygon>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
correct_ring
|
||||
<
|
||||
ring_type,
|
||||
std::greater<area_result_type>
|
||||
>::apply(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::correct
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Point>
|
||||
struct correct<Point, point_tag>
|
||||
: detail::correct::correct_nop<Point>
|
||||
{};
|
||||
|
||||
template <typename LineString>
|
||||
struct correct<LineString, linestring_tag>
|
||||
: detail::correct::correct_nop<LineString>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct correct<Segment, segment_tag>
|
||||
: detail::correct::correct_nop<Segment>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct correct<Box, box_tag>
|
||||
: detail::correct::correct_box<Box>
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct correct<Ring, ring_tag>
|
||||
: detail::correct::correct_ring
|
||||
<
|
||||
Ring,
|
||||
std::less<typename default_area_result<Ring>::type>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct correct<Polygon, polygon_tag>
|
||||
: detail::correct::correct_polygon<Polygon>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct correct<MultiPoint, multi_point_tag>
|
||||
: detail::correct::correct_nop<MultiPoint>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLineString>
|
||||
struct correct<MultiLineString, multi_linestring_tag>
|
||||
: detail::correct::correct_nop<MultiLineString>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct<Geometry, multi_polygon_tag>
|
||||
: detail::multi_modify
|
||||
<
|
||||
Geometry,
|
||||
detail::correct::correct_polygon
|
||||
<
|
||||
typename boost::range_value<Geometry>::type
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
dispatch::correct<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry& geometry) const
|
||||
{
|
||||
correct<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
|
||||
{
|
||||
boost::apply_visitor(visitor(), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Corrects a geometry
|
||||
\details Corrects a geometry: all rings which are wrongly oriented with respect
|
||||
to their expected orientation are reversed. To all rings which do not have a
|
||||
closing point and are typed as they should have one, the first point is
|
||||
appended. Also boxes can be corrected.
|
||||
\ingroup correct
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry which will be corrected if necessary
|
||||
|
||||
\qbk{[include reference/algorithms/correct.qbk]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void correct(Geometry& geometry)
|
||||
{
|
||||
resolve_variant::correct<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
|
||||
@@ -0,0 +1,462 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2017.
|
||||
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace covered_by {
|
||||
|
||||
struct use_point_in_geometry
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct use_relate
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
typedef typename detail::de9im::static_mask_covered_by_type
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type covered_by_mask;
|
||||
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::covered_by
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct covered_by
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Box>
|
||||
struct covered_by<Point, Box, point_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
::boost::ignore_unused_variable_warning(strategy);
|
||||
return strategy.apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct covered_by<Box1, Box2, box_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
::boost::ignore_unused_variable_warning(strategy);
|
||||
return strategy.apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// P/P
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct covered_by<Point1, Point2, point_tag, point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPoint>
|
||||
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// P/L
|
||||
|
||||
template <typename Point, typename Segment>
|
||||
struct covered_by<Point, Segment, point_tag, segment_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Linestring>
|
||||
struct covered_by<Point, Linestring, point_tag, linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiLinestring>
|
||||
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// P/A
|
||||
|
||||
template <typename Point, typename Ring>
|
||||
struct covered_by<Point, Ring, point_tag, ring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Polygon>
|
||||
struct covered_by<Point, Polygon, point_tag, polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPolygon>
|
||||
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// L/L
|
||||
|
||||
template <typename Linestring1, typename Linestring2>
|
||||
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiLinestring>
|
||||
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Linestring>
|
||||
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring1, typename MultiLinestring2>
|
||||
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// L/A
|
||||
|
||||
template <typename Linestring, typename Ring>
|
||||
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Ring>
|
||||
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename Polygon>
|
||||
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Polygon>
|
||||
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiPolygon>
|
||||
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename MultiPolygon>
|
||||
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// A/A
|
||||
|
||||
template <typename Ring1, typename Ring2>
|
||||
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename Polygon>
|
||||
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Ring>
|
||||
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename MultiPolygon>
|
||||
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Ring>
|
||||
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename MultiPolygon>
|
||||
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Polygon>
|
||||
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon1, typename MultiPolygon2>
|
||||
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::within::check
|
||||
<
|
||||
typename tag<Geometry1>::type,
|
||||
typename tag<Geometry2>::type,
|
||||
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
|
||||
Strategy
|
||||
>();
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
assert_dimension_equal<Geometry1, Geometry2>();
|
||||
|
||||
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
|
||||
geometry2,
|
||||
strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::covered_by::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return covered_by::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::covered_by
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2, Strategy const& strategy)
|
||||
: m_geometry2(geometry2), m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry1>
|
||||
bool operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, m_geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1, Strategy const& strategy)
|
||||
: m_geometry1(geometry1), m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry2>
|
||||
bool operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(m_geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(Geometry1 const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T1),
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T2)
|
||||
>
|
||||
struct covered_by<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
bool operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border}
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
\note The default strategy is used for covered_by detection
|
||||
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border} \brief_strategy
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\param strategy strategy to be used
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
@@ -0,0 +1,267 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/relate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct crosses
|
||||
: detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_crosses_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
struct crosses
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct crosses
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::crosses::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2, Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
result_type operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return crosses
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, m_geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct crosses<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1, Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
result_type operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return crosses
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(m_geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
result_type operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return crosses
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{crosses}
|
||||
\ingroup crosses
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Crosses}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{crosses}
|
||||
\return \return_check2{crosses}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/crosses.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool crosses(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{crosses}
|
||||
\ingroup crosses
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_check2{crosses}
|
||||
|
||||
\qbk{[include reference/algorithms/crosses.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
|
||||
@@ -0,0 +1,105 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/add_const_if_c.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename GeometryTag, typename Geometry, typename Range, bool IsConst>
|
||||
struct as_range
|
||||
{
|
||||
static inline typename add_const_if_c<IsConst, Range>::type& get(
|
||||
typename add_const_if_c<IsConst, Geometry>::type& input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry, typename Range, bool IsConst>
|
||||
struct as_range<polygon_tag, Geometry, Range, IsConst>
|
||||
{
|
||||
static inline typename add_const_if_c<IsConst, Range>::type& get(
|
||||
typename add_const_if_c<IsConst, Geometry>::type& input)
|
||||
{
|
||||
return exterior_ring(input);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
// Will probably be replaced by the more generic "view_as", therefore in detail
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Function getting either the range (ring, linestring) itself
|
||||
or the outer ring (polygon)
|
||||
\details Utility to handle polygon's outer ring as a range
|
||||
\ingroup utility
|
||||
*/
|
||||
template <typename Range, typename Geometry>
|
||||
inline Range& as_range(Geometry& input)
|
||||
{
|
||||
return dispatch::as_range
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
Range,
|
||||
false
|
||||
>::get(input);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Function getting either the range (ring, linestring) itself
|
||||
or the outer ring (polygon), const version
|
||||
\details Utility to handle polygon's outer ring as a range
|
||||
\ingroup utility
|
||||
*/
|
||||
template <typename Range, typename Geometry>
|
||||
inline Range const& as_range(Geometry const& input)
|
||||
{
|
||||
return dispatch::as_range
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
Range,
|
||||
true
|
||||
>::get(input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
|
||||
+107
@@ -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
|
||||
+94
@@ -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
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/concept/requires.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace assign
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct initialize
|
||||
{
|
||||
template <typename Box>
|
||||
static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)
|
||||
{
|
||||
geometry::set<Index, Dimension>(box, value);
|
||||
initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t Index, std::size_t DimensionCount>
|
||||
struct initialize<Index, DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box>
|
||||
static inline void apply(Box&, typename coordinate_type<Box>::type const&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
struct assign_zero_point
|
||||
{
|
||||
template <typename Point>
|
||||
static inline void apply(Point& point)
|
||||
{
|
||||
geometry::assign_value(point, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct assign_inverse_box_or_segment
|
||||
{
|
||||
|
||||
template <typename BoxOrSegment>
|
||||
static inline void apply(BoxOrSegment& geometry)
|
||||
{
|
||||
typedef typename point_type<BoxOrSegment>::type point_type;
|
||||
typedef typename coordinate_type<point_type>::type bound_type;
|
||||
|
||||
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, boost::numeric::bounds<bound_type>::highest()
|
||||
);
|
||||
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, boost::numeric::bounds<bound_type>::lowest()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct assign_zero_box_or_segment
|
||||
{
|
||||
template <typename BoxOrSegment>
|
||||
static inline void apply(BoxOrSegment& geometry)
|
||||
{
|
||||
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
|
||||
|
||||
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, coordinate_type()
|
||||
);
|
||||
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, coordinate_type()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Corner1, std::size_t Corner2,
|
||||
typename Box, typename Point
|
||||
>
|
||||
inline void assign_box_2d_corner(Box const& box, Point& point)
|
||||
{
|
||||
// Be sure both are 2-Dimensional
|
||||
assert_dimension<Box, 2>();
|
||||
assert_dimension<Point, 2>();
|
||||
|
||||
// Copy coordinates
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
|
||||
geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry, typename Point,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct assign_point_to_index
|
||||
{
|
||||
|
||||
static inline void apply(Point const& point, Geometry& geometry)
|
||||
{
|
||||
geometry::set<Index, Dimension>(geometry, boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>(geometry::get<Dimension>(point)));
|
||||
|
||||
assign_point_to_index
|
||||
<
|
||||
Geometry, Point, Index, Dimension + 1, DimensionCount
|
||||
>::apply(point, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry, typename Point,
|
||||
std::size_t Index,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct assign_point_to_index
|
||||
<
|
||||
Geometry, Point,
|
||||
Index,
|
||||
DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
static inline void apply(Point const& , Geometry& )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry, typename Point,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct assign_point_from_index
|
||||
{
|
||||
|
||||
static inline void apply(Geometry const& geometry, Point& point)
|
||||
{
|
||||
geometry::set<Dimension>( point, boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<Point>::type
|
||||
>(geometry::get<Index, Dimension>(geometry)));
|
||||
|
||||
assign_point_from_index
|
||||
<
|
||||
Geometry, Point, Index, Dimension + 1, DimensionCount
|
||||
>::apply(geometry, point);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry, typename Point,
|
||||
std::size_t Index,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct assign_point_from_index
|
||||
<
|
||||
Geometry, Point,
|
||||
Index,
|
||||
DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
static inline void apply(Geometry const&, Point&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct assign_2d_box_or_segment
|
||||
{
|
||||
typedef typename coordinate_type<Geometry>::type coordinate_type;
|
||||
|
||||
// Here we assign 4 coordinates to a box of segment
|
||||
// -> Most logical is: x1,y1,x2,y2
|
||||
// In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)
|
||||
|
||||
template <typename Type>
|
||||
static inline void apply(Geometry& geometry,
|
||||
Type const& x1, Type const& y1, Type const& x2, Type const& y2)
|
||||
{
|
||||
geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));
|
||||
geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
|
||||
geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
|
||||
geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::assign
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
|
||||
struct assign
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
|
||||
, (types<Geometry>)
|
||||
);
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct assign<point_tag, Point, 2>
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
template <typename T>
|
||||
static inline void apply(Point& point, T const& c1, T const& c2)
|
||||
{
|
||||
set<0>(point, boost::numeric_cast<coordinate_type>(c1));
|
||||
set<1>(point, boost::numeric_cast<coordinate_type>(c2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct assign<point_tag, Point, 3>
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
template <typename T>
|
||||
static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
|
||||
{
|
||||
set<0>(point, boost::numeric_cast<coordinate_type>(c1));
|
||||
set<1>(point, boost::numeric_cast<coordinate_type>(c2));
|
||||
set<2>(point, boost::numeric_cast<coordinate_type>(c3));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct assign<box_tag, Box, 2>
|
||||
: detail::assign::assign_2d_box_or_segment<Box>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign<segment_tag, Segment, 2>
|
||||
: detail::assign::assign_2d_box_or_segment<Segment>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
template <typename GeometryTag, typename Geometry>
|
||||
struct assign_zero {};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct assign_zero<point_tag, Point>
|
||||
: detail::assign::assign_zero_point
|
||||
{};
|
||||
|
||||
template <typename Box>
|
||||
struct assign_zero<box_tag, Box>
|
||||
: detail::assign::assign_zero_box_or_segment
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign_zero<segment_tag, Segment>
|
||||
: detail::assign::assign_zero_box_or_segment
|
||||
{};
|
||||
|
||||
|
||||
template <typename GeometryTag, typename Geometry>
|
||||
struct assign_inverse {};
|
||||
|
||||
template <typename Box>
|
||||
struct assign_inverse<box_tag, Box>
|
||||
: detail::assign::assign_inverse_box_or_segment
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign_inverse<segment_tag, Segment>
|
||||
: detail::assign::assign_inverse_box_or_segment
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
|
||||
@@ -0,0 +1,148 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2016, 2017.
|
||||
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
#include <boost/geometry/formulas/vincenty_inverse.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// An azimuth is an angle between a vector/segment from origin to a point of
|
||||
// interest and a reference vector. Typically north-based azimuth is used.
|
||||
// North direction is used as a reference, angle is measured clockwise
|
||||
// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS
|
||||
// the reference vector is Y axis, angle is measured clockwise.
|
||||
// http://en.wikipedia.org/wiki/Azimuth
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace detail_dispatch
|
||||
{
|
||||
|
||||
template <typename ReturnType, typename Tag>
|
||||
struct azimuth
|
||||
: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, geographic_tag>
|
||||
{
|
||||
template <typename P1, typename P2, typename Spheroid>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)
|
||||
{
|
||||
return geometry::formula::vincenty_inverse<ReturnType, false, true>().apply
|
||||
( get_as_radian<0>(p1), get_as_radian<1>(p1),
|
||||
get_as_radian<0>(p2), get_as_radian<1>(p2),
|
||||
spheroid ).azimuth;
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return apply(p1, p2, srs::spheroid<ReturnType>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, spherical_equatorial_tag>
|
||||
{
|
||||
template <typename P1, typename P2, typename Sphere>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
|
||||
{
|
||||
return geometry::formula::spherical_azimuth<ReturnType, false>
|
||||
( get_as_radian<0>(p1), get_as_radian<1>(p1),
|
||||
get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth;
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return apply(p1, p2, 0); // dummy model
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, spherical_polar_tag>
|
||||
: azimuth<ReturnType, spherical_equatorial_tag>
|
||||
{};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, cartesian_tag>
|
||||
{
|
||||
template <typename P1, typename P2, typename Plane>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/)
|
||||
{
|
||||
ReturnType x = get<0>(p2) - get<0>(p1);
|
||||
ReturnType y = get<1>(p2) - get<1>(p1);
|
||||
|
||||
// NOTE: azimuth 0 is at Y axis, increasing right
|
||||
// as in spherical/geographic where 0 is at North axis
|
||||
return atan2(x, y);
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return apply(p1, p2, 0); // dummy model
|
||||
}
|
||||
};
|
||||
|
||||
} // detail_dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Calculate azimuth between two points.
|
||||
/// The result is in radians.
|
||||
template <typename ReturnType, typename Point1, typename Point2>
|
||||
inline ReturnType azimuth(Point1 const& p1, Point2 const& p2)
|
||||
{
|
||||
return detail_dispatch::azimuth
|
||||
<
|
||||
ReturnType,
|
||||
typename geometry::cs_tag<Point1>::type
|
||||
>::apply(p1, p2);
|
||||
}
|
||||
|
||||
/// Calculate azimuth between two points.
|
||||
/// The result is in radians.
|
||||
template <typename ReturnType, typename Point1, typename Point2, typename Model>
|
||||
inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model)
|
||||
{
|
||||
return detail_dispatch::azimuth
|
||||
<
|
||||
ReturnType,
|
||||
typename geometry::cs_tag<Point1>::type
|
||||
>::apply(p1, p2, model);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
+1033
File diff suppressed because it is too large
Load Diff
+241
@@ -0,0 +1,241 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
|
||||
# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
enum intersection_location_type
|
||||
{
|
||||
location_ok, inside_buffer, location_discard
|
||||
};
|
||||
|
||||
class backtrack_for_buffer
|
||||
{
|
||||
public :
|
||||
typedef detail::overlay::backtrack_state state_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Operation,
|
||||
typename Rings,
|
||||
typename Turns,
|
||||
typename Geometry,
|
||||
typename Strategy,
|
||||
typename RobustPolicy,
|
||||
typename Visitor
|
||||
>
|
||||
static inline void apply(std::size_t size_at_start,
|
||||
Rings& rings, typename boost::range_value<Rings>::type& ring,
|
||||
Turns& turns,
|
||||
typename boost::range_value<Turns>::type const& /*turn*/,
|
||||
Operation& operation,
|
||||
detail::overlay::traverse_error_type /*traverse_error*/,
|
||||
Geometry const& ,
|
||||
Geometry const& ,
|
||||
Strategy const& ,
|
||||
RobustPolicy const& ,
|
||||
state_type& state,
|
||||
Visitor& /*visitor*/
|
||||
)
|
||||
{
|
||||
#if defined(BOOST_GEOMETRY_COUNT_BACKTRACK_WARNINGS)
|
||||
extern int g_backtrack_warning_count;
|
||||
g_backtrack_warning_count++;
|
||||
#endif
|
||||
//std::cout << "!";
|
||||
//std::cout << "WARNING " << traverse_error_string(traverse_error) << std::endl;
|
||||
|
||||
state.m_good = false;
|
||||
|
||||
// Make bad output clean
|
||||
rings.resize(size_at_start);
|
||||
ring.clear();
|
||||
|
||||
// Reject this as a starting point
|
||||
operation.visited.set_rejected();
|
||||
|
||||
// And clear all visit info
|
||||
clear_visit_info(turns);
|
||||
}
|
||||
};
|
||||
|
||||
struct buffer_overlay_visitor
|
||||
{
|
||||
public :
|
||||
void print(char const* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void visit_turns(int , Turns const& ) {}
|
||||
|
||||
template <typename Clusters, typename Turns>
|
||||
void visit_clusters(Clusters const& , Turns const& ) {}
|
||||
|
||||
template <typename Turns, typename Turn, typename Operation>
|
||||
void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns, typename Turn, typename Operation>
|
||||
void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
|
||||
detail::overlay::traverse_error_type )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Should follow traversal-turn-concept (enrichment, visit structure)
|
||||
// and adds index in piece vector to find it back
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct buffer_turn_operation
|
||||
: public detail::overlay::traversal_turn_operation<Point, SegmentRatio>
|
||||
{
|
||||
signed_size_type piece_index;
|
||||
signed_size_type index_in_robust_ring;
|
||||
|
||||
inline buffer_turn_operation()
|
||||
: piece_index(-1)
|
||||
, index_in_robust_ring(-1)
|
||||
{}
|
||||
};
|
||||
|
||||
// Version for buffer including type of location, is_opposite, and helper variables
|
||||
template <typename Point, typename RobustPoint, typename SegmentRatio>
|
||||
struct buffer_turn_info
|
||||
: public detail::overlay::turn_info
|
||||
<
|
||||
Point,
|
||||
SegmentRatio,
|
||||
buffer_turn_operation<Point, SegmentRatio>
|
||||
>
|
||||
{
|
||||
typedef Point point_type;
|
||||
typedef RobustPoint robust_point_type;
|
||||
|
||||
std::size_t turn_index; // TODO: this might go if partition can operate on non-const input
|
||||
|
||||
RobustPoint robust_point;
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
|
||||
// Will (most probably) be removed later
|
||||
RobustPoint mapped_robust_point; // alas... we still need to adapt our points, offsetting them 1 integer to be co-located with neighbours
|
||||
#endif
|
||||
|
||||
|
||||
inline RobustPoint const& get_robust_point() const
|
||||
{
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
|
||||
return mapped_robust_point;
|
||||
#endif
|
||||
return robust_point;
|
||||
}
|
||||
|
||||
intersection_location_type location;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
|
||||
#endif
|
||||
|
||||
std::size_t count_within;
|
||||
|
||||
bool within_original;
|
||||
std::size_t count_on_original_boundary;
|
||||
signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
|
||||
|
||||
std::size_t count_on_offsetted;
|
||||
std::size_t count_on_helper;
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
std::size_t count_within_near_offsetted;
|
||||
#endif
|
||||
|
||||
bool remove_on_multi;
|
||||
|
||||
// Obsolete:
|
||||
std::size_t count_on_occupied;
|
||||
std::size_t count_on_multi;
|
||||
|
||||
inline buffer_turn_info()
|
||||
: turn_index(0)
|
||||
, location(location_ok)
|
||||
, count_within(0)
|
||||
, within_original(false)
|
||||
, count_on_original_boundary(0)
|
||||
, count_in_original(0)
|
||||
, count_on_offsetted(0)
|
||||
, count_on_helper(0)
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
, count_within_near_offsetted(0)
|
||||
#endif
|
||||
, remove_on_multi(false)
|
||||
, count_on_occupied(0)
|
||||
, count_on_multi(0)
|
||||
{}
|
||||
};
|
||||
|
||||
struct buffer_operation_less
|
||||
{
|
||||
template <typename Turn>
|
||||
inline bool operator()(Turn const& left, Turn const& right) const
|
||||
{
|
||||
segment_identifier const& sl = left.seg_id;
|
||||
segment_identifier const& sr = right.seg_id;
|
||||
|
||||
// Sort them descending
|
||||
return sl == sr
|
||||
? left.fraction < right.fraction
|
||||
: sl < sr;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
+1447
File diff suppressed because it is too large
Load Diff
+282
@@ -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
|
||||
+304
@@ -0,0 +1,304 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
struct buffer_assign_turn
|
||||
{
|
||||
static bool const include_no_turn = false;
|
||||
static bool const include_degenerate = false;
|
||||
static bool const include_opposite = false;
|
||||
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Info& info,
|
||||
Point1 const& /*p1*/,
|
||||
Point2 const& /*p2*/,
|
||||
IntersectionInfo const& iinfo)
|
||||
{
|
||||
info.rob_pi = iinfo.rpi();
|
||||
info.rob_pj = iinfo.rpj();
|
||||
info.rob_qi = iinfo.rqi();
|
||||
info.rob_qj = iinfo.rqj();
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
template
|
||||
<
|
||||
typename Pieces,
|
||||
typename Rings,
|
||||
typename Turns,
|
||||
typename IntersectionStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
class piece_turn_visitor
|
||||
{
|
||||
Pieces const& m_pieces;
|
||||
Rings const& m_rings;
|
||||
Turns& m_turns;
|
||||
IntersectionStrategy const& m_intersection_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
template <typename Piece>
|
||||
inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const
|
||||
{
|
||||
if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return piece1.index == piece2.left_index
|
||||
|| piece1.index == piece2.right_index;
|
||||
}
|
||||
|
||||
template <typename Piece>
|
||||
inline bool is_on_same_convex_ring(Piece const& piece1, Piece const& piece2) const
|
||||
{
|
||||
if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
|
||||
}
|
||||
|
||||
template <typename Range, typename Iterator>
|
||||
inline void move_to_next_point(Range const& range, Iterator& next) const
|
||||
{
|
||||
++next;
|
||||
if (next == boost::end(range))
|
||||
{
|
||||
next = boost::begin(range) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename Iterator>
|
||||
inline Iterator next_point(Range const& range, Iterator it) const
|
||||
{
|
||||
Iterator result = it;
|
||||
move_to_next_point(range, result);
|
||||
// TODO: we could use either piece-boundaries, or comparison with
|
||||
// robust points, to check if the point equals the last one
|
||||
while(geometry::equals(*it, *result))
|
||||
{
|
||||
move_to_next_point(range, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
|
||||
signed_size_type& index, int dir, Box const& other_bounding_box)
|
||||
{
|
||||
for(; it_begin != it_beyond
|
||||
&& it_begin + 1 != it_beyond
|
||||
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
|
||||
other_bounding_box, m_robust_policy);
|
||||
++it_begin, index++)
|
||||
{}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
|
||||
int dir, Box const& other_bounding_box)
|
||||
{
|
||||
while (it_beyond != it_begin
|
||||
&& it_beyond - 1 != it_begin
|
||||
&& it_beyond - 2 != it_begin)
|
||||
{
|
||||
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
|
||||
other_bounding_box, m_robust_policy))
|
||||
{
|
||||
--it_beyond;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Piece, typename Section>
|
||||
inline void calculate_turns(Piece const& piece1, Piece const& piece2,
|
||||
Section const& section1, Section const& section2)
|
||||
{
|
||||
typedef typename boost::range_value<Rings const>::type ring_type;
|
||||
typedef typename boost::range_value<Turns const>::type turn_type;
|
||||
typedef typename boost::range_iterator<ring_type const>::type iterator;
|
||||
|
||||
signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;
|
||||
signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;
|
||||
if (piece1_first_index < 0 || piece2_first_index < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get indices of part of offsetted_rings for this monotonic section:
|
||||
signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index;
|
||||
signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index;
|
||||
|
||||
// index of last point in section, beyond-end is one further
|
||||
signed_size_type const sec1_last_index = piece1_first_index + section1.end_index;
|
||||
signed_size_type const sec2_last_index = piece2_first_index + section2.end_index;
|
||||
|
||||
// get geometry and iterators over these sections
|
||||
ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
|
||||
iterator it1_first = boost::begin(ring1) + sec1_first_index;
|
||||
iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
|
||||
|
||||
ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];
|
||||
iterator it2_first = boost::begin(ring2) + sec2_first_index;
|
||||
iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
|
||||
|
||||
// Set begin/end of monotonic ranges, in both x/y directions
|
||||
signed_size_type index1 = sec1_first_index;
|
||||
move_begin_iterator<0>(it1_first, it1_beyond, index1,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
move_end_iterator<0>(it1_first, it1_beyond,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
move_begin_iterator<1>(it1_first, it1_beyond, index1,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
move_end_iterator<1>(it1_first, it1_beyond,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
|
||||
signed_size_type index2 = sec2_first_index;
|
||||
move_begin_iterator<0>(it2_first, it2_beyond, index2,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
move_end_iterator<0>(it2_first, it2_beyond,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
move_begin_iterator<1>(it2_first, it2_beyond, index2,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
move_end_iterator<1>(it2_first, it2_beyond,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
|
||||
turn_type the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
the_model.operations[0].seg_id = piece1.first_seg_id;
|
||||
the_model.operations[0].seg_id.segment_index = index1; // override
|
||||
|
||||
iterator it1 = it1_first;
|
||||
for (iterator prev1 = it1++;
|
||||
it1 != it1_beyond;
|
||||
prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
|
||||
{
|
||||
the_model.operations[1].piece_index = piece2.index;
|
||||
the_model.operations[1].seg_id = piece2.first_seg_id;
|
||||
the_model.operations[1].seg_id.segment_index = index2; // override
|
||||
|
||||
iterator next1 = next_point(ring1, it1);
|
||||
|
||||
iterator it2 = it2_first;
|
||||
for (iterator prev2 = it2++;
|
||||
it2 != it2_beyond;
|
||||
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
|
||||
{
|
||||
iterator next2 = next_point(ring2, it2);
|
||||
|
||||
// TODO: internally get_turn_info calculates robust points.
|
||||
// But they are already calculated.
|
||||
// We should be able to use them.
|
||||
// this means passing them to this visitor,
|
||||
// and iterating in sync with them...
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
buffer_assign_turn
|
||||
#else
|
||||
detail::overlay::assign_null_policy
|
||||
#endif
|
||||
> turn_policy;
|
||||
|
||||
turn_policy::apply(*prev1, *it1, *next1,
|
||||
*prev2, *it2, *next2,
|
||||
false, false, false, false,
|
||||
the_model,
|
||||
m_intersection_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
piece_turn_visitor(Pieces const& pieces,
|
||||
Rings const& ring_collection,
|
||||
Turns& turns,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_pieces(pieces)
|
||||
, m_rings(ring_collection)
|
||||
, m_turns(turns)
|
||||
, m_intersection_strategy(intersection_strategy)
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
template <typename Section>
|
||||
inline void apply(Section const& section1, Section const& section2,
|
||||
bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
|
||||
typedef typename boost::range_value<Pieces const>::type piece_type;
|
||||
piece_type const& piece1 = m_pieces[section1.ring_id.source_index];
|
||||
piece_type const& piece2 = m_pieces[section2.ring_id.source_index];
|
||||
|
||||
if ( piece1.index == piece2.index
|
||||
|| is_adjacent(piece1, piece2)
|
||||
|| is_on_same_convex_ring(piece1, piece2)
|
||||
|| detail::disjoint::disjoint_box_box(section1.bounding_box,
|
||||
section2.bounding_box) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
calculate_turns(piece1, piece2, section1, section2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
+88
@@ -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
|
||||
+33
@@ -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
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
|
||||
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
struct original_get_box
|
||||
{
|
||||
template <typename Box, typename Original>
|
||||
static inline void apply(Box& total, Original const& original)
|
||||
{
|
||||
geometry::expand(total, original.m_box);
|
||||
}
|
||||
};
|
||||
|
||||
struct original_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Original>
|
||||
static inline bool apply(Box const& box, Original const& original)
|
||||
{
|
||||
return ! detail::disjoint::disjoint_box_box(box, original.m_box);
|
||||
}
|
||||
};
|
||||
|
||||
struct include_turn_policy
|
||||
{
|
||||
template <typename Turn>
|
||||
static inline bool apply(Turn const& turn)
|
||||
{
|
||||
return turn.location == location_ok;
|
||||
}
|
||||
};
|
||||
|
||||
struct turn_in_original_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
{
|
||||
if (turn.location != location_ok || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(
|
||||
turn.robust_point, box);
|
||||
}
|
||||
};
|
||||
|
||||
//! Check if specified is in range of specified iterators
|
||||
//! Return value of strategy (true if we can bail out)
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
typename State,
|
||||
typename Point,
|
||||
typename Iterator
|
||||
>
|
||||
inline bool point_in_range(Strategy& strategy, State& state,
|
||||
Point const& point, Iterator begin, Iterator end)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
|
||||
Iterator it = begin;
|
||||
for (Iterator previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
if (! strategy.apply(point, *previous, *it, state))
|
||||
{
|
||||
// We're probably on the boundary
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
typename State,
|
||||
typename Point,
|
||||
typename CoordinateType,
|
||||
typename Iterator
|
||||
>
|
||||
inline bool point_in_section(Strategy& strategy, State& state,
|
||||
Point const& point, CoordinateType const& point_x,
|
||||
Iterator begin, Iterator end,
|
||||
int direction)
|
||||
{
|
||||
if (direction == 0)
|
||||
{
|
||||
// Not a monotonic section, or no change in X-direction
|
||||
return point_in_range(strategy, state, point, begin, end);
|
||||
}
|
||||
|
||||
// We're in a monotonic section in x-direction
|
||||
Iterator it = begin;
|
||||
|
||||
for (Iterator previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
// Depending on sections.direction we can quit for this section
|
||||
CoordinateType const previous_x = geometry::get<0>(*previous);
|
||||
|
||||
if (direction == 1 && point_x < previous_x)
|
||||
{
|
||||
// Section goes upwards, x increases, point is is below section
|
||||
return true;
|
||||
}
|
||||
else if (direction == -1 && point_x > previous_x)
|
||||
{
|
||||
// Section goes downwards, x decreases, point is above section
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! strategy.apply(point, *previous, *it, state))
|
||||
{
|
||||
// We're probably on the boundary
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Point, typename Original>
|
||||
inline int point_in_original(Point const& point, Original const& original)
|
||||
{
|
||||
// The winding strategy is scanning in x direction
|
||||
// therefore it's critical to pass direction calculated
|
||||
// for x dimension below.
|
||||
typedef strategy::within::winding<Point> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
|
||||
if (boost::size(original.m_sections) == 0
|
||||
|| boost::size(original.m_ring) - boost::size(original.m_sections) < 16)
|
||||
{
|
||||
// There are no sections, or it does not profit to walk over sections
|
||||
// instead of over points. Boundary of 16 is arbitrary but can influence
|
||||
// performance
|
||||
point_in_range(strategy, state, point,
|
||||
original.m_ring.begin(), original.m_ring.end());
|
||||
return strategy.result(state);
|
||||
}
|
||||
|
||||
typedef typename Original::sections_type sections_type;
|
||||
typedef typename boost::range_iterator<sections_type const>::type iterator_type;
|
||||
typedef typename boost::range_value<sections_type const>::type section_type;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const point_x = geometry::get<0>(point);
|
||||
|
||||
// Walk through all monotonic sections of this original
|
||||
for (iterator_type it = boost::begin(original.m_sections);
|
||||
it != boost::end(original.m_sections);
|
||||
++it)
|
||||
{
|
||||
section_type const& section = *it;
|
||||
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box)
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box))
|
||||
{
|
||||
// x-coordinate of point overlaps with section
|
||||
if (! point_in_section(strategy, state, point, point_x,
|
||||
boost::begin(original.m_ring) + section.begin_index,
|
||||
boost::begin(original.m_ring) + section.end_index + 1,
|
||||
section.directions[0]))
|
||||
{
|
||||
// We're probably on the boundary
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strategy.result(state);
|
||||
}
|
||||
|
||||
|
||||
template <typename Turns>
|
||||
class turn_in_original_visitor
|
||||
{
|
||||
public:
|
||||
turn_in_original_visitor(Turns& turns)
|
||||
: m_mutable_turns(turns)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Original>
|
||||
inline void apply(Turn const& turn, Original const& original, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
|
||||
if (turn.location != location_ok || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return;
|
||||
}
|
||||
|
||||
if (geometry::disjoint(turn.robust_point, original.m_box))
|
||||
{
|
||||
// Skip all disjoint
|
||||
return;
|
||||
}
|
||||
|
||||
int const code = point_in_original(turn.robust_point, original);
|
||||
|
||||
if (code == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Turn& mutable_turn = m_mutable_turns[turn.turn_index];
|
||||
|
||||
if (code == 0)
|
||||
{
|
||||
// On border of original: always discard
|
||||
mutable_turn.location = location_discard;
|
||||
}
|
||||
|
||||
// Point is inside an original ring
|
||||
if (original.m_is_interior)
|
||||
{
|
||||
mutable_turn.count_in_original--;
|
||||
}
|
||||
else if (original.m_has_interiors)
|
||||
{
|
||||
mutable_turn.count_in_original++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is an exterior ring and there are no interior rings.
|
||||
// Then we are completely ready with this turn
|
||||
mutable_turn.within_original = true;
|
||||
mutable_turn.count_in_original = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private :
|
||||
Turns& m_mutable_turns;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
|
||||
+803
@@ -0,0 +1,803 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
|
||||
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/dot_product.hpp>
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/comparable_distance.hpp>
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
struct piece_get_box
|
||||
{
|
||||
template <typename Box, typename Piece>
|
||||
static inline void apply(Box& total, Piece const& piece)
|
||||
{
|
||||
geometry::expand(total, piece.robust_envelope);
|
||||
}
|
||||
};
|
||||
|
||||
struct piece_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Piece>
|
||||
static inline bool apply(Box const& box, Piece const& piece)
|
||||
{
|
||||
if (piece.type == strategy::buffer::buffered_flat_end
|
||||
|| piece.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// Turns cannot be inside a flat end (though they can be on border)
|
||||
// Neither we need to check if they are inside concave helper pieces
|
||||
|
||||
// Skip all pieces not used as soon as possible
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
|
||||
}
|
||||
};
|
||||
|
||||
struct turn_get_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline void apply(Box& total, Turn const& turn)
|
||||
{
|
||||
geometry::expand(total, turn.robust_point);
|
||||
}
|
||||
};
|
||||
|
||||
struct turn_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
{
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum analyse_result
|
||||
{
|
||||
analyse_unknown,
|
||||
analyse_continue,
|
||||
analyse_disjoint,
|
||||
analyse_within,
|
||||
analyse_on_original_boundary,
|
||||
analyse_on_offsetted
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
, analyse_near_offsetted
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
inline bool in_box(Point const& previous,
|
||||
Point const& current, Point const& point)
|
||||
{
|
||||
// Get its box (TODO: this can be prepared-on-demand later)
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, previous);
|
||||
geometry::expand(box, current);
|
||||
|
||||
return geometry::covered_by(point, box);
|
||||
}
|
||||
|
||||
template <typename Point, typename Turn>
|
||||
inline analyse_result check_segment(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (side == -1 && from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
if (side == 1 && from_monotonic)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
return analyse_continue;
|
||||
|
||||
#else
|
||||
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const twice_area
|
||||
= side_strategy::template side_value
|
||||
<
|
||||
coordinate_type,
|
||||
coordinate_type
|
||||
>(previous, current, turn.robust_point);
|
||||
|
||||
if (twice_area == 0)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (twice_area < 0)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (twice_area * twice_area < geometry::comparable_distance(previous, current)
|
||||
&& in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
}
|
||||
else if (twice_area > 0 && from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
class analyse_turn_wrt_point_piece
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Piece::section_type section_type;
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<point_type const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
#else
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
boost::ignore_unused(strategy);
|
||||
#endif
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
coordinate_type const point_x = geometry::get<0>(turn.robust_point);
|
||||
|
||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||
{
|
||||
section_type const& section = piece.sections[s];
|
||||
// If point within horizontal range of monotonic section:
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)
|
||||
{
|
||||
for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
|
||||
// First check if it is in range - if it is not, the
|
||||
// expensive side_of_intersection does not need to be
|
||||
// applied
|
||||
coordinate_type x1 = geometry::get<0>(previous);
|
||||
coordinate_type x2 = geometry::get<0>(current);
|
||||
|
||||
if (x1 > x2)
|
||||
{
|
||||
std::swap(x1, x2);
|
||||
}
|
||||
|
||||
if (point_x >= x1 - 1 && point_x <= x2 + 1)
|
||||
{
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
// Sections are monotonic in x-dimension
|
||||
if (side == 1)
|
||||
{
|
||||
// Left on segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
else if (side == 0)
|
||||
{
|
||||
// Collinear - TODO: check if really on segment
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
#else
|
||||
analyse_result code = check_segment(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
// Get the state (to determine it is within), we don't have
|
||||
// to cover the on-segment case (covered above)
|
||||
strategy.apply(turn.robust_point, previous, current, state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// It is nowhere outside, and not on segment, so it is within
|
||||
return analyse_within;
|
||||
#else
|
||||
int const code = strategy.result(state);
|
||||
if (code == 1)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
else if (code == -1)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Should normally not occur - on-segment is covered
|
||||
return analyse_unknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class analyse_turn_wrt_piece
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result check_helper_segment(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(s1, s2);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 1)
|
||||
{
|
||||
// left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
else if (side == 0)
|
||||
{
|
||||
// If is collinear, either on segment or before/after
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, s1);
|
||||
geometry::expand(box, s2);
|
||||
|
||||
if (geometry::covered_by(turn.robust_point, box))
|
||||
{
|
||||
// Points on helper-segments are considered as within
|
||||
// Points on original boundary are processed differently
|
||||
return is_original
|
||||
? analyse_on_original_boundary
|
||||
: analyse_within;
|
||||
}
|
||||
|
||||
// It is collinear but not on the segment. Because these
|
||||
// segments are convex, it is outside
|
||||
// Unless the offsetted ring is collinear or concave w.r.t.
|
||||
// helper-segment but that scenario is not yet supported
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
#else
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
|
||||
switch(side_strategy::apply(s1, s2, turn.robust_point))
|
||||
{
|
||||
case 1 :
|
||||
return analyse_disjoint; // left of segment
|
||||
case 0 :
|
||||
{
|
||||
// If is collinear, either on segment or before/after
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, s1);
|
||||
geometry::expand(box, s2);
|
||||
|
||||
if (geometry::covered_by(turn.robust_point, box))
|
||||
{
|
||||
// It is on the segment
|
||||
if (! is_original
|
||||
&& geometry::comparable_distance(turn.robust_point, offsetted) <= 1)
|
||||
{
|
||||
// It is close to the offsetted-boundary, take
|
||||
// any rounding-issues into account
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
|
||||
// Points on helper-segments are considered as within
|
||||
// Points on original boundary are processed differently
|
||||
return is_original
|
||||
? analyse_on_original_boundary
|
||||
: analyse_within;
|
||||
}
|
||||
|
||||
// It is collinear but not on the segment. Because these
|
||||
// segments are convex, it is outside
|
||||
// Unless the offsetted ring is collinear or concave w.r.t.
|
||||
// helper-segment but that scenario is not yet supported
|
||||
return analyse_disjoint;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
geometry::equal_to<point_type> comparator;
|
||||
|
||||
point_type points[4];
|
||||
|
||||
signed_size_type helper_count = static_cast<signed_size_type>(piece.robust_ring.size())
|
||||
- piece.offsetted_count;
|
||||
if (helper_count == 4)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
points[i] = piece.robust_ring[piece.offsetted_count + i];
|
||||
}
|
||||
}
|
||||
else if (helper_count == 3)
|
||||
{
|
||||
// Triangular piece, assign points but assign second twice
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int index = i < 2 ? i : i - 1;
|
||||
points[i] = piece.robust_ring[piece.offsetted_count + index];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some pieces (e.g. around points) do not have helper segments.
|
||||
// Others should have 3 (join) or 4 (side)
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
// First check point-equality
|
||||
point_type const& point = turn.robust_point;
|
||||
if (comparator(point, points[0]) || comparator(point, points[3]))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (comparator(point, points[1]) || comparator(point, points[2]))
|
||||
{
|
||||
return analyse_on_original_boundary;
|
||||
}
|
||||
|
||||
// Right side of the piece
|
||||
analyse_result result
|
||||
= check_helper_segment(points[0], points[1], turn,
|
||||
false, points[0]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Left side of the piece
|
||||
result = check_helper_segment(points[2], points[3], turn,
|
||||
false, points[3]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (! comparator(points[1], points[2]))
|
||||
{
|
||||
// Side of the piece at side of original geometry
|
||||
result = check_helper_segment(points[1], points[2], turn,
|
||||
true, point);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// We are within the \/ or |_| shaped piece, where the top is the
|
||||
// offsetted ring.
|
||||
if (! geometry::covered_by(point, piece.robust_offsetted_envelope))
|
||||
{
|
||||
// Not in offsetted-area. This makes a cheap check possible
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
switch(side_strategy::apply(points[3], points[0], point))
|
||||
{
|
||||
case 1 : return analyse_disjoint;
|
||||
case -1 : return analyse_within;
|
||||
case 0 : return analyse_disjoint;
|
||||
}
|
||||
}
|
||||
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
template <typename Turn, typename Piece, typename Compare>
|
||||
static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare)
|
||||
{
|
||||
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||
typedef typename ring_type::const_iterator it_type;
|
||||
it_type end = piece.robust_ring.begin() + piece.offsetted_count;
|
||||
it_type it = std::lower_bound(piece.robust_ring.begin(),
|
||||
end,
|
||||
turn.robust_point,
|
||||
compare);
|
||||
|
||||
if (it != end
|
||||
&& it != piece.robust_ring.begin())
|
||||
{
|
||||
// iterator points to point larger than point
|
||||
// w.r.t. specified direction, and prev points to a point smaller
|
||||
// We now know if it is inside/outside
|
||||
it_type prev = it - 1;
|
||||
return check_segment(*prev, *it, turn, true);
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
analyse_result code = check_helper_segments(turn, piece);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
geometry::equal_to<point_type> comparator;
|
||||
|
||||
if (piece.offsetted_count > 8)
|
||||
{
|
||||
// If the offset contains some points and is monotonic, we try
|
||||
// to avoid walking all points linearly.
|
||||
// We try it only once.
|
||||
if (piece.is_monotonic_increasing[0])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::less<point_type, 0>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
else if (piece.is_monotonic_increasing[1])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::less<point_type, 1>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
else if (piece.is_monotonic_decreasing[0])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::greater<point_type, 0>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
else if (piece.is_monotonic_decreasing[1])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::greater<point_type, 1>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
}
|
||||
|
||||
// It is small or not monotonic, walk linearly through offset
|
||||
// TODO: this will be combined with winding strategy
|
||||
|
||||
for (signed_size_type i = 1; i < piece.offsetted_count; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
// The robust ring can contain duplicates
|
||||
// (on which any side or side-value would return 0)
|
||||
if (! comparator(previous, current))
|
||||
{
|
||||
code = check_segment(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return analyse_unknown;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename Turns, typename Pieces>
|
||||
class turn_in_piece_visitor
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
Pieces const& m_pieces; // to check for piece-type
|
||||
|
||||
template <typename Operation, typename Piece>
|
||||
inline bool skip(Operation const& op, Piece const& piece) const
|
||||
{
|
||||
if (op.piece_index == piece.index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Piece const& pc = m_pieces[op.piece_index];
|
||||
if (pc.left_index == piece.index || pc.right_index == piece.index)
|
||||
{
|
||||
if (pc.type == strategy::buffer::buffered_flat_end)
|
||||
{
|
||||
// If it is a flat end, don't compare against its neighbor:
|
||||
// it will always be located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
if (pc.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// If it is concave, the same applies: the IP will be
|
||||
// located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// NOTE: this function returns a side value in {-1, 0, 1}
|
||||
template <typename Turn, typename Piece>
|
||||
static inline int turn_in_convex_piece(Turn const& turn,
|
||||
Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||
typedef geometry::model::referring_segment<point_type const> segment;
|
||||
|
||||
segment const p(turn.rob_pi, turn.rob_pj);
|
||||
segment const q(turn.rob_qi, turn.rob_qj);
|
||||
|
||||
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
|
||||
iterator_type it = boost::begin(piece.robust_ring);
|
||||
iterator_type end = boost::end(piece.robust_ring);
|
||||
|
||||
// A robust ring is always closed, and always clockwise
|
||||
for (iterator_type previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
geometry::equal_to<point_type> comparator;
|
||||
if (comparator(*previous, *it))
|
||||
{
|
||||
// Points are the same
|
||||
continue;
|
||||
}
|
||||
|
||||
segment r(*previous, *it);
|
||||
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 1)
|
||||
{
|
||||
// IP is left of segment, so it is outside
|
||||
return -1; // outside
|
||||
}
|
||||
else if (side == 0)
|
||||
{
|
||||
// IP is collinear with segment. TODO: we should analyze this further
|
||||
// For now we use the fallback point
|
||||
if (in_box(*previous, *it, turn.robust_point))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; // outside
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1; // inside
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces)
|
||||
: m_turns(turns)
|
||||
, m_pieces(pieces)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
inline void apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
|
||||
if (turn.count_within > 0)
|
||||
{
|
||||
// Already inside - no need to check again
|
||||
return;
|
||||
}
|
||||
|
||||
if (piece.type == strategy::buffer::buffered_flat_end
|
||||
|| piece.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// Turns cannot be located within flat-end or concave pieces
|
||||
return;
|
||||
}
|
||||
|
||||
if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))
|
||||
{
|
||||
// Easy check: if the turn is not in the envelope, we can safely return
|
||||
return;
|
||||
}
|
||||
|
||||
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: mutable_piece to make some on-demand preparations in analyse
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
|
||||
if (piece.type == geometry::strategy::buffer::buffered_point)
|
||||
{
|
||||
// Optimization for buffer around points: if distance from center
|
||||
// is not between min/max radius, the result is clear
|
||||
typedef typename default_comparable_distance_result
|
||||
<
|
||||
typename Turn::robust_point_type
|
||||
>::type distance_type;
|
||||
|
||||
distance_type const cd
|
||||
= geometry::comparable_distance(piece.robust_center,
|
||||
turn.robust_point);
|
||||
|
||||
if (cd < piece.robust_min_comparable_radius)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
return;
|
||||
}
|
||||
if (cd > piece.robust_max_comparable_radius)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
analyse_result analyse_code =
|
||||
piece.type == geometry::strategy::buffer::buffered_point
|
||||
? analyse_turn_wrt_point_piece::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece::apply(turn, piece);
|
||||
|
||||
switch(analyse_code)
|
||||
{
|
||||
case analyse_disjoint :
|
||||
return;
|
||||
case analyse_on_offsetted :
|
||||
mutable_turn.count_on_offsetted++; // value is not used anymore
|
||||
return;
|
||||
case analyse_on_original_boundary :
|
||||
mutable_turn.count_on_original_boundary++;
|
||||
return;
|
||||
case analyse_within :
|
||||
mutable_turn.count_within++;
|
||||
return;
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
case analyse_near_offsetted :
|
||||
mutable_turn.count_within_near_offsetted++;
|
||||
return;
|
||||
#endif
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// We don't know (yet)
|
||||
int geometry_code = 0;
|
||||
if (piece.is_convex)
|
||||
{
|
||||
geometry_code = turn_in_convex_piece(turn, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// TODO: this point_in_geometry is a performance-bottleneck here and
|
||||
// will be replaced completely by extending analyse_piece functionality
|
||||
geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
}
|
||||
#else
|
||||
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
#endif
|
||||
|
||||
if (geometry_code == 1)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
|
||||
+38
@@ -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
|
||||
+62
@@ -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
|
||||
+119
@@ -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
|
||||
+71
@@ -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
|
||||
+145
@@ -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
|
||||
+250
@@ -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
|
||||
+196
@@ -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
|
||||
+24
@@ -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
|
||||
+363
@@ -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
|
||||
+80
@@ -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
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
|
||||
|
||||
// Note: extracted from "convert.hpp" to avoid circular references convert/append
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace conversion
|
||||
{
|
||||
|
||||
|
||||
template <typename Source, typename Destination, std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct point_to_point
|
||||
{
|
||||
static inline void apply(Source const& source, Destination& destination)
|
||||
{
|
||||
typedef typename coordinate_type<Destination>::type coordinate_type;
|
||||
|
||||
set<Dimension>(destination, boost::numeric_cast<coordinate_type>(get<Dimension>(source)));
|
||||
point_to_point<Source, Destination, Dimension + 1, DimensionCount>::apply(source, destination);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source, typename Destination, std::size_t DimensionCount>
|
||||
struct point_to_point<Source, Destination, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Source const& , Destination& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Source, typename Destination>
|
||||
inline void convert_point_to_point(Source const& source, Destination& destination)
|
||||
{
|
||||
point_to_point<Source, Destination, 0, dimension<Destination>::value>::apply(source, destination);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::conversion
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
|
||||
@@ -0,0 +1,107 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace counting
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t D>
|
||||
struct other_count
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline std::size_t apply(Geometry const&)
|
||||
{
|
||||
return D;
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
static inline std::size_t apply(Geometry const&, bool)
|
||||
{
|
||||
return D;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename RangeCount>
|
||||
struct polygon_count
|
||||
{
|
||||
template <typename Polygon>
|
||||
static inline std::size_t apply(Polygon const& poly)
|
||||
{
|
||||
std::size_t n = RangeCount::apply(exterior_ring(poly));
|
||||
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(poly);
|
||||
for (typename detail::interior_iterator<Polygon const>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
n += RangeCount::apply(*it);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename SingleCount>
|
||||
struct multi_count
|
||||
{
|
||||
template <typename MultiGeometry>
|
||||
static inline std::size_t apply(MultiGeometry const& geometry)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for (typename boost::range_iterator<MultiGeometry const>::type
|
||||
it = boost::begin(geometry);
|
||||
it != boost::end(geometry);
|
||||
++it)
|
||||
{
|
||||
n += SingleCount::apply(*it);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::counting
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP
|
||||
@@ -0,0 +1,40 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/azimuth.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Calculate course (bearing) between two points.
|
||||
///
|
||||
/// NOTE: left for convenience and temporary backward compatibility
|
||||
template <typename ReturnType, typename Point1, typename Point2>
|
||||
inline ReturnType course(Point1 const& p1, Point2 const& p2)
|
||||
{
|
||||
return azimuth<ReturnType>(p1, p2);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <std::size_t Index, typename Point1, typename Point2>
|
||||
inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return
|
||||
math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))
|
||||
?
|
||||
0
|
||||
:
|
||||
(geometry::get<Index>(point1) > geometry::get<Index>(point2) ? 1 : -1);
|
||||
}
|
||||
|
||||
|
||||
// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
|
||||
// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
|
||||
// Returns 1 if p goes forward, so extends (a,b)
|
||||
// Returns 0 if p is equal with b, or if (a,b) is degenerate
|
||||
// Note that it does not do any collinearity test, that should be done before
|
||||
template <typename Point1, typename Point2>
|
||||
inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
|
||||
const Point2& p)
|
||||
{
|
||||
// Suppose segment = (4 3,4 4) and p =(4 2)
|
||||
// Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1
|
||||
|
||||
int const sign_a0 = sign_of_difference<0>(segment_b, segment_a);
|
||||
int const sign_a1 = sign_of_difference<1>(segment_b, segment_a);
|
||||
|
||||
if (sign_a0 == 0 && sign_a1 == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int const sign_p0 = sign_of_difference<0>(segment_b, p);
|
||||
int const sign_p1 = sign_of_difference<1>(segment_b, p);
|
||||
|
||||
if (sign_p0 == 0 && sign_p1 == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct check_each_ring_for_within_call_covered_by
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename Point, typename Strategy>
|
||||
static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy)
|
||||
{
|
||||
return geometry::covered_by(p, g, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct check_each_ring_for_within_call_covered_by<Geometry, box_tag>
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline bool apply(Point const& p, Geometry const& g, Strategy const& )
|
||||
{
|
||||
return geometry::covered_by(p, g);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template<typename Geometry, typename Strategy>
|
||||
struct check_each_ring_for_within
|
||||
{
|
||||
bool not_disjoint;
|
||||
Geometry const& m_geometry;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
inline check_each_ring_for_within(Geometry const& g,
|
||||
Strategy const& strategy)
|
||||
: not_disjoint(false)
|
||||
, m_geometry(g)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Range>
|
||||
inline void apply(Range const& range)
|
||||
{
|
||||
typename point_type<Range>::type pt;
|
||||
not_disjoint = not_disjoint
|
||||
|| ( geometry::point_on_border(pt, range)
|
||||
&& check_each_ring_for_within_call_covered_by
|
||||
<
|
||||
Geometry
|
||||
>::apply(pt, m_geometry, m_strategy) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
|
||||
inline bool rings_containing(FirstGeometry const& geometry1,
|
||||
SecondGeometry const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
check_each_ring_for_within
|
||||
<
|
||||
FirstGeometry, Strategy
|
||||
> checker(geometry1, strategy);
|
||||
geometry::detail::for_each_range(geometry2, checker);
|
||||
return checker.not_disjoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct general_areal
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no intersection of segments, they might located
|
||||
// inside each other
|
||||
|
||||
// We check that using a point on the border (external boundary),
|
||||
// and see if that is contained in the other geometry. And vice versa.
|
||||
|
||||
if ( rings_containing(geometry1, geometry2,
|
||||
strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>())
|
||||
|| rings_containing(geometry2, geometry1,
|
||||
strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Areal1, typename Areal2>
|
||||
struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false>
|
||||
: detail::disjoint::general_areal<Areal1, Areal2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Box>
|
||||
struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>
|
||||
: detail::disjoint::general_areal<Areal, Box>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2,
|
||||
std::size_t Dimension = 0,
|
||||
std::size_t DimensionCount = dimension<Box1>::value,
|
||||
typename CSTag = typename tag_cast
|
||||
<
|
||||
typename cs_tag<Box1>::type,
|
||||
spherical_tag
|
||||
>::type
|
||||
>
|
||||
struct box_box
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
{
|
||||
return apply(box1, box2);
|
||||
}
|
||||
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return box_box
|
||||
<
|
||||
Box1, Box2,
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount, typename CSTag>
|
||||
struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>
|
||||
{
|
||||
static inline bool apply(Box1 const& , Box2 const& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount>
|
||||
struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
{
|
||||
return apply(box1, box2);
|
||||
}
|
||||
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
typename coordinate_type<Box1>::type,
|
||||
typename coordinate_type<Box2>::type
|
||||
>::type calc_t;
|
||||
typedef typename coordinate_system<Box1>::type::units units_t;
|
||||
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
|
||||
|
||||
calc_t const b1_min = get<min_corner, 0>(box1);
|
||||
calc_t const b1_max = get<max_corner, 0>(box1);
|
||||
calc_t const b2_min = get<min_corner, 0>(box2);
|
||||
calc_t const b2_max = get<max_corner, 0>(box2);
|
||||
|
||||
// min <= max <=> diff >= 0
|
||||
calc_t const diff1 = b1_max - b1_min;
|
||||
calc_t const diff2 = b2_max - b2_min;
|
||||
|
||||
// check the intersection if neither box cover the whole globe
|
||||
if (diff1 < constants::period() && diff2 < constants::period())
|
||||
{
|
||||
// calculate positive longitude translation with b1_min as origin
|
||||
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
|
||||
calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
|
||||
|
||||
if (b2_min_transl > b1_max // b2_min right of b1_max
|
||||
&& b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return box_box
|
||||
<
|
||||
Box1, Box2,
|
||||
1, DimensionCount
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect if boxes are disjoint
|
||||
\note Is used from other algorithms, declared separately
|
||||
to avoid circular references
|
||||
*/
|
||||
template <typename Box1, typename Box2>
|
||||
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
return box_box<Box1, Box2>::apply(box1, box2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount>
|
||||
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
|
||||
: detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2014.
|
||||
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/areal_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
|
||||
+246
@@ -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
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
|
||||
struct disjoint_no_intersections_policy
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Geometry1>::type point1_type;
|
||||
point1_type p;
|
||||
geometry::point_on_border(p, g1);
|
||||
|
||||
return !geometry::covered_by(p, g2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1>
|
||||
struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
// TODO: use partition or rtree on g2
|
||||
typedef typename boost::range_iterator<Geometry1 const>::type iterator;
|
||||
for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
|
||||
{
|
||||
typedef typename boost::range_value<Geometry1 const>::type value_type;
|
||||
if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
|
||||
::apply(*it, g2, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Geometry1, typename Geometry2,
|
||||
typename NoIntersectionsPolicy
|
||||
= disjoint_no_intersections_policy<Geometry1, Geometry2> >
|
||||
struct disjoint_linear_areal
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
// if there are intersections - return false
|
||||
if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return NoIntersectionsPolicy
|
||||
::apply(g1, g2,
|
||||
strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Areal,
|
||||
typename Tag = typename tag<Areal>::type
|
||||
>
|
||||
struct disjoint_segment_areal
|
||||
: not_implemented<Segment, Areal>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment, typename Polygon>
|
||||
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
|
||||
{
|
||||
private:
|
||||
template <typename InteriorRings, typename Strategy>
|
||||
static inline
|
||||
bool check_interior_rings(InteriorRings const& interior_rings,
|
||||
Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<InteriorRings>::type ring_type;
|
||||
|
||||
typedef unary_disjoint_geometry_to_query_geometry
|
||||
<
|
||||
Segment,
|
||||
Strategy,
|
||||
disjoint_range_segment_or_box
|
||||
<
|
||||
ring_type, closure<ring_type>::value, Segment
|
||||
>
|
||||
> unary_predicate_type;
|
||||
|
||||
return check_iterator_range
|
||||
<
|
||||
unary_predicate_type
|
||||
>::apply(boost::begin(interior_rings),
|
||||
boost::end(interior_rings),
|
||||
unary_predicate_type(segment, strategy));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
template <typename IntersectionStrategy>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Polygon const& polygon,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring;
|
||||
|
||||
if ( !disjoint_range_segment_or_box
|
||||
<
|
||||
ring, closure<Polygon>::value, Segment
|
||||
>::apply(geometry::exterior_ring(polygon), segment, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !check_interior_rings(geometry::interior_rings(polygon), segment, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typename point_type<Segment>::type p;
|
||||
detail::assign_point_from_index<0>(segment, p);
|
||||
|
||||
return !geometry::covered_by(p, polygon,
|
||||
strategy.template get_point_in_geometry_strategy<Segment, Polygon>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Segment, typename MultiPolygon>
|
||||
struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
|
||||
{
|
||||
template <typename IntersectionStrategy>
|
||||
static inline bool apply(Segment const& segment, MultiPolygon const& multipolygon,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
return multirange_constant_size_geometry
|
||||
<
|
||||
MultiPolygon, Segment
|
||||
>::apply(multipolygon, segment, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Segment, typename Ring>
|
||||
struct disjoint_segment_areal<Segment, Ring, ring_tag>
|
||||
{
|
||||
template <typename IntersectionStrategy>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Ring const& ring,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
if ( !disjoint_range_segment_or_box
|
||||
<
|
||||
Ring, closure<Ring>::value, Segment
|
||||
>::apply(ring, segment, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typename point_type<Segment>::type p;
|
||||
detail::assign_point_from_index<0>(segment, p);
|
||||
|
||||
return !geometry::covered_by(p, ring,
|
||||
strategy.template get_point_in_geometry_strategy<Segment, Ring>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Areal>
|
||||
struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>
|
||||
: public detail::disjoint::disjoint_linear_areal<Linear, Areal>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Linear>
|
||||
struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Areal const& areal, Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::disjoint::disjoint_linear_areal
|
||||
<
|
||||
Linear, Areal
|
||||
>::apply(linear, areal, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Areal, typename Segment>
|
||||
struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Areal const& g1, Segment const& g2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::disjoint::disjoint_segment_areal
|
||||
<
|
||||
Segment, Areal
|
||||
>::apply(g2, g1, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Segment, typename Areal>
|
||||
struct disjoint<Segment, Areal, 2, segment_tag, areal_tag, false>
|
||||
: detail::disjoint::disjoint_segment_areal<Segment, Areal>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
||||
|
||||
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename Segment1, typename Segment2>
|
||||
struct disjoint_segment
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Segment1>::type point_type;
|
||||
|
||||
// We don't need to rescale to detect disjointness
|
||||
typedef no_rescale_policy rescale_policy_type;
|
||||
rescale_policy_type robust_policy;
|
||||
|
||||
typedef segment_intersection_points
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type
|
||||
<
|
||||
point_type,
|
||||
rescale_policy_type
|
||||
>::type
|
||||
> intersection_return_type;
|
||||
|
||||
typedef policies::relate::segments_intersection_points
|
||||
<
|
||||
intersection_return_type
|
||||
> intersection_policy;
|
||||
|
||||
intersection_return_type is = strategy.apply(segment1, segment2,
|
||||
intersection_policy(),
|
||||
robust_policy);
|
||||
|
||||
return is.count == 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct assign_disjoint_policy
|
||||
{
|
||||
// We want to include all points:
|
||||
static bool const include_no_turn = true;
|
||||
static bool const include_degenerate = true;
|
||||
static bool const include_opposite = true;
|
||||
|
||||
// We don't assign extra info:
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Info& , Point1 const& , Point2 const&,
|
||||
IntersectionInfo const&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct disjoint_linear
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry1>::type point_type;
|
||||
typedef detail::no_rescale_policy rescale_policy_type;
|
||||
typedef typename geometry::segment_ratio_type
|
||||
<
|
||||
point_type, rescale_policy_type
|
||||
>::type segment_ratio_type;
|
||||
typedef overlay::turn_info
|
||||
<
|
||||
point_type,
|
||||
segment_ratio_type,
|
||||
typename detail::get_turns::turn_operation_type
|
||||
<
|
||||
Geometry1, Geometry2, segment_ratio_type
|
||||
>::type
|
||||
> turn_info_type;
|
||||
|
||||
std::deque<turn_info_type> turns;
|
||||
|
||||
// Specify two policies:
|
||||
// 1) Stop at any intersection
|
||||
// 2) In assignment, include also degenerate points (which are normally skipped)
|
||||
disjoint_interrupt_policy interrupt_policy;
|
||||
dispatch::get_turns
|
||||
<
|
||||
typename geometry::tag<Geometry1>::type,
|
||||
typename geometry::tag<Geometry2>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, // should be false
|
||||
overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, // should be false
|
||||
detail::get_turns::get_turn_info_type
|
||||
<
|
||||
Geometry1, Geometry2, assign_disjoint_policy
|
||||
>
|
||||
>::apply(0, geometry1, 1, geometry2,
|
||||
strategy, rescale_policy_type(), turns, interrupt_policy);
|
||||
|
||||
return !interrupt_policy.has_intersections;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear1, typename Linear2>
|
||||
struct disjoint<Linear1, Linear2, 2, linear_tag, linear_tag, false>
|
||||
: detail::disjoint::disjoint_linear<Linear1, Linear2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment1, typename Segment2>
|
||||
struct disjoint<Segment1, Segment2, 2, segment_tag, segment_tag, false>
|
||||
: detail::disjoint::disjoint_segment<Segment1, Segment2>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
|
||||
+171
@@ -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
|
||||
+332
@@ -0,0 +1,332 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2>
|
||||
class multipoint_multipoint
|
||||
{
|
||||
private:
|
||||
template <typename Iterator>
|
||||
class unary_disjoint_predicate
|
||||
: detail::relate::less
|
||||
{
|
||||
private:
|
||||
typedef detail::relate::less base_type;
|
||||
|
||||
public:
|
||||
unary_disjoint_predicate(Iterator first, Iterator last)
|
||||
: base_type(), m_first(first), m_last(last)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
inline bool apply(Point const& point) const
|
||||
{
|
||||
return !std::binary_search(m_first,
|
||||
m_last,
|
||||
point,
|
||||
static_cast<base_type const&>(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator m_first, m_last;
|
||||
};
|
||||
|
||||
public:
|
||||
static inline bool apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
|
||||
|
||||
typedef typename boost::range_value<MultiPoint1>::type point1_type;
|
||||
|
||||
std::vector<point1_type> points1(boost::begin(multipoint1),
|
||||
boost::end(multipoint1));
|
||||
|
||||
std::sort(points1.begin(), points1.end(), detail::relate::less());
|
||||
|
||||
typedef unary_disjoint_predicate
|
||||
<
|
||||
typename std::vector<point1_type>::const_iterator
|
||||
> predicate_type;
|
||||
|
||||
return check_iterator_range
|
||||
<
|
||||
predicate_type
|
||||
>::apply(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
predicate_type(points1.begin(), points1.end()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear>
|
||||
class multipoint_linear
|
||||
{
|
||||
private:
|
||||
struct expand_box_point
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline void apply(Box& total, Point const& point)
|
||||
{
|
||||
geometry::expand(total, point);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: After adding non-cartesian Segment envelope to the library
|
||||
// this policy should be modified to take envelope strategy.
|
||||
struct expand_box_segment
|
||||
{
|
||||
template <typename Box, typename Segment>
|
||||
static inline void apply(Box& total, Segment const& segment)
|
||||
{
|
||||
geometry::expand(total, geometry::return_envelope<Box>(segment));
|
||||
}
|
||||
};
|
||||
|
||||
struct overlaps_box_point
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline bool apply(Box const& box, Point const& point)
|
||||
{
|
||||
// The default strategy is enough in this case
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Point, Box
|
||||
>::type strategy_type;
|
||||
return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: After implementing disjoint Segment/Box for non-cartesian geometries
|
||||
// this strategy should be passed here.
|
||||
// TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy
|
||||
// which by default is winding containing CS-specific side strategy
|
||||
// TODO: disjoint Segment/Box will be called in this case which may take
|
||||
// quite long in non-cartesian CS. So we should consider passing range of bounding boxes
|
||||
// of segments after calculating them once.
|
||||
struct overlaps_box_segment
|
||||
{
|
||||
template <typename Box, typename Segment>
|
||||
static inline bool apply(Box const& box, Segment const& segment)
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Segment, Box
|
||||
>::type strategy_type;
|
||||
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PtSegStrategy>
|
||||
class item_visitor_type
|
||||
{
|
||||
public:
|
||||
item_visitor_type(PtSegStrategy const& strategy)
|
||||
: m_intersection_found(false)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Item1, typename Item2>
|
||||
inline void apply(Item1 const& item1, Item2 const& item2)
|
||||
{
|
||||
if (! m_intersection_found
|
||||
&& ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
|
||||
{
|
||||
m_intersection_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool intersection_found() const { return m_intersection_found; }
|
||||
|
||||
private:
|
||||
bool m_intersection_found;
|
||||
PtSegStrategy const& m_strategy;
|
||||
};
|
||||
// structs for partition -- end
|
||||
|
||||
class segment_range
|
||||
{
|
||||
public:
|
||||
typedef geometry::segment_iterator<Linear const> const_iterator;
|
||||
typedef const_iterator iterator;
|
||||
|
||||
segment_range(Linear const& linear)
|
||||
: m_linear(linear)
|
||||
{}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return geometry::segments_begin(m_linear);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return geometry::segments_end(m_linear);
|
||||
}
|
||||
|
||||
private:
|
||||
Linear const& m_linear;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy)
|
||||
{
|
||||
item_visitor_type<Strategy> visitor(strategy);
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
geometry::model::box<typename point_type<MultiPoint>::type>
|
||||
>::apply(multipoint, segment_range(linear), visitor,
|
||||
expand_box_point(), overlaps_box_point(),
|
||||
expand_box_segment(), overlaps_box_segment());
|
||||
|
||||
return ! visitor.intersection_found();
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy)
|
||||
{
|
||||
return apply(multipoint, linear, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename MultiPoint, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false
|
||||
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Point>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Segment, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false
|
||||
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Segment>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false
|
||||
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Box>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiPoint1,
|
||||
typename MultiPoint2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint1, MultiPoint2, DimensionCount,
|
||||
multi_point_tag, multi_point_tag, false
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const& )
|
||||
{
|
||||
if ( boost::size(multipoint2) < boost::size(multipoint1) )
|
||||
{
|
||||
return detail::disjoint::multipoint_multipoint
|
||||
<
|
||||
MultiPoint2, MultiPoint1
|
||||
>::apply(multipoint2, multipoint1);
|
||||
}
|
||||
|
||||
return detail::disjoint::multipoint_multipoint
|
||||
<
|
||||
MultiPoint1, MultiPoint2
|
||||
>::apply(multipoint1, multipoint2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Linear, typename MultiPoint, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false
|
||||
> : detail::disjoint::multipoint_linear<MultiPoint, Linear>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false
|
||||
> : detail::disjoint::multipoint_linear<MultiPoint, Linear>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
|
||||
+94
@@ -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
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect if point/box are disjoint
|
||||
*/
|
||||
template <typename Point, typename Box>
|
||||
inline bool disjoint_point_box(Point const& point, Box const& box)
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Point, Box
|
||||
>::type strategy_type;
|
||||
|
||||
// ! covered_by(point, box)
|
||||
return ! strategy_type::apply(point, box);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box, Strategy const& )
|
||||
{
|
||||
// ! covered_by(point, box)
|
||||
return ! Strategy::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
|
||||
+89
@@ -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
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/strategy_transform.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/transform.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct point_point_generic
|
||||
{
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& )
|
||||
{
|
||||
return apply(p1, p2);
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const& p1, Point2 const& p2)
|
||||
{
|
||||
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return
|
||||
point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct point_point_generic<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const&, Point2 const& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class point_point_on_spheroid
|
||||
{
|
||||
private:
|
||||
template <typename Point1, typename Point2, bool SameUnits>
|
||||
struct are_same_points
|
||||
{
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
typedef typename helper_geometry<Point1>::type helper_point_type1;
|
||||
typedef typename helper_geometry<Point2>::type helper_point_type2;
|
||||
|
||||
helper_point_type1 point1_normalized
|
||||
= return_normalized<helper_point_type1>(point1);
|
||||
helper_point_type2 point2_normalized
|
||||
= return_normalized<helper_point_type2>(point2);
|
||||
|
||||
return point_point_generic
|
||||
<
|
||||
0, dimension<Point1>::value
|
||||
>::apply(point1_normalized, point2_normalized);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct are_same_points<Point1, Point2, false> // points have different units
|
||||
{
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
typename fp_coordinate_type<Point1>::type,
|
||||
typename fp_coordinate_type<Point2>::type
|
||||
>::type calculation_type;
|
||||
|
||||
typename helper_geometry
|
||||
<
|
||||
Point1, calculation_type, radian
|
||||
>::type helper_point1, helper_point2;
|
||||
|
||||
Point1 point1_normalized = return_normalized<Point1>(point1);
|
||||
Point2 point2_normalized = return_normalized<Point2>(point2);
|
||||
|
||||
geometry::transform(point1_normalized, helper_point1);
|
||||
geometry::transform(point2_normalized, helper_point2);
|
||||
|
||||
return point_point_generic
|
||||
<
|
||||
0, dimension<Point1>::value
|
||||
>::apply(helper_point1, helper_point2);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
|
||||
{
|
||||
return apply(point1, point2);
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return are_same_points
|
||||
<
|
||||
Point1,
|
||||
Point2,
|
||||
boost::is_same
|
||||
<
|
||||
typename coordinate_system<Point1>::type::units,
|
||||
typename coordinate_system<Point2>::type::units
|
||||
>::value
|
||||
>::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount,
|
||||
typename CSTag1 = typename cs_tag<Point1>::type,
|
||||
typename CSTag2 = CSTag1
|
||||
>
|
||||
struct point_point
|
||||
: point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_point
|
||||
<
|
||||
Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag
|
||||
> : point_point_on_spheroid
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_point
|
||||
<
|
||||
Point1, Point2, Dimension, DimensionCount, geographic_tag
|
||||
> : point_point_on_spheroid
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
|
||||
: point_point_generic<Dimension, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect of points are disjoint
|
||||
\note To avoid circular references
|
||||
*/
|
||||
template <typename Point1, typename Point2>
|
||||
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return point_point
|
||||
<
|
||||
Point1, Point2,
|
||||
0, dimension<Point1>::type::value
|
||||
>::apply(point1, point2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point1, typename Point2, std::size_t DimensionCount>
|
||||
struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
|
||||
: detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
struct disjoint_segment_box
|
||||
{
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
return strategy.apply(segment, box);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
|
||||
: detail::disjoint::disjoint_segment_box
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
|
||||
+333
@@ -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
|
||||
+60
@@ -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
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/reverse_dispatch.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Helper metafunction for default strategy retrieval
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2 = Geometry1,
|
||||
typename Tag1 = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry1>::type, pointlike_tag
|
||||
>::type,
|
||||
typename Tag2 = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry2>::type, pointlike_tag
|
||||
>::type,
|
||||
bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
|
||||
>
|
||||
struct default_strategy
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, segment_tag,
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1,
|
||||
typename Tag2
|
||||
>
|
||||
struct default_strategy<Geometry1, Geometry2, Tag1, Tag2, true>
|
||||
: default_strategy<Geometry2, Geometry1, Tag2, Tag1, false>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Pointlike1, typename Pointlike2>
|
||||
struct default_strategy
|
||||
<
|
||||
Pointlike1, Pointlike2,
|
||||
pointlike_tag, pointlike_tag, false
|
||||
> : strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, point_tag,
|
||||
typename point_type<Pointlike1>::type,
|
||||
typename point_type<Pointlike2>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Pointlike, typename Box>
|
||||
struct default_strategy<Pointlike, Box, pointlike_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, box_tag,
|
||||
typename point_type<Pointlike>::type,
|
||||
typename point_type<Box>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct default_strategy<Box1, Box2, box_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
box_tag, box_tag,
|
||||
typename point_type<Box1>::type,
|
||||
typename point_type<Box2>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
// Helper metafunction for default point-segment strategy retrieval
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
struct default_ps_strategy
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, segment_tag,
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type,
|
||||
typename cs_tag<typename point_type<Geometry1>::type>::type,
|
||||
typename cs_tag<typename point_type<Geometry2>::type>::type,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP
|
||||
+464
@@ -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
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP
|
||||
|
||||
// the implementation details
|
||||
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/box_to_box.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/backward_compatibility.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP
|
||||
+403
@@ -0,0 +1,403 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
#include <boost/mpl/always.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/default_distance_result.hpp>
|
||||
#include <boost/geometry/strategies/distance_result.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// If reversal is needed, perform it
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2, typename Strategy,
|
||||
typename Tag1, typename Tag2, typename StrategyTag
|
||||
>
|
||||
struct distance
|
||||
<
|
||||
Geometry1, Geometry2, Strategy,
|
||||
Tag1, Tag2, StrategyTag,
|
||||
true
|
||||
>
|
||||
: distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Geometry2>::type,
|
||||
typename point_type<Geometry1>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(
|
||||
Geometry1 const& g1,
|
||||
Geometry2 const& g2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return distance
|
||||
<
|
||||
Geometry2, Geometry1, Strategy,
|
||||
Tag2, Tag1, StrategyTag,
|
||||
false
|
||||
>::apply(g2, g1, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
struct distance
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline
|
||||
typename distance_result<Geometry1, Geometry2, default_strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename detail::distance::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, strategy_type
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct distance
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return
|
||||
resolve_strategy::distance::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor
|
||||
<
|
||||
typename distance_result
|
||||
<
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
|
||||
Geometry2,
|
||||
Strategy
|
||||
>::type
|
||||
>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
: m_geometry2(geometry2),
|
||||
m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
Strategy
|
||||
>(geometry1, m_geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline typename distance_result
|
||||
<
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
|
||||
Geometry2,
|
||||
Strategy
|
||||
>::type
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor
|
||||
<
|
||||
typename distance_result
|
||||
<
|
||||
Geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
|
||||
Strategy
|
||||
>::type
|
||||
>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1,
|
||||
Strategy const& strategy)
|
||||
: m_geometry1(geometry1),
|
||||
m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
Strategy
|
||||
>(m_geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline typename distance_result
|
||||
<
|
||||
Geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
|
||||
Strategy
|
||||
>::type
|
||||
apply(
|
||||
Geometry1 const& geometry1,
|
||||
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T1),
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T2)
|
||||
>
|
||||
struct distance
|
||||
<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor
|
||||
<
|
||||
typename distance_result
|
||||
<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
|
||||
Strategy
|
||||
>::type
|
||||
>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
|
||||
{
|
||||
return distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::template apply
|
||||
<
|
||||
Strategy
|
||||
>(geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline typename distance_result
|
||||
<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
|
||||
Strategy
|
||||
>::type
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{distance} \brief_strategy
|
||||
\ingroup distance
|
||||
\details
|
||||
\details \details_calc{area}. \brief_strategy. \details_strategy_reasons
|
||||
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Distance}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{distance}
|
||||
\return \return_calc{distance}
|
||||
\note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
|
||||
it may also be a point-segment strategy.
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
|
||||
\* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
|
||||
\* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
|
||||
\* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
|
||||
\* more (currently extensions): Vincenty\, Andoyer (geographic)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Note, in case of a Compilation Error:
|
||||
if you get:
|
||||
- "Failed to specialize function template ..."
|
||||
- "error: no matching function for call to ..."
|
||||
for distance, it is probably so that there is no specialization
|
||||
for return_type<...> for your strategy.
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
detail::throw_on_empty_input(geometry1);
|
||||
detail::throw_on_empty_input(geometry2);
|
||||
|
||||
return resolve_variant::distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{distance}
|
||||
\ingroup distance
|
||||
\details The default strategy is used, corresponding to the coordinate system of the geometries
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_calc{distance}
|
||||
|
||||
\qbk{[include reference/algorithms/distance.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline typename default_distance_result<Geometry1, Geometry2>::type
|
||||
distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return geometry::distance(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
|
||||
+45
@@ -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
|
||||
+70
@@ -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
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Areal, typename Strategy>
|
||||
struct linear_to_areal
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Areal>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
Areal const& areal,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( geometry::intersects(linear, areal) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return linear_to_linear
|
||||
<
|
||||
Linear, Areal, Strategy
|
||||
>::apply(linear, areal, strategy, false);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type apply(Areal const& areal,
|
||||
Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(linear, areal, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Strategy>
|
||||
struct areal_to_areal
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Areal1>::type,
|
||||
typename point_type<Areal2>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Areal1 const& areal1,
|
||||
Areal2 const& areal2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( geometry::intersects(areal1, areal2) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return linear_to_linear
|
||||
<
|
||||
Areal1, Areal2, Strategy
|
||||
>::apply(areal1, areal2, strategy, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Linear, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Areal, Strategy,
|
||||
linear_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::linear_to_areal
|
||||
<
|
||||
Linear, Areal, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Linear, Strategy,
|
||||
areal_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::linear_to_areal
|
||||
<
|
||||
Linear, Areal, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal1, Areal2, Strategy,
|
||||
areal_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::areal_to_areal
|
||||
<
|
||||
Areal1, Areal2, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP
|
||||
+123
@@ -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
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
struct multipoint_to_multipoint
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<MultiPoint1>::type,
|
||||
typename point_type<MultiPoint2>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (boost::size(multipoint2) < boost::size(multipoint1))
|
||||
|
||||
{
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint2 const>::type,
|
||||
MultiPoint1,
|
||||
Strategy
|
||||
>::apply(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
multipoint1,
|
||||
strategy);
|
||||
}
|
||||
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint1 const>::type,
|
||||
MultiPoint2,
|
||||
Strategy
|
||||
>::apply(boost::begin(multipoint1),
|
||||
boost::end(multipoint1),
|
||||
multipoint2,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, typename Strategy>
|
||||
struct multipoint_to_linear
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<MultiPoint>::type,
|
||||
typename point_type<Linear>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint const& multipoint,
|
||||
Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::distance::point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint const>::type,
|
||||
Linear,
|
||||
Strategy
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
linear,
|
||||
strategy);
|
||||
}
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
MultiPoint const& multipoint,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(multipoint, linear, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Strategy>
|
||||
class multipoint_to_areal
|
||||
{
|
||||
private:
|
||||
struct not_covered_by_areal
|
||||
{
|
||||
not_covered_by_areal(Areal const& areal)
|
||||
: m_areal(areal)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
inline bool apply(Point const& point) const
|
||||
{
|
||||
return !geometry::covered_by(point, m_areal);
|
||||
}
|
||||
|
||||
Areal const& m_areal;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<MultiPoint>::type,
|
||||
typename point_type<Areal>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint const& multipoint,
|
||||
Areal const& areal,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
not_covered_by_areal predicate(areal);
|
||||
|
||||
if (check_iterator_range
|
||||
<
|
||||
not_covered_by_areal, false
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
predicate))
|
||||
{
|
||||
return detail::distance::point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint const>::type,
|
||||
Areal,
|
||||
Strategy
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
areal,
|
||||
strategy);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline return_type apply(Areal const& areal,
|
||||
MultiPoint const& multipoint,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(multipoint, areal, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint1, MultiPoint2, Strategy,
|
||||
multi_point_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_point, false
|
||||
> : detail::distance::multipoint_to_multipoint
|
||||
<
|
||||
MultiPoint1, MultiPoint2, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint, Linear, Strategy, multi_point_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Linear, typename MultiPoint, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, MultiPoint, Strategy, linear_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint, Areal, Strategy, multi_point_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename MultiPoint, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, MultiPoint, Strategy, areal_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
+518
@@ -0,0 +1,518 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename P1, typename P2, typename Strategy>
|
||||
struct point_to_point
|
||||
{
|
||||
static inline
|
||||
typename strategy::distance::services::return_type<Strategy, P1, P2>::type
|
||||
apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Range,
|
||||
closure_selector Closure,
|
||||
typename Strategy
|
||||
>
|
||||
class point_to_range
|
||||
{
|
||||
private:
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type comparable_strategy;
|
||||
|
||||
typedef detail::closest_feature::point_to_point_range
|
||||
<
|
||||
Point, Range, Closure, comparable_strategy
|
||||
> point_to_point_range;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename boost::range_value<Range>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Point const& point, Range const& range,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return_type const zero = return_type(0);
|
||||
|
||||
if (boost::size(range) == 0)
|
||||
{
|
||||
return zero;
|
||||
}
|
||||
|
||||
namespace sds = strategy::distance::services;
|
||||
|
||||
typename sds::return_type
|
||||
<
|
||||
comparable_strategy,
|
||||
Point,
|
||||
typename point_type<Range>::type
|
||||
>::type cd_min;
|
||||
|
||||
std::pair
|
||||
<
|
||||
typename boost::range_iterator<Range const>::type,
|
||||
typename boost::range_iterator<Range const>::type
|
||||
> it_pair
|
||||
= point_to_point_range::apply(point,
|
||||
boost::begin(range),
|
||||
boost::end(range),
|
||||
sds::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy),
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<Strategy>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
strategy.apply(point, *it_pair.first, *it_pair.second);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Ring,
|
||||
closure_selector Closure,
|
||||
typename Strategy
|
||||
>
|
||||
struct point_to_ring
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, Point, typename point_type<Ring>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
Ring const& ring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (geometry::within(point, ring))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return point_to_range
|
||||
<
|
||||
Point, Ring, closure<Ring>::value, Strategy
|
||||
>::apply(point, ring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Polygon,
|
||||
closure_selector Closure,
|
||||
typename Strategy
|
||||
>
|
||||
class point_to_polygon
|
||||
{
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, Point, typename point_type<Polygon>::type
|
||||
>::type return_type;
|
||||
|
||||
private:
|
||||
typedef point_to_range
|
||||
<
|
||||
Point, typename ring_type<Polygon>::type, Closure, Strategy
|
||||
> per_ring;
|
||||
|
||||
struct distance_to_interior_rings
|
||||
{
|
||||
template <typename InteriorRingIterator>
|
||||
static inline return_type apply(Point const& point,
|
||||
InteriorRingIterator first,
|
||||
InteriorRingIterator last,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
for (InteriorRingIterator it = first; it != last; ++it)
|
||||
{
|
||||
if (geometry::within(point, *it))
|
||||
{
|
||||
// the point is inside a polygon hole, so its distance
|
||||
// to the polygon its distance to the polygon's
|
||||
// hole boundary
|
||||
return per_ring::apply(point, *it, strategy);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename InteriorRings>
|
||||
static inline return_type apply(Point const& point,
|
||||
InteriorRings const& interior_rings,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(point,
|
||||
boost::begin(interior_rings),
|
||||
boost::end(interior_rings),
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
static inline return_type apply(Point const& point,
|
||||
Polygon const& polygon,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (!geometry::covered_by(point, exterior_ring(polygon)))
|
||||
{
|
||||
// the point is outside the exterior ring, so its distance
|
||||
// to the polygon is its distance to the polygon's exterior ring
|
||||
return per_ring::apply(point, exterior_ring(polygon), strategy);
|
||||
}
|
||||
|
||||
// Check interior rings
|
||||
return distance_to_interior_rings::apply(point,
|
||||
interior_rings(polygon),
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename MultiGeometry,
|
||||
typename Strategy,
|
||||
bool CheckCoveredBy = boost::is_same
|
||||
<
|
||||
typename tag<MultiGeometry>::type, multi_polygon_tag
|
||||
>::value
|
||||
>
|
||||
class point_to_multigeometry
|
||||
{
|
||||
private:
|
||||
typedef detail::closest_feature::geometry_to_range geometry_to_range;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename point_type<MultiGeometry>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
MultiGeometry const& multigeometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef iterator_selector<MultiGeometry const> selector_type;
|
||||
|
||||
namespace sds = strategy::distance::services;
|
||||
|
||||
typename sds::return_type
|
||||
<
|
||||
typename sds::comparable_type<Strategy>::type,
|
||||
Point,
|
||||
typename point_type<MultiGeometry>::type
|
||||
>::type cd;
|
||||
|
||||
typename selector_type::iterator_type it_min
|
||||
= geometry_to_range::apply(point,
|
||||
selector_type::begin(multigeometry),
|
||||
selector_type::end(multigeometry),
|
||||
sds::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy),
|
||||
cd);
|
||||
|
||||
return
|
||||
is_comparable<Strategy>::value
|
||||
?
|
||||
cd
|
||||
:
|
||||
dispatch::distance
|
||||
<
|
||||
Point,
|
||||
typename std::iterator_traits
|
||||
<
|
||||
typename selector_type::iterator_type
|
||||
>::value_type,
|
||||
Strategy
|
||||
>::apply(point, *it_min, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// this is called only for multipolygons, hence the change in the
|
||||
// template parameter name MultiGeometry to MultiPolygon
|
||||
template <typename Point, typename MultiPolygon, typename Strategy>
|
||||
struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename point_type<MultiPolygon>::type
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
MultiPolygon const& multipolygon,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (geometry::covered_by(point, multipolygon))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return point_to_multigeometry
|
||||
<
|
||||
Point, MultiPolygon, Strategy, false
|
||||
>::apply(point, multipolygon, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// Point-point
|
||||
template <typename P1, typename P2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
P1, P2, Strategy, point_tag, point_tag,
|
||||
strategy_tag_distance_point_point, false
|
||||
> : detail::distance::point_to_point<P1, P2, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
// Point-line version 2, where point-segment strategy is specified
|
||||
template <typename Point, typename Linestring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Linestring, Strategy, point_tag, linestring_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
// Point-ring , where point-segment strategy is specified
|
||||
template <typename Point, typename Ring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Ring, Strategy, point_tag, ring_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_ring
|
||||
<
|
||||
Point, Ring, closure<Ring>::value, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
// Point-polygon , where point-segment strategy is specified
|
||||
template <typename Point, typename Polygon, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Polygon, Strategy, point_tag, polygon_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_polygon
|
||||
<
|
||||
Point, Polygon, closure<Polygon>::value, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
// Point-segment version 2, with point-segment strategy
|
||||
template <typename Point, typename Segment, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Segment, Strategy, point_tag, segment_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
{
|
||||
static inline typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, Point, typename point_type<Segment>::type
|
||||
>::type apply(Point const& point,
|
||||
Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename point_type<Segment>::type p[2];
|
||||
geometry::detail::assign_point_from_index<0>(segment, p[0]);
|
||||
geometry::detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(point, p[0], p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Box, Strategy, point_tag, box_tag,
|
||||
strategy_tag_distance_point_box, false
|
||||
>
|
||||
{
|
||||
static inline typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, Point, typename point_type<Box>::type
|
||||
>::type
|
||||
apply(Point const& point, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Point, typename MultiPoint, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, MultiPoint, Strategy, point_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_point, false
|
||||
> : detail::distance::point_to_multigeometry
|
||||
<
|
||||
Point, MultiPoint, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename MultiLinestring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_multigeometry
|
||||
<
|
||||
Point, MultiLinestring, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename MultiPolygon, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_multigeometry
|
||||
<
|
||||
Point, MultiPolygon, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Linear, Strategy, point_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : distance
|
||||
<
|
||||
Point, Linear, Strategy,
|
||||
point_tag, typename tag<Linear>::type,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Areal, Strategy, point_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : distance
|
||||
<
|
||||
Point, Areal, Strategy,
|
||||
point_tag, typename tag<Areal>::type,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
+130
@@ -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
|
||||
+892
@@ -0,0 +1,892 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/calculation_type.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename Strategy,
|
||||
bool UsePointBoxStrategy = false
|
||||
>
|
||||
class segment_to_box_2D_generic
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type comparable_strategy;
|
||||
|
||||
typedef detail::closest_feature::point_to_point_range
|
||||
<
|
||||
segment_point,
|
||||
std::vector<box_point>,
|
||||
open,
|
||||
comparable_strategy
|
||||
> point_to_point_range;
|
||||
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
comparable_strategy, segment_point, box_point
|
||||
>::type comparable_return_type;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, segment_point, box_point
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && geometry::intersects(segment, box))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
comparable_strategy cstrategy =
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy);
|
||||
|
||||
// get segment points
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
// get box points
|
||||
std::vector<box_point> box_points(4);
|
||||
detail::assign_box_corners_oriented<true>(box, box_points);
|
||||
|
||||
comparable_return_type cd[6];
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
|
||||
}
|
||||
|
||||
std::pair
|
||||
<
|
||||
typename std::vector<box_point>::const_iterator,
|
||||
typename std::vector<box_point>::const_iterator
|
||||
> bit_min[2];
|
||||
|
||||
bit_min[0] = point_to_point_range::apply(p[0],
|
||||
box_points.begin(),
|
||||
box_points.end(),
|
||||
cstrategy,
|
||||
cd[4]);
|
||||
bit_min[1] = point_to_point_range::apply(p[1],
|
||||
box_points.begin(),
|
||||
box_points.end(),
|
||||
cstrategy,
|
||||
cd[5]);
|
||||
|
||||
unsigned int imin = 0;
|
||||
for (unsigned int i = 1; i < 6; ++i)
|
||||
{
|
||||
if (cd[i] < cd[imin])
|
||||
{
|
||||
imin = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
return strategy.apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int bimin = imin - 4;
|
||||
return strategy.apply(p[bimin],
|
||||
*bit_min[bimin].first,
|
||||
*bit_min[bimin].second);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename Strategy
|
||||
>
|
||||
class segment_to_box_2D_generic<Segment, Box, Strategy, true>
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type comparable_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
comparable_strategy, segment_point, box_point
|
||||
>::type comparable_return_type;
|
||||
|
||||
typedef typename detail::distance::default_strategy
|
||||
<
|
||||
segment_point, Box
|
||||
>::type point_box_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
point_box_strategy
|
||||
>::type point_box_comparable_strategy;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, segment_point, box_point
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && geometry::intersects(segment, box))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
comparable_strategy cstrategy =
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy);
|
||||
boost::ignore_unused(cstrategy);
|
||||
|
||||
// get segment points
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
// get box points
|
||||
std::vector<box_point> box_points(4);
|
||||
detail::assign_box_corners_oriented<true>(box, box_points);
|
||||
|
||||
comparable_return_type cd[6];
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
|
||||
}
|
||||
|
||||
point_box_comparable_strategy pb_cstrategy;
|
||||
boost::ignore_unused(pb_cstrategy);
|
||||
cd[4] = pb_cstrategy.apply(p[0], box);
|
||||
cd[5] = pb_cstrategy.apply(p[1], box);
|
||||
|
||||
unsigned int imin = 0;
|
||||
for (unsigned int i = 1; i < 6; ++i)
|
||||
{
|
||||
if (cd[i] < cd[imin])
|
||||
{
|
||||
imin = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_comparable<Strategy>::value)
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
strategy.apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return point_box_strategy().apply(p[imin - 4], box);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename ReturnType,
|
||||
typename SegmentPoint,
|
||||
typename BoxPoint,
|
||||
typename PPStrategy,
|
||||
typename PSStrategy
|
||||
>
|
||||
class segment_to_box_2D
|
||||
{
|
||||
private:
|
||||
template <typename Result>
|
||||
struct cast_to_result
|
||||
{
|
||||
template <typename T>
|
||||
static inline Result apply(T const& t)
|
||||
{
|
||||
return boost::numeric_cast<Result>(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, bool IsLess /* true */>
|
||||
struct compare_less_equal
|
||||
{
|
||||
typedef compare_less_equal<T, !IsLess> other;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator()(T1 const& t1, T2 const& t2) const
|
||||
{
|
||||
return std::less_equal<T>()(cast_to_result<T>::apply(t1),
|
||||
cast_to_result<T>::apply(t2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct compare_less_equal<T, false>
|
||||
{
|
||||
typedef compare_less_equal<T, true> other;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator()(T1 const& t1, T2 const& t2) const
|
||||
{
|
||||
return std::greater_equal<T>()(cast_to_result<T>::apply(t1),
|
||||
cast_to_result<T>::apply(t2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename LessEqual>
|
||||
struct other_compare
|
||||
{
|
||||
typedef typename LessEqual::other type;
|
||||
};
|
||||
|
||||
|
||||
// it is assumed here that p0 lies to the right of the box (so the
|
||||
// entire segment lies to the right of the box)
|
||||
template <typename LessEqual>
|
||||
struct right_of_box
|
||||
{
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& bottom_right,
|
||||
BoxPoint const& top_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
{
|
||||
boost::ignore_unused(pp_strategy, ps_strategy);
|
||||
|
||||
// the implementation below is written for non-negative slope
|
||||
// segments
|
||||
//
|
||||
// for negative slope segments swap the roles of bottom_right
|
||||
// and top_right and use greater_equal instead of less_equal.
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
|
||||
LessEqual less_equal;
|
||||
|
||||
if (less_equal(geometry::get<1>(top_right), geometry::get<1>(p0)))
|
||||
{
|
||||
// closest box point is the top-right corner
|
||||
return cast::apply(pp_strategy.apply(p0, top_right));
|
||||
}
|
||||
else if (less_equal(geometry::get<1>(bottom_right),
|
||||
geometry::get<1>(p0)))
|
||||
{
|
||||
// distance is realized between p0 and right-most
|
||||
// segment of box
|
||||
ReturnType diff = cast::apply(geometry::get<0>(p0))
|
||||
- cast::apply(geometry::get<0>(bottom_right));
|
||||
return strategy::distance::services::result_from_distance
|
||||
<
|
||||
PSStrategy, BoxPoint, SegmentPoint
|
||||
>::apply(ps_strategy, math::abs(diff));
|
||||
}
|
||||
else
|
||||
{
|
||||
// distance is realized between the bottom-right
|
||||
// corner of the box and the segment
|
||||
return cast::apply(ps_strategy.apply(bottom_right, p0, p1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// it is assumed here that p0 lies above the box (so the
|
||||
// entire segment lies above the box)
|
||||
template <typename LessEqual>
|
||||
struct above_of_box
|
||||
{
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
PSStrategy const& ps_strategy)
|
||||
{
|
||||
boost::ignore_unused(ps_strategy);
|
||||
|
||||
// the segment lies above the box
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
|
||||
LessEqual less_equal;
|
||||
|
||||
// p0 is above the upper segment of the box
|
||||
// (and inside its band)
|
||||
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p0)))
|
||||
{
|
||||
ReturnType diff = cast::apply(geometry::get<1>(p0))
|
||||
- cast::apply(geometry::get<1>(top_left));
|
||||
return strategy::distance::services::result_from_distance
|
||||
<
|
||||
PSStrategy, SegmentPoint, BoxPoint
|
||||
>::apply(ps_strategy, math::abs(diff));
|
||||
}
|
||||
|
||||
// p0 is to the left of the box, but p1 is above the box
|
||||
// in this case the distance is realized between the
|
||||
// top-left corner of the box and the segment
|
||||
return cast::apply(ps_strategy.apply(top_left, p0, p1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename LessEqual>
|
||||
struct check_right_left_of_box
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy,
|
||||
ReturnType& result)
|
||||
{
|
||||
// p0 lies to the right of the box
|
||||
if (geometry::get<0>(p0) >= geometry::get<0>(top_right))
|
||||
{
|
||||
result = right_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, bottom_right, top_right,
|
||||
pp_strategy, ps_strategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
// p1 lies to the left of the box
|
||||
if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))
|
||||
{
|
||||
result = right_of_box
|
||||
<
|
||||
typename other_compare<LessEqual>::type
|
||||
>::apply(p1, p0, top_left, bottom_left,
|
||||
pp_strategy, ps_strategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename LessEqual>
|
||||
struct check_above_below_of_box
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PSStrategy const& ps_strategy,
|
||||
ReturnType& result)
|
||||
{
|
||||
// the segment lies below the box
|
||||
if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
|
||||
{
|
||||
result = above_of_box
|
||||
<
|
||||
typename other_compare<LessEqual>::type
|
||||
>::apply(p1, p0, bottom_right, ps_strategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
// the segment lies above the box
|
||||
if (geometry::get<1>(p0) > geometry::get<1>(top_right))
|
||||
{
|
||||
result = above_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, top_left, ps_strategy);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct check_generic_position
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& bottom_left0,
|
||||
BoxPoint const& top_right0,
|
||||
BoxPoint const& bottom_left1,
|
||||
BoxPoint const& top_right1,
|
||||
BoxPoint const& corner1,
|
||||
BoxPoint const& corner2,
|
||||
PSStrategy const& ps_strategy,
|
||||
ReturnType& result)
|
||||
{
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
|
||||
ReturnType diff0 = cast::apply(geometry::get<0>(p1))
|
||||
- cast::apply(geometry::get<0>(p0));
|
||||
ReturnType t_min0 = cast::apply(geometry::get<0>(bottom_left0))
|
||||
- cast::apply(geometry::get<0>(p0));
|
||||
ReturnType t_max0 = cast::apply(geometry::get<0>(top_right0))
|
||||
- cast::apply(geometry::get<0>(p0));
|
||||
|
||||
ReturnType diff1 = cast::apply(geometry::get<1>(p1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
ReturnType t_min1 = cast::apply(geometry::get<1>(bottom_left1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
ReturnType t_max1 = cast::apply(geometry::get<1>(top_right1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
|
||||
if (diff1 < 0)
|
||||
{
|
||||
diff1 = -diff1;
|
||||
t_min1 = -t_min1;
|
||||
t_max1 = -t_max1;
|
||||
}
|
||||
|
||||
// t_min0 > t_max1
|
||||
if (t_min0 * diff1 > t_max1 * diff0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
|
||||
return true;
|
||||
}
|
||||
|
||||
// t_max0 < t_min1
|
||||
if (t_max0 * diff1 < t_min1 * diff0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner2, p0, p1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static inline ReturnType
|
||||
non_negative_slope_segment(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, true> less_equal;
|
||||
|
||||
// assert that the segment has non-negative slope
|
||||
BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
|
||||
&& geometry::get<1>(p0) < geometry::get<1>(p1))
|
||||
||
|
||||
( geometry::get<0>(p0) < geometry::get<0>(p1)
|
||||
&& geometry::get<1>(p0) <= geometry::get<1>(p1) )
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1));
|
||||
|
||||
ReturnType result(0);
|
||||
|
||||
if (check_right_left_of_box
|
||||
<
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
pp_strategy, ps_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_above_below_of_box
|
||||
<
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
ps_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
bottom_left, top_right,
|
||||
bottom_left, top_right,
|
||||
top_left, bottom_right,
|
||||
ps_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// in all other cases the box and segment intersect, so return 0
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline ReturnType
|
||||
negative_slope_segment(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> greater_equal;
|
||||
|
||||
// assert that the segment has negative slope
|
||||
BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1)
|
||||
&& geometry::get<1>(p0) > geometry::get<1>(p1) )
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1) );
|
||||
|
||||
ReturnType result(0);
|
||||
|
||||
if (check_right_left_of_box
|
||||
<
|
||||
greater_equal
|
||||
>::apply(p0, p1,
|
||||
bottom_left, bottom_right, top_left, top_right,
|
||||
pp_strategy, ps_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_above_below_of_box
|
||||
<
|
||||
greater_equal
|
||||
>::apply(p1, p0,
|
||||
top_right, top_left, bottom_right, bottom_left,
|
||||
ps_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
bottom_left, top_right,
|
||||
top_right, bottom_left,
|
||||
bottom_left, top_right,
|
||||
ps_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// in all other cases the box and segment intersect, so return 0
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1)
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1) );
|
||||
|
||||
if (geometry::get<0>(p0) < geometry::get<0>(p1)
|
||||
&& geometry::get<1>(p0) > geometry::get<1>(p1))
|
||||
{
|
||||
return negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
pp_strategy, ps_strategy);
|
||||
}
|
||||
|
||||
return non_negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
pp_strategy, ps_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=========================================================================
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename std::size_t Dimension,
|
||||
typename PPStrategy,
|
||||
typename PSStrategy
|
||||
>
|
||||
class segment_to_box
|
||||
: not_implemented<Segment, Box>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename PPStrategy,
|
||||
typename PSStrategy
|
||||
>
|
||||
class segment_to_box<Segment, Box, 2, PPStrategy, PSStrategy>
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
PPStrategy
|
||||
>::type pp_comparable_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
PSStrategy
|
||||
>::type ps_comparable_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
ps_comparable_strategy, segment_point, box_point
|
||||
>::type comparable_return_type;
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
PSStrategy, segment_point, box_point
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
{
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
if (geometry::equals(p[0], p[1]))
|
||||
{
|
||||
typedef typename boost::mpl::if_
|
||||
<
|
||||
boost::is_same
|
||||
<
|
||||
ps_comparable_strategy,
|
||||
PSStrategy
|
||||
>,
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
segment_point, Box
|
||||
>::type
|
||||
>::type,
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
segment_point, Box
|
||||
>::type
|
||||
>::type point_box_strategy_type;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
segment_point,
|
||||
Box,
|
||||
point_box_strategy_type
|
||||
>::apply(p[0], box, point_box_strategy_type());
|
||||
}
|
||||
|
||||
box_point top_left, top_right, bottom_left, bottom_right;
|
||||
detail::assign_box_corners(box, bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
|
||||
if (geometry::less<segment_point>()(p[0], p[1]))
|
||||
{
|
||||
return segment_to_box_2D
|
||||
<
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
PPStrategy,
|
||||
PSStrategy
|
||||
>::apply(p[0], p[1],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
pp_strategy,
|
||||
ps_strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
return segment_to_box_2D
|
||||
<
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
PPStrategy,
|
||||
PSStrategy
|
||||
>::apply(p[1], p[0],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
pp_strategy,
|
||||
ps_strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Segment, Box, Strategy, segment_tag, box_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Segment>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type return_type;
|
||||
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
assert_dimension_equal<Segment, Box>();
|
||||
|
||||
typedef typename boost::mpl::if_
|
||||
<
|
||||
boost::is_same
|
||||
<
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type,
|
||||
Strategy
|
||||
>,
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
typename point_type<Segment>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type
|
||||
>::type,
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
typename point_type<Segment>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type
|
||||
>::type pp_strategy_type;
|
||||
|
||||
|
||||
return detail::distance::segment_to_box
|
||||
<
|
||||
Segment,
|
||||
Box,
|
||||
dimension<Segment>::value,
|
||||
pp_strategy_type,
|
||||
Strategy
|
||||
>::apply(segment, box, pp_strategy_type(), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
+152
@@ -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
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Index,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct envelope_indexed_box
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
|
||||
{
|
||||
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
|
||||
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
|
||||
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<BoxIn const, Index>,
|
||||
detail::indexed_point_view<BoxOut, Index>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(box_in_corner, mbr_corner);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Index,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct envelope_indexed_box_on_spheroid
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
|
||||
{
|
||||
// transform() does not work with boxes of dimension higher
|
||||
// than 2; to account for such boxes we transform the min/max
|
||||
// points of the boxes using the indexed_point_view
|
||||
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
|
||||
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
|
||||
|
||||
// first transform the units
|
||||
transform_units(box_in_corner, mbr_corner);
|
||||
|
||||
// now transform the remaining coordinates
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<BoxIn const, Index>,
|
||||
detail::indexed_point_view<BoxOut, Index>,
|
||||
2,
|
||||
DimensionCount
|
||||
>::apply(box_in_corner, mbr_corner);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct envelope_box
|
||||
{
|
||||
template<typename BoxIn, typename BoxOut, typename Strategy>
|
||||
static inline void apply(BoxIn const& box_in,
|
||||
BoxOut& mbr,
|
||||
Strategy const&)
|
||||
{
|
||||
envelope_indexed_box
|
||||
<
|
||||
min_corner, 0, dimension<BoxIn>::value
|
||||
>::apply(box_in, mbr);
|
||||
|
||||
envelope_indexed_box
|
||||
<
|
||||
max_corner, 0, dimension<BoxIn>::value
|
||||
>::apply(box_in, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct envelope_box_on_spheroid
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut, typename Strategy>
|
||||
static inline void apply(BoxIn const& box_in,
|
||||
BoxOut& mbr,
|
||||
Strategy const&)
|
||||
{
|
||||
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
|
||||
|
||||
envelope_indexed_box_on_spheroid
|
||||
<
|
||||
min_corner, dimension<BoxIn>::value
|
||||
>::apply(box_in_normalized, mbr);
|
||||
|
||||
envelope_indexed_box_on_spheroid
|
||||
<
|
||||
max_corner, dimension<BoxIn>::value
|
||||
>::apply(box_in_normalized, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box, typename CS_Tag>
|
||||
struct envelope<Box, box_tag, CS_Tag>
|
||||
: detail::envelope::envelope_box
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_box_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, geographic_tag>
|
||||
: detail::envelope::envelope_box_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct envelope_polygon
|
||||
{
|
||||
template <typename Polygon, typename Box, typename Strategy>
|
||||
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
typename ring_return_type<Polygon const>::type ext_ring
|
||||
= exterior_ring(polygon);
|
||||
|
||||
if (geometry::is_empty(ext_ring))
|
||||
{
|
||||
// if the exterior ring is empty, consider the interior rings
|
||||
envelope_multi_range
|
||||
<
|
||||
envelope_range
|
||||
>::apply(interior_rings(polygon), mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, consider only the exterior ring
|
||||
envelope_range::apply(ext_ring, mbr, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct envelope<Ring, ring_tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon>
|
||||
struct envelope<Polygon, polygon_tag>
|
||||
: detail::envelope::envelope_polygon
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct envelope<MultiPolygon, multi_polygon_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
+86
@@ -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
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017.
|
||||
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct envelope
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
dispatch::envelope<Geometry>::apply(geometry, box, strategy);
|
||||
}
|
||||
|
||||
template <typename Box>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef typename coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef typename strategy::envelope::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
coordinate_type
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct envelope
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
concepts::check<Box>();
|
||||
|
||||
resolve_strategy::envelope<Geometry>::apply(geometry, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Box& m_box;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Box& box, Strategy const& strategy)
|
||||
: m_box(box)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry) const
|
||||
{
|
||||
envelope<Geometry>::apply(geometry, m_box, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope (with strategy)}
|
||||
\ingroup envelope
|
||||
\details \details_calc{envelope,\det_envelope}.
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Box \tparam_box
|
||||
\tparam Strategy \tparam_strategy{Envelope}
|
||||
\param geometry \param_geometry
|
||||
\param mbr \param_box \param_set{envelope}
|
||||
\param strategy \param_strategy{envelope}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[envelope] [envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Box, typename Strategy>
|
||||
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{envelope,\det_envelope}.
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Box \tparam_box
|
||||
\param geometry \param_geometry
|
||||
\param mbr \param_box \param_set{envelope}
|
||||
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[envelope] [envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Box>
|
||||
inline void envelope(Geometry const& geometry, Box& mbr)
|
||||
{
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
|
||||
\tparam Box \tparam_box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Envelope}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{envelope}
|
||||
\return \return_calc{envelope}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[return_envelope] [return_envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Box, typename Geometry, typename Strategy>
|
||||
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
Box mbr;
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
return mbr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
|
||||
\tparam Box \tparam_box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_calc{envelope}
|
||||
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[return_envelope] [return_envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Box, typename Geometry>
|
||||
inline Box return_envelope(Geometry const& geometry)
|
||||
{
|
||||
Box mbr;
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
return mbr;
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
+78
@@ -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
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct envelope_linestring_on_spheroid
|
||||
{
|
||||
template <typename Linestring, typename Box, typename Strategy>
|
||||
static inline void apply(Linestring const& linestring,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
envelope_range::apply(geometry::segments_begin(linestring),
|
||||
geometry::segments_end(linestring),
|
||||
mbr,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linestring, typename CS_Tag>
|
||||
struct envelope<Linestring, linestring_tag, CS_Tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
template <typename Linestring>
|
||||
struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_linestring_on_spheroid
|
||||
{};
|
||||
|
||||
template <typename Linestring>
|
||||
struct envelope<Linestring, linestring_tag, geographic_tag>
|
||||
: detail::envelope::envelope_linestring_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLinestring, typename CS_Tag>
|
||||
struct envelope
|
||||
<
|
||||
MultiLinestring, multi_linestring_tag, CS_Tag
|
||||
> : detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_range
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct envelope
|
||||
<
|
||||
MultiLinestring, multi_linestring_tag, spherical_equatorial_tag
|
||||
> : detail::envelope::envelope_multi_range_on_spheroid
|
||||
<
|
||||
detail::envelope::envelope_linestring_on_spheroid
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct envelope
|
||||
<
|
||||
MultiLinestring, multi_linestring_tag, geographic_tag
|
||||
> : detail::envelope::envelope_multi_range_on_spheroid
|
||||
<
|
||||
detail::envelope::envelope_linestring_on_spheroid
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
+379
@@ -0,0 +1,379 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/algorithm/minmax_element.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
class envelope_multipoint_on_spheroid
|
||||
{
|
||||
private:
|
||||
template <std::size_t Dim>
|
||||
struct coordinate_less
|
||||
{
|
||||
template <typename Point>
|
||||
inline bool operator()(Point const& point1, Point const& point2) const
|
||||
{
|
||||
return math::smaller(geometry::get<Dim>(point1),
|
||||
geometry::get<Dim>(point2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Constants, typename MultiPoint, typename OutputIterator>
|
||||
static inline void analyze_point_coordinates(MultiPoint const& multipoint,
|
||||
bool& has_south_pole,
|
||||
bool& has_north_pole,
|
||||
OutputIterator oit)
|
||||
{
|
||||
typedef typename boost::range_value<MultiPoint>::type point_type;
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiPoint const
|
||||
>::type iterator_type;
|
||||
|
||||
// analyze point coordinates:
|
||||
// (1) normalize point coordinates
|
||||
// (2) check if any point is the north or the south pole
|
||||
// (3) put all non-pole points in a container
|
||||
//
|
||||
// notice that at this point in the algorithm, we have at
|
||||
// least two points on the spheroid
|
||||
has_south_pole = false;
|
||||
has_north_pole = false;
|
||||
|
||||
for (iterator_type it = boost::begin(multipoint);
|
||||
it != boost::end(multipoint);
|
||||
++it)
|
||||
{
|
||||
point_type point = detail::return_normalized<point_type>(*it);
|
||||
|
||||
if (math::equals(geometry::get<1>(point),
|
||||
Constants::min_latitude()))
|
||||
{
|
||||
has_south_pole = true;
|
||||
}
|
||||
else if (math::equals(geometry::get<1>(point),
|
||||
Constants::max_latitude()))
|
||||
{
|
||||
has_north_pole = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*oit++ = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SortedRange, typename Value>
|
||||
static inline Value maximum_gap(SortedRange const& sorted_range,
|
||||
Value& max_gap_left,
|
||||
Value& max_gap_right)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
SortedRange const
|
||||
>::type iterator_type;
|
||||
|
||||
iterator_type it1 = boost::begin(sorted_range), it2 = it1;
|
||||
++it2;
|
||||
max_gap_left = geometry::get<0>(*it1);
|
||||
max_gap_right = geometry::get<0>(*it2);
|
||||
|
||||
Value max_gap = max_gap_right - max_gap_left;
|
||||
for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)
|
||||
{
|
||||
Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);
|
||||
if (math::larger(gap, max_gap))
|
||||
{
|
||||
max_gap_left = geometry::get<0>(*it1);
|
||||
max_gap_right = geometry::get<0>(*it2);
|
||||
max_gap = gap;
|
||||
}
|
||||
}
|
||||
|
||||
return max_gap;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Constants,
|
||||
typename PointRange,
|
||||
typename LongitudeLess,
|
||||
typename CoordinateType
|
||||
>
|
||||
static inline void get_min_max_longitudes(PointRange& range,
|
||||
LongitudeLess const& lon_less,
|
||||
CoordinateType& lon_min,
|
||||
CoordinateType& lon_max)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
PointRange const
|
||||
>::type iterator_type;
|
||||
|
||||
// compute min and max longitude values
|
||||
std::pair<iterator_type, iterator_type> min_max_longitudes
|
||||
= boost::minmax_element(boost::begin(range),
|
||||
boost::end(range),
|
||||
lon_less);
|
||||
|
||||
lon_min = geometry::get<0>(*min_max_longitudes.first);
|
||||
lon_max = geometry::get<0>(*min_max_longitudes.second);
|
||||
|
||||
// if the longitude span is "large" compute the true maximum gap
|
||||
if (math::larger(lon_max - lon_min, Constants::half_period()))
|
||||
{
|
||||
std::sort(boost::begin(range), boost::end(range), lon_less);
|
||||
|
||||
CoordinateType max_gap_left = 0, max_gap_right = 0;
|
||||
CoordinateType max_gap
|
||||
= maximum_gap(range, max_gap_left, max_gap_right);
|
||||
|
||||
CoordinateType complement_gap
|
||||
= Constants::period() + lon_min - lon_max;
|
||||
|
||||
if (math::larger(max_gap, complement_gap))
|
||||
{
|
||||
lon_min = max_gap_right;
|
||||
lon_max = max_gap_left + Constants::period();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Constants,
|
||||
typename Iterator,
|
||||
typename LatitudeLess,
|
||||
typename CoordinateType
|
||||
>
|
||||
static inline void get_min_max_latitudes(Iterator const first,
|
||||
Iterator const last,
|
||||
LatitudeLess const& lat_less,
|
||||
bool has_south_pole,
|
||||
bool has_north_pole,
|
||||
CoordinateType& lat_min,
|
||||
CoordinateType& lat_max)
|
||||
{
|
||||
if (has_south_pole && has_north_pole)
|
||||
{
|
||||
lat_min = Constants::min_latitude();
|
||||
lat_max = Constants::max_latitude();
|
||||
}
|
||||
else if (has_south_pole)
|
||||
{
|
||||
lat_min = Constants::min_latitude();
|
||||
lat_max
|
||||
= geometry::get<1>(*std::max_element(first, last, lat_less));
|
||||
}
|
||||
else if (has_north_pole)
|
||||
{
|
||||
lat_min
|
||||
= geometry::get<1>(*std::min_element(first, last, lat_less));
|
||||
lat_max = Constants::max_latitude();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<Iterator, Iterator> min_max_latitudes
|
||||
= boost::minmax_element(first, last, lat_less);
|
||||
|
||||
lat_min = geometry::get<1>(*min_max_latitudes.first);
|
||||
lat_max = geometry::get<1>(*min_max_latitudes.second);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename MultiPoint, typename Box, typename Strategy>
|
||||
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<MultiPoint>::type point_type;
|
||||
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiPoint const
|
||||
>::type iterator_type;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
coordinate_type,
|
||||
typename coordinate_system<MultiPoint>::type::units
|
||||
> constants;
|
||||
|
||||
if (boost::empty(multipoint))
|
||||
{
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
return;
|
||||
}
|
||||
|
||||
initialize<Box, 0, 2>::apply(mbr);
|
||||
|
||||
if (boost::size(multipoint) == 1)
|
||||
{
|
||||
return dispatch::envelope
|
||||
<
|
||||
typename boost::range_value<MultiPoint>::type
|
||||
>::apply(range::front(multipoint), mbr, strategy);
|
||||
}
|
||||
|
||||
// analyze the points and put the non-pole ones in the
|
||||
// points vector
|
||||
std::vector<point_type> points;
|
||||
bool has_north_pole = false, has_south_pole = false;
|
||||
|
||||
analyze_point_coordinates<constants>(multipoint,
|
||||
has_south_pole, has_north_pole,
|
||||
std::back_inserter(points));
|
||||
|
||||
coordinate_type lon_min, lat_min, lon_max, lat_max;
|
||||
if (points.size() == 1)
|
||||
{
|
||||
// we have one non-pole point and at least one pole point
|
||||
lon_min = geometry::get<0>(range::front(points));
|
||||
lon_max = geometry::get<0>(range::front(points));
|
||||
lat_min = has_south_pole
|
||||
? constants::min_latitude()
|
||||
: constants::max_latitude();
|
||||
lat_max = has_north_pole
|
||||
? constants::max_latitude()
|
||||
: constants::min_latitude();
|
||||
}
|
||||
else if (points.empty())
|
||||
{
|
||||
// all points are pole points
|
||||
BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);
|
||||
lon_min = coordinate_type(0);
|
||||
lon_max = coordinate_type(0);
|
||||
lat_min = has_south_pole
|
||||
? constants::min_latitude()
|
||||
: constants::max_latitude();
|
||||
lat_max = (has_north_pole)
|
||||
? constants::max_latitude()
|
||||
: constants::min_latitude();
|
||||
}
|
||||
else
|
||||
{
|
||||
get_min_max_longitudes<constants>(points,
|
||||
coordinate_less<0>(),
|
||||
lon_min,
|
||||
lon_max);
|
||||
|
||||
get_min_max_latitudes<constants>(points.begin(),
|
||||
points.end(),
|
||||
coordinate_less<1>(),
|
||||
has_south_pole,
|
||||
has_north_pole,
|
||||
lat_min,
|
||||
lat_max);
|
||||
}
|
||||
|
||||
typedef typename helper_geometry
|
||||
<
|
||||
Box,
|
||||
coordinate_type,
|
||||
typename coordinate_system<MultiPoint>::type::units
|
||||
>::type helper_box_type;
|
||||
|
||||
helper_box_type helper_mbr;
|
||||
|
||||
geometry::set<min_corner, 0>(helper_mbr, lon_min);
|
||||
geometry::set<min_corner, 1>(helper_mbr, lat_min);
|
||||
geometry::set<max_corner, 0>(helper_mbr, lon_max);
|
||||
geometry::set<max_corner, 1>(helper_mbr, lat_max);
|
||||
|
||||
// now transform to output MBR (per index)
|
||||
envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
|
||||
envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
|
||||
|
||||
// compute envelope for higher coordinates
|
||||
iterator_type it = boost::begin(multipoint);
|
||||
envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy);
|
||||
|
||||
for (++it; it != boost::end(multipoint); ++it)
|
||||
{
|
||||
detail::expand::point_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
2, dimension<Box>::value
|
||||
>::apply(mbr, *it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint, typename CSTag>
|
||||
struct envelope<MultiPoint, multi_point_tag, CSTag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_multipoint_on_spheroid
|
||||
{};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct envelope<MultiPoint, multi_point_tag, geographic_tag>
|
||||
: detail::envelope::envelope_multipoint_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_one_point
|
||||
{
|
||||
template <std::size_t Index, typename Point, typename Box>
|
||||
static inline void apply(Point const& point, Box& mbr)
|
||||
{
|
||||
detail::indexed_point_view<Box, Index> box_corner(mbr);
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
Point,
|
||||
detail::indexed_point_view<Box, Index>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(point, box_corner);
|
||||
}
|
||||
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const&)
|
||||
{
|
||||
apply<min_corner>(point, mbr);
|
||||
apply<max_corner>(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct envelope_point_on_spheroid
|
||||
{
|
||||
template<typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
Point normalized_point = detail::return_normalized<Point>(point);
|
||||
|
||||
typename point_type<Box>::type box_point;
|
||||
|
||||
// transform units of input point to units of a box point
|
||||
transform_units(normalized_point, box_point);
|
||||
|
||||
geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
|
||||
geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
|
||||
|
||||
geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
|
||||
geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
|
||||
|
||||
envelope_one_point
|
||||
<
|
||||
2, dimension<Point>::value
|
||||
>::apply(normalized_point, mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename CS_Tag>
|
||||
struct envelope<Point, point_tag, CS_Tag>
|
||||
: detail::envelope::envelope_one_point<0, dimension<Point>::value>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_point_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, geographic_tag>
|
||||
: detail::envelope::envelope_point_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/segment.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
// implementation for simple ranges
|
||||
struct envelope_range
|
||||
{
|
||||
template <typename Iterator, typename Box, typename Strategy>
|
||||
static inline void apply(Iterator first,
|
||||
Iterator last,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
||||
|
||||
// initialize MBR
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
|
||||
Iterator it = first;
|
||||
if (it != last)
|
||||
{
|
||||
// initialize box with first element in range
|
||||
dispatch::envelope<value_type>::apply(*it, mbr, strategy);
|
||||
|
||||
// consider now the remaining elements in the range (if any)
|
||||
for (++it; it != last; ++it)
|
||||
{
|
||||
dispatch::expand<Box, value_type>::apply(mbr, *it, strategy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename Box, typename Strategy>
|
||||
static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
return apply(boost::begin(range), boost::end(range), mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// implementation for multi-ranges
|
||||
template <typename EnvelopePolicy>
|
||||
struct envelope_multi_range
|
||||
{
|
||||
template <typename MultiRange, typename Box, typename Strategy>
|
||||
static inline void apply(MultiRange const& multirange,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiRange const
|
||||
>::type iterator_type;
|
||||
|
||||
bool initialized = false;
|
||||
for (iterator_type it = boost::begin(multirange);
|
||||
it != boost::end(multirange);
|
||||
++it)
|
||||
{
|
||||
if (! geometry::is_empty(*it))
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
Box helper_mbr;
|
||||
EnvelopePolicy::apply(*it, helper_mbr, strategy);
|
||||
|
||||
dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compute the initial envelope
|
||||
EnvelopePolicy::apply(*it, mbr, strategy);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! initialized)
|
||||
{
|
||||
// if not already initialized, initialize MBR
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// implementation for multi-range on a spheroid (longitude is periodic)
|
||||
template <typename EnvelopePolicy>
|
||||
struct envelope_multi_range_on_spheroid
|
||||
{
|
||||
template <typename MultiRange, typename Box, typename Strategy>
|
||||
static inline void apply(MultiRange const& multirange,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiRange const
|
||||
>::type iterator_type;
|
||||
|
||||
// due to the periodicity of longitudes we need to compute the boxes
|
||||
// of all the single geometries and keep them in a container
|
||||
std::vector<Box> boxes;
|
||||
for (iterator_type it = boost::begin(multirange);
|
||||
it != boost::end(multirange);
|
||||
++it)
|
||||
{
|
||||
if (! geometry::is_empty(*it))
|
||||
{
|
||||
Box helper_box;
|
||||
EnvelopePolicy::apply(*it, helper_box, strategy);
|
||||
boxes.push_back(helper_box);
|
||||
}
|
||||
}
|
||||
|
||||
// now we need to compute the envelope of the range of boxes
|
||||
// (cannot be done in an incremental fashion as in the
|
||||
// Cartesian coordinate system)
|
||||
// if all single geometries are empty no boxes have been found
|
||||
// and the MBR is simply initialized
|
||||
if (! boxes.empty())
|
||||
{
|
||||
envelope_range_of_boxes::apply(boxes, mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
template <typename T>
|
||||
class longitude_interval
|
||||
{
|
||||
typedef T const& reference_type;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T difference_type;
|
||||
|
||||
longitude_interval(T const& left, T const& right)
|
||||
{
|
||||
m_end[0] = left;
|
||||
m_end[1] = right;
|
||||
}
|
||||
|
||||
template <std::size_t Index>
|
||||
reference_type get() const
|
||||
{
|
||||
return m_end[Index];
|
||||
}
|
||||
|
||||
difference_type length() const
|
||||
{
|
||||
return get<1>() - get<0>();
|
||||
}
|
||||
|
||||
private:
|
||||
T m_end[2];
|
||||
};
|
||||
|
||||
|
||||
template <typename Units>
|
||||
struct envelope_range_of_longitudes
|
||||
{
|
||||
template <std::size_t Index>
|
||||
struct longitude_less
|
||||
{
|
||||
template <typename Interval>
|
||||
inline bool operator()(Interval const& i1, Interval const& i2) const
|
||||
{
|
||||
return math::smaller(i1.template get<Index>(),
|
||||
i2.template get<Index>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RangeOfLongitudeIntervals, typename Longitude>
|
||||
static inline void apply(RangeOfLongitudeIntervals const& range,
|
||||
Longitude& lon_min, Longitude& lon_max)
|
||||
{
|
||||
typedef typename math::detail::constants_on_spheroid
|
||||
<
|
||||
Longitude, Units
|
||||
> constants;
|
||||
|
||||
Longitude const zero = 0;
|
||||
Longitude const period = constants::period();
|
||||
|
||||
lon_min = lon_max = zero;
|
||||
|
||||
// the range of longitude intervals can be empty if all input boxes
|
||||
// degenerate to the north or south pole (or combination of the two)
|
||||
// in this case the initialization values for lon_min and
|
||||
// lon_max are valid choices
|
||||
if (! boost::empty(range))
|
||||
{
|
||||
lon_min = std::min_element(boost::begin(range),
|
||||
boost::end(range),
|
||||
longitude_less<0>())->template get<0>();
|
||||
lon_max = std::max_element(boost::begin(range),
|
||||
boost::end(range),
|
||||
longitude_less<1>())->template get<1>();
|
||||
|
||||
if (math::larger(lon_max - lon_min, constants::half_period()))
|
||||
{
|
||||
Longitude max_gap_left, max_gap_right;
|
||||
Longitude max_gap = geometry::maximum_gap(range,
|
||||
max_gap_left,
|
||||
max_gap_right);
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! math::larger(lon_min, lon_max));
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(! math::larger(lon_max, constants::max_longitude()));
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(! math::smaller(lon_min, constants::min_longitude()));
|
||||
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(! math::larger(max_gap_left, max_gap_right));
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(! math::larger(max_gap_right, constants::max_longitude()));
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(! math::smaller(max_gap_left, constants::min_longitude()));
|
||||
|
||||
if (math::larger(max_gap, zero))
|
||||
{
|
||||
Longitude wrapped_gap = period + lon_min - lon_max;
|
||||
if (math::larger(max_gap, wrapped_gap))
|
||||
{
|
||||
lon_min = max_gap_right;
|
||||
lon_max = max_gap_left + period;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_range_of_boxes_by_expansion
|
||||
{
|
||||
template <typename RangeOfBoxes, typename Box, typename Strategy>
|
||||
static inline void apply(RangeOfBoxes const& range_of_boxes,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
|
||||
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
RangeOfBoxes const
|
||||
>::type iterator_type;
|
||||
|
||||
// first initialize MBR
|
||||
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
|
||||
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
|
||||
|
||||
detail::indexed_point_view<box_type const, min_corner>
|
||||
first_box_min(range::front(range_of_boxes));
|
||||
|
||||
detail::indexed_point_view<box_type const, max_corner>
|
||||
first_box_max(range::front(range_of_boxes));
|
||||
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<box_type const, min_corner>,
|
||||
detail::indexed_point_view<Box, min_corner>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(first_box_min, mbr_min);
|
||||
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<box_type const, max_corner>,
|
||||
detail::indexed_point_view<Box, max_corner>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(first_box_max, mbr_max);
|
||||
|
||||
// now expand using the remaining boxes
|
||||
iterator_type it = boost::begin(range_of_boxes);
|
||||
for (++it; it != boost::end(range_of_boxes); ++it)
|
||||
{
|
||||
detail::expand::indexed_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
min_corner,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(mbr, *it, strategy);
|
||||
|
||||
detail::expand::indexed_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
max_corner,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(mbr, *it, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct envelope_range_of_boxes
|
||||
{
|
||||
template <std::size_t Index>
|
||||
struct latitude_less
|
||||
{
|
||||
template <typename Box>
|
||||
inline bool operator()(Box const& box1, Box const& box2) const
|
||||
{
|
||||
return math::smaller(geometry::get<Index, 1>(box1),
|
||||
geometry::get<Index, 1>(box2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RangeOfBoxes, typename Box, typename Strategy>
|
||||
static inline void apply(RangeOfBoxes const& range_of_boxes,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// boxes in the range are assumed to be normalized already
|
||||
|
||||
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
|
||||
typedef typename coordinate_type<box_type>::type coordinate_type;
|
||||
typedef typename coordinate_system<box_type>::type::units units_type;
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
RangeOfBoxes const
|
||||
>::type iterator_type;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
coordinate_type, units_type
|
||||
> constants;
|
||||
|
||||
typedef longitude_interval<coordinate_type> interval_type;
|
||||
typedef std::vector<interval_type> interval_range_type;
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes));
|
||||
|
||||
iterator_type it_min = std::min_element(boost::begin(range_of_boxes),
|
||||
boost::end(range_of_boxes),
|
||||
latitude_less<min_corner>());
|
||||
iterator_type it_max = std::max_element(boost::begin(range_of_boxes),
|
||||
boost::end(range_of_boxes),
|
||||
latitude_less<max_corner>());
|
||||
|
||||
coordinate_type const min_longitude = constants::min_longitude();
|
||||
coordinate_type const max_longitude = constants::max_longitude();
|
||||
coordinate_type const period = constants::period();
|
||||
|
||||
interval_range_type intervals;
|
||||
for (iterator_type it = boost::begin(range_of_boxes);
|
||||
it != boost::end(range_of_boxes);
|
||||
++it)
|
||||
{
|
||||
coordinate_type lat_min = geometry::get<min_corner, 1>(*it);
|
||||
coordinate_type lat_max = geometry::get<max_corner, 1>(*it);
|
||||
if (math::equals(lat_min, constants::max_latitude())
|
||||
|| math::equals(lat_max, constants::min_latitude()))
|
||||
{
|
||||
// if the box degenerates to the south or north pole
|
||||
// just ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
coordinate_type lon_left = geometry::get<min_corner, 0>(*it);
|
||||
coordinate_type lon_right = geometry::get<max_corner, 0>(*it);
|
||||
|
||||
if (math::larger(lon_right, max_longitude))
|
||||
{
|
||||
intervals.push_back(interval_type(lon_left, max_longitude));
|
||||
intervals.push_back
|
||||
(interval_type(min_longitude, lon_right - period));
|
||||
}
|
||||
else
|
||||
{
|
||||
intervals.push_back(interval_type(lon_left, lon_right));
|
||||
}
|
||||
}
|
||||
|
||||
coordinate_type lon_min = 0;
|
||||
coordinate_type lon_max = 0;
|
||||
envelope_range_of_longitudes
|
||||
<
|
||||
units_type
|
||||
>::apply(intervals, lon_min, lon_max);
|
||||
|
||||
// do not convert units; conversion will be performed at a
|
||||
// higher level
|
||||
|
||||
// assign now the min/max longitude/latitude values
|
||||
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
|
||||
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
|
||||
|
||||
geometry::set<0>(mbr_min, lon_min);
|
||||
geometry::set<1>(mbr_min, geometry::get<min_corner, 1>(*it_min));
|
||||
geometry::set<0>(mbr_max, lon_max);
|
||||
geometry::set<1>(mbr_max, geometry::get<max_corner, 1>(*it_max));
|
||||
|
||||
// what remains to be done is to compute the envelope range
|
||||
// for the remaining dimensions (if any)
|
||||
envelope_range_of_boxes_by_expansion
|
||||
<
|
||||
2, dimension<Box>::value
|
||||
>::apply(range_of_boxes, mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_OF_BOXES_HPP
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-2017.
|
||||
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/vertex_latitude.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
template <typename CalculationType, typename CS_Tag>
|
||||
struct envelope_segment_call_vertex_latitude
|
||||
{
|
||||
template <typename T1, typename T2, typename Strategy>
|
||||
static inline CalculationType apply(T1 const& lat1,
|
||||
T2 const& alp1,
|
||||
Strategy const& )
|
||||
{
|
||||
return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
|
||||
::apply(lat1, alp1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CalculationType>
|
||||
struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
|
||||
{
|
||||
template <typename T1, typename T2, typename Strategy>
|
||||
static inline CalculationType apply(T1 const& lat1,
|
||||
T2 const& alp1,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
|
||||
::apply(lat1, alp1, strategy.model());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CS_Tag>
|
||||
class envelope_segment_impl
|
||||
{
|
||||
private:
|
||||
|
||||
// degrees or radians
|
||||
template <typename CalculationType>
|
||||
static inline void swap(CalculationType& lon1,
|
||||
CalculationType& lat1,
|
||||
CalculationType& lon2,
|
||||
CalculationType& lat2)
|
||||
{
|
||||
std::swap(lon1, lon2);
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
|
||||
// radians
|
||||
template <typename CalculationType>
|
||||
static inline bool contains_pi_half(CalculationType const& a1,
|
||||
CalculationType const& a2)
|
||||
{
|
||||
// azimuths a1 and a2 are assumed to be in radians
|
||||
BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));
|
||||
|
||||
static CalculationType const pi_half = math::half_pi<CalculationType>();
|
||||
|
||||
return (a1 < a2)
|
||||
? (a1 < pi_half && pi_half < a2)
|
||||
: (a1 > pi_half && pi_half > a2);
|
||||
}
|
||||
|
||||
// radians or degrees
|
||||
template <typename Units, typename CoordinateType>
|
||||
static inline bool crosses_antimeridian(CoordinateType const& lon1,
|
||||
CoordinateType const& lon2)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
CoordinateType, Units
|
||||
> constants;
|
||||
|
||||
return math::abs(lon1 - lon2) > constants::half_period(); // > pi
|
||||
}
|
||||
|
||||
// degrees or radians
|
||||
template <typename Units, typename CalculationType, typename Strategy>
|
||||
static inline void compute_box_corners(CalculationType& lon1,
|
||||
CalculationType& lat1,
|
||||
CalculationType& lon2,
|
||||
CalculationType& lat2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// coordinates are assumed to be in radians
|
||||
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
|
||||
|
||||
CalculationType lon1_rad = math::as_radian<Units>(lon1);
|
||||
CalculationType lat1_rad = math::as_radian<Units>(lat1);
|
||||
CalculationType lon2_rad = math::as_radian<Units>(lon2);
|
||||
CalculationType lat2_rad = math::as_radian<Units>(lat2);
|
||||
|
||||
CalculationType a1, a2;
|
||||
strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
|
||||
|
||||
if (lat1 > lat2)
|
||||
{
|
||||
std::swap(lat1, lat2);
|
||||
std::swap(lat1_rad, lat2_rad);
|
||||
std::swap(a1, a2);
|
||||
}
|
||||
|
||||
if (math::equals(a1, a2))
|
||||
{
|
||||
// the segment must lie on the equator or is very short
|
||||
return;
|
||||
}
|
||||
|
||||
if (contains_pi_half(a1, a2))
|
||||
{
|
||||
CalculationType p_max = envelope_segment_call_vertex_latitude
|
||||
<CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
|
||||
|
||||
CalculationType const mid_lat = lat1 + lat2;
|
||||
if (mid_lat < 0)
|
||||
{
|
||||
// update using min latitude
|
||||
CalculationType const lat_min_rad = -p_max;
|
||||
CalculationType const lat_min
|
||||
= math::from_radian<Units>(lat_min_rad);
|
||||
|
||||
if (lat1 > lat_min)
|
||||
{
|
||||
lat1 = lat_min;
|
||||
}
|
||||
}
|
||||
else if (mid_lat > 0)
|
||||
{
|
||||
// update using max latitude
|
||||
CalculationType const lat_max_rad = p_max;
|
||||
CalculationType const lat_max
|
||||
= math::from_radian<Units>(lat_max_rad);
|
||||
|
||||
if (lat2 < lat_max)
|
||||
{
|
||||
lat2 = lat_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Units, typename CalculationType, typename Strategy>
|
||||
static inline void apply(CalculationType& lon1,
|
||||
CalculationType& lat1,
|
||||
CalculationType& lon2,
|
||||
CalculationType& lat2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
CalculationType, Units
|
||||
> constants;
|
||||
|
||||
bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude());
|
||||
bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude());
|
||||
|
||||
if (is_pole1 && is_pole2)
|
||||
{
|
||||
// both points are poles; nothing more to do:
|
||||
// longitudes are already normalized to 0
|
||||
// but just in case
|
||||
lon1 = 0;
|
||||
lon2 = 0;
|
||||
}
|
||||
else if (is_pole1 && !is_pole2)
|
||||
{
|
||||
// first point is a pole, second point is not:
|
||||
// make the longitude of the first point the same as that
|
||||
// of the second point
|
||||
lon1 = lon2;
|
||||
}
|
||||
else if (!is_pole1 && is_pole2)
|
||||
{
|
||||
// second point is a pole, first point is not:
|
||||
// make the longitude of the second point the same as that
|
||||
// of the first point
|
||||
lon2 = lon1;
|
||||
}
|
||||
|
||||
if (lon1 == lon2)
|
||||
{
|
||||
// segment lies on a meridian
|
||||
if (lat1 > lat2)
|
||||
{
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);
|
||||
|
||||
if (lon1 > lon2)
|
||||
{
|
||||
swap(lon1, lat1, lon2, lat2);
|
||||
}
|
||||
|
||||
if (crosses_antimeridian<Units>(lon1, lon2))
|
||||
{
|
||||
lon1 += constants::period();
|
||||
swap(lon1, lat1, lon2, lat2);
|
||||
}
|
||||
|
||||
compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy);
|
||||
}
|
||||
|
||||
public:
|
||||
template <
|
||||
typename Units,
|
||||
typename CalculationType,
|
||||
typename Box,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(CalculationType lon1,
|
||||
CalculationType lat1,
|
||||
CalculationType lon2,
|
||||
CalculationType lat2,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type box_coordinate_type;
|
||||
|
||||
typedef typename helper_geometry
|
||||
<
|
||||
Box, box_coordinate_type, Units
|
||||
>::type helper_box_type;
|
||||
|
||||
helper_box_type radian_mbr;
|
||||
|
||||
apply<Units>(lon1, lat1, lon2, lat2, strategy);
|
||||
|
||||
geometry::set
|
||||
<
|
||||
min_corner, 0
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
min_corner, 1
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
max_corner, 0
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
max_corner, 1
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
|
||||
|
||||
transform_units(radian_mbr, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_one_segment
|
||||
{
|
||||
template<typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& p1,
|
||||
Point const& p2,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy);
|
||||
detail::expand::point_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(mbr, p2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct envelope_segment
|
||||
{
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& p1,
|
||||
Point const& p2,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// first compute the envelope range for the first two coordinates
|
||||
strategy.apply(p1, p2, mbr);
|
||||
|
||||
// now compute the envelope range for coordinates of
|
||||
// dimension 2 and higher
|
||||
envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy);
|
||||
}
|
||||
|
||||
template <typename Segment, typename Box>
|
||||
static inline void apply(Segment const& segment, Box& mbr)
|
||||
{
|
||||
typename point_type<Segment>::type p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
apply(p[0], p[1], mbr);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment>
|
||||
struct envelope<Segment, segment_tag>
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Segment const& segment,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename point_type<Segment>::type p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
detail::envelope::envelope_segment
|
||||
<
|
||||
dimension<Segment>::value
|
||||
>::apply(p[0], p[1], mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
|
||||
+103
@@ -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
|
||||
+575
@@ -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
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-2014.
|
||||
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace equals
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect of points are disjoint
|
||||
\note To avoid circular references
|
||||
*/
|
||||
template <typename Point1, typename Point2>
|
||||
inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return ! detail::disjoint::disjoint_point_point(point1, point2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::equals
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
|
||||
@@ -0,0 +1,129 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
|
||||
struct box_on_spheroid
|
||||
{
|
||||
template <typename BoxOut, typename BoxIn, typename Strategy>
|
||||
static inline void apply(BoxOut& box_out,
|
||||
BoxIn const& box_in,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// normalize both boxes and convert box-in to be of type of box-out
|
||||
BoxOut mbrs[2];
|
||||
detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0], strategy);
|
||||
detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy);
|
||||
|
||||
// compute the envelope of the two boxes
|
||||
detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// Box + box -> new box containing two input boxes
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<BoxIn>::value, StrategyLess, StrategyGreater
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::box_on_spheroid
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::box_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
|
||||
+27
@@ -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
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct indexed_loop
|
||||
{
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box& box, Geometry const& source, Strategy const& strategy)
|
||||
{
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyLess, 1, Box, Dimension
|
||||
>::type less_type;
|
||||
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyGreater, -1, Box, Dimension
|
||||
>::type greater_type;
|
||||
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Box,
|
||||
Geometry
|
||||
>::type coordinate_type;
|
||||
|
||||
less_type less;
|
||||
greater_type greater;
|
||||
|
||||
coordinate_type const coord = get<Index, Dimension>(source);
|
||||
|
||||
if (less(coord, get<min_corner, Dimension>(box)))
|
||||
{
|
||||
set<min_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
if (greater(coord, get<max_corner, Dimension>(box)))
|
||||
{
|
||||
set<max_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
Index, Dimension + 1, DimensionCount
|
||||
>::apply(box, source, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Index, std::size_t DimensionCount
|
||||
>
|
||||
struct indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
Index, DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box&, Geometry const&, Strategy const&) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Changes a box such that the other box is also contained by the box
|
||||
template
|
||||
<
|
||||
std::size_t Dimension, std::size_t DimensionCount,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand_indexed
|
||||
{
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
0, Dimension, DimensionCount
|
||||
>::apply(box, geometry, strategy);
|
||||
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
1, Dimension, DimensionCount
|
||||
>::apply(box, geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct expand
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
dispatch::expand<Box, Geometry>::apply(box, geometry, strategy);
|
||||
}
|
||||
|
||||
template <typename Box>
|
||||
static inline void apply(Box& box,
|
||||
Geometry const& geometry,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef typename coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef typename strategy::envelope::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
coordinate_type
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct expand
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Box>();
|
||||
concepts::check<Geometry const>();
|
||||
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
|
||||
|
||||
resolve_strategy::expand<Geometry>::apply(box, geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Box& m_box;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Box& box, Strategy const& strategy)
|
||||
: m_box(box)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry) const
|
||||
{
|
||||
return expand<Geometry>::apply(m_box, geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Box, typename Strategy>
|
||||
static inline void
|
||||
apply(Box& box,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
|
||||
geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/***
|
||||
*!
|
||||
\brief Expands a box using the extend (envelope) of another geometry (box, point)
|
||||
\ingroup expand
|
||||
\tparam Box type of the box
|
||||
\tparam Geometry of second geometry, to be expanded with the box
|
||||
\param box box to expand another geometry with, might be changed
|
||||
\param geometry other geometry
|
||||
\param strategy_less
|
||||
\param strategy_greater
|
||||
\note Strategy is currently ignored
|
||||
*
|
||||
template
|
||||
<
|
||||
typename Box, typename Geometry,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
inline void expand(Box& box, Geometry const& geometry,
|
||||
StrategyLess const& strategy_less,
|
||||
StrategyGreater const& strategy_greater)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
|
||||
|
||||
dispatch::expand<Box, Geometry>::apply(box, geometry);
|
||||
}
|
||||
***/
|
||||
|
||||
/*!
|
||||
\brief Expands (with strategy)
|
||||
\ingroup expand
|
||||
\tparam Box type of the box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{expand}
|
||||
\param box box to be expanded using another geometry, mutable
|
||||
\param geometry \param_geometry geometry which envelope (bounding box)
|
||||
\param strategy \param_strategy{expand}
|
||||
will be added to the box
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/expand.qbk]}
|
||||
*/
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
|
||||
resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Expands a box using the bounding box (envelope) of another geometry
|
||||
(box, point)
|
||||
\ingroup expand
|
||||
\tparam Box type of the box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param box box to be expanded using another geometry, mutable
|
||||
\param geometry \param_geometry geometry which envelope (bounding box) will be
|
||||
added to the box
|
||||
|
||||
\qbk{[include reference/algorithms/expand.qbk]}
|
||||
*/
|
||||
template <typename Box, typename Geometry>
|
||||
inline void expand(Box& box, Geometry const& geometry)
|
||||
{
|
||||
resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
static inline void apply(Box& box, Point const& source, Strategy const& strategy)
|
||||
{
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyLess, 1, Point, Dimension
|
||||
>::type less_type;
|
||||
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyGreater, -1, Point, Dimension
|
||||
>::type greater_type;
|
||||
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Point, Box
|
||||
>::type coordinate_type;
|
||||
|
||||
less_type less;
|
||||
greater_type greater;
|
||||
|
||||
coordinate_type const coord = get<Dimension>(source);
|
||||
|
||||
if (less(coord, get<min_corner, Dimension>(box)))
|
||||
{
|
||||
set<min_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
if (greater(coord, get<max_corner, Dimension>(box)))
|
||||
{
|
||||
set<max_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
|
||||
>::apply(box, source, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess,
|
||||
typename StrategyGreater,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
static inline void apply(Box&, Point const&, Strategy const&) {}
|
||||
};
|
||||
|
||||
|
||||
// implementation for the spherical equatorial and geographic coordinate systems
|
||||
template
|
||||
<
|
||||
typename StrategyLess,
|
||||
typename StrategyGreater,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop_on_spheroid
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Point const& point,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Box>::type box_point_type;
|
||||
typedef typename coordinate_type<Box>::type box_coordinate_type;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
box_coordinate_type,
|
||||
typename coordinate_system<Box>::type::units
|
||||
> constants;
|
||||
|
||||
// normalize input point and input box
|
||||
Point p_normalized = detail::return_normalized<Point>(point);
|
||||
detail::normalize(box, box);
|
||||
|
||||
// transform input point to be of the same type as the box point
|
||||
box_point_type box_point;
|
||||
detail::envelope::transform_units(p_normalized, box_point);
|
||||
|
||||
box_coordinate_type p_lon = geometry::get<0>(box_point);
|
||||
box_coordinate_type p_lat = geometry::get<1>(box_point);
|
||||
|
||||
typename coordinate_type<Box>::type
|
||||
b_lon_min = geometry::get<min_corner, 0>(box),
|
||||
b_lat_min = geometry::get<min_corner, 1>(box),
|
||||
b_lon_max = geometry::get<max_corner, 0>(box),
|
||||
b_lat_max = geometry::get<max_corner, 1>(box);
|
||||
|
||||
if (math::equals(math::abs(p_lat), constants::max_latitude()))
|
||||
{
|
||||
// the point of expansion is the either the north or the
|
||||
// south pole; the only important coordinate here is the
|
||||
// pole's latitude, as the longitude can be anything;
|
||||
// we, thus, take into account the point's latitude only and return
|
||||
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
|
||||
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
|
||||
return;
|
||||
}
|
||||
|
||||
if (math::equals(b_lat_min, b_lat_max)
|
||||
&& math::equals(math::abs(b_lat_min), constants::max_latitude()))
|
||||
{
|
||||
// the box degenerates to either the north or the south pole;
|
||||
// the only important coordinate here is the pole's latitude,
|
||||
// as the longitude can be anything;
|
||||
// we thus take into account the box's latitude only and return
|
||||
geometry::set<min_corner, 0>(box, p_lon);
|
||||
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
|
||||
geometry::set<max_corner, 0>(box, p_lon);
|
||||
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
|
||||
return;
|
||||
}
|
||||
|
||||
// update latitudes
|
||||
b_lat_min = (std::min)(b_lat_min, p_lat);
|
||||
b_lat_max = (std::max)(b_lat_max, p_lat);
|
||||
|
||||
// update longitudes
|
||||
if (math::smaller(p_lon, b_lon_min))
|
||||
{
|
||||
box_coordinate_type p_lon_shifted = p_lon + constants::period();
|
||||
|
||||
if (math::larger(p_lon_shifted, b_lon_max))
|
||||
{
|
||||
// here we could check using: ! math::larger(.., ..)
|
||||
if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
|
||||
{
|
||||
b_lon_min = p_lon;
|
||||
}
|
||||
else
|
||||
{
|
||||
b_lon_max = p_lon_shifted;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (math::larger(p_lon, b_lon_max))
|
||||
{
|
||||
// in this case, and since p_lon is normalized in the range
|
||||
// (-180, 180], we must have that b_lon_max <= 180
|
||||
if (b_lon_min < 0
|
||||
&& math::larger(p_lon - b_lon_max,
|
||||
constants::period() - p_lon + b_lon_min))
|
||||
{
|
||||
b_lon_min = p_lon;
|
||||
b_lon_max += constants::period();
|
||||
}
|
||||
else
|
||||
{
|
||||
b_lon_max = p_lon;
|
||||
}
|
||||
}
|
||||
|
||||
geometry::set<min_corner, 0>(box, b_lon_min);
|
||||
geometry::set<min_corner, 1>(box, b_lat_min);
|
||||
geometry::set<max_corner, 0>(box, b_lon_max);
|
||||
geometry::set<max_corner, 1>(box, b_lat_max);
|
||||
|
||||
point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, 2, DimensionCount
|
||||
>::apply(box, point, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// Box + point -> new box containing also point
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, 0, dimension<Point>::value
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::point_loop_on_spheroid
|
||||
<
|
||||
StrategyLess, StrategyGreater, dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::point_loop_on_spheroid
|
||||
<
|
||||
StrategyLess, StrategyGreater, dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
struct segment
|
||||
{
|
||||
template <typename Box, typename Segment, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
Box mbrs[2];
|
||||
|
||||
// compute the envelope of the segment
|
||||
typename point_type<Segment>::type p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
detail::envelope::envelope_segment
|
||||
<
|
||||
dimension<Segment>::value
|
||||
>::apply(p[0], p[1], mbrs[0], strategy);
|
||||
|
||||
// normalize the box
|
||||
detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy);
|
||||
|
||||
// compute the envelope of the two boxes
|
||||
detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<Segment>::value, StrategyLess, StrategyGreater
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::segment
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::segment
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
|
||||
+113
@@ -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
|
||||
+520
@@ -0,0 +1,520 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace extreme_points
|
||||
{
|
||||
|
||||
template <std::size_t Dimension>
|
||||
struct compare
|
||||
{
|
||||
template <typename Point>
|
||||
inline bool operator()(Point const& lhs, Point const& rhs)
|
||||
{
|
||||
return geometry::get<Dimension>(lhs) < geometry::get<Dimension>(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t Dimension, typename PointType, typename CoordinateType>
|
||||
inline void move_along_vector(PointType& point, PointType const& extreme, CoordinateType const& base_value)
|
||||
{
|
||||
// Moves a point along the vector (point, extreme) in the direction of the extreme point
|
||||
// This adapts the possibly uneven legs of the triangle (or trapezium-like shape)
|
||||
// _____extreme _____
|
||||
// / \ / \ .
|
||||
// /base \ => / \ point .
|
||||
// \ point .
|
||||
//
|
||||
// For so-called intruders, it can be used to adapt both legs to the level of "base"
|
||||
// For the base, it can be used to adapt both legs to the level of the max-value of the intruders
|
||||
// If there are 2 or more extreme values, use the one close to 'point' to have a correct vector
|
||||
|
||||
CoordinateType const value = geometry::get<Dimension>(point);
|
||||
//if (geometry::math::equals(value, base_value))
|
||||
if (value >= base_value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PointType vector = point;
|
||||
subtract_point(vector, extreme);
|
||||
|
||||
CoordinateType const diff = geometry::get<Dimension>(vector);
|
||||
|
||||
// diff should never be zero
|
||||
// because of the way our triangle/trapezium is build.
|
||||
// We just return if it would be the case.
|
||||
if (geometry::math::equals(diff, 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CoordinateType const base_diff = base_value - geometry::get<Dimension>(extreme);
|
||||
|
||||
multiply_value(vector, base_diff);
|
||||
divide_value(vector, diff);
|
||||
|
||||
// The real move:
|
||||
point = extreme;
|
||||
add_point(point, vector);
|
||||
}
|
||||
|
||||
|
||||
template <std::size_t Dimension, typename Range, typename CoordinateType>
|
||||
inline void move_along_vector(Range& range, CoordinateType const& base_value)
|
||||
{
|
||||
if (range.size() >= 3)
|
||||
{
|
||||
move_along_vector<Dimension>(range.front(), *(range.begin() + 1), base_value);
|
||||
move_along_vector<Dimension>(range.back(), *(range.rbegin() + 1), base_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Ring, std::size_t Dimension>
|
||||
struct extreme_points_on_ring
|
||||
{
|
||||
|
||||
typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
|
||||
typedef typename boost::range_iterator<Ring const>::type range_iterator;
|
||||
typedef typename geometry::point_type<Ring>::type point_type;
|
||||
|
||||
typedef typename geometry::strategy::side::services::default_strategy
|
||||
<
|
||||
typename geometry::cs_tag<point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
|
||||
template <typename CirclingIterator, typename Points>
|
||||
static inline bool extend(CirclingIterator& it,
|
||||
std::size_t n,
|
||||
coordinate_type max_coordinate_value,
|
||||
Points& points, int direction)
|
||||
{
|
||||
std::size_t safe_index = 0;
|
||||
do
|
||||
{
|
||||
it += direction;
|
||||
|
||||
points.push_back(*it);
|
||||
|
||||
if (safe_index++ >= n)
|
||||
{
|
||||
// E.g.: ring is completely horizontal or vertical (= invalid, but we don't want to have an infinite loop)
|
||||
return false;
|
||||
}
|
||||
} while (geometry::math::equals(geometry::get<Dimension>(*it), max_coordinate_value));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overload without adding to poinst
|
||||
template <typename CirclingIterator>
|
||||
static inline bool extend(CirclingIterator& it,
|
||||
std::size_t n,
|
||||
coordinate_type max_coordinate_value,
|
||||
int direction)
|
||||
{
|
||||
std::size_t safe_index = 0;
|
||||
do
|
||||
{
|
||||
it += direction;
|
||||
|
||||
if (safe_index++ >= n)
|
||||
{
|
||||
// E.g.: ring is completely horizontal or vertical (= invalid, but we don't want to have an infinite loop)
|
||||
return false;
|
||||
}
|
||||
} while (geometry::math::equals(geometry::get<Dimension>(*it), max_coordinate_value));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CirclingIterator>
|
||||
static inline bool extent_both_sides(Ring const& ring,
|
||||
point_type extreme,
|
||||
CirclingIterator& left,
|
||||
CirclingIterator& right)
|
||||
{
|
||||
std::size_t const n = boost::size(ring);
|
||||
coordinate_type const max_coordinate_value = geometry::get<Dimension>(extreme);
|
||||
|
||||
if (! extend(left, n, max_coordinate_value, -1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (! extend(right, n, max_coordinate_value, +1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Collection, typename CirclingIterator>
|
||||
static inline bool collect(Ring const& ring,
|
||||
point_type extreme,
|
||||
Collection& points,
|
||||
CirclingIterator& left,
|
||||
CirclingIterator& right)
|
||||
{
|
||||
std::size_t const n = boost::size(ring);
|
||||
coordinate_type const max_coordinate_value = geometry::get<Dimension>(extreme);
|
||||
|
||||
// Collects first left, which is reversed (if more than one point) then adds the top itself, then right
|
||||
if (! extend(left, n, max_coordinate_value, points, -1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::reverse(points.begin(), points.end());
|
||||
points.push_back(extreme);
|
||||
if (! extend(right, n, max_coordinate_value, points, +1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Extremes, typename Intruders, typename CirclingIterator>
|
||||
static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right,
|
||||
Extremes const& extremes,
|
||||
Intruders& intruders)
|
||||
{
|
||||
if (boost::size(extremes) < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
coordinate_type const min_value = geometry::get<Dimension>(*std::min_element(boost::begin(extremes), boost::end(extremes), compare<Dimension>()));
|
||||
|
||||
// Also select left/right (if Dimension=1)
|
||||
coordinate_type const other_min = geometry::get<1 - Dimension>(*std::min_element(boost::begin(extremes), boost::end(extremes), compare<1 - Dimension>()));
|
||||
coordinate_type const other_max = geometry::get<1 - Dimension>(*std::max_element(boost::begin(extremes), boost::end(extremes), compare<1 - Dimension>()));
|
||||
|
||||
std::size_t defensive_check_index = 0; // in case we skip over left/right check, collect modifies right too
|
||||
std::size_t const n = boost::size(ring);
|
||||
while (left != right && defensive_check_index < n)
|
||||
{
|
||||
coordinate_type const coordinate = geometry::get<Dimension>(*right);
|
||||
coordinate_type const other_coordinate = geometry::get<1 - Dimension>(*right);
|
||||
if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max)
|
||||
{
|
||||
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
|
||||
int const first_side = side_strategy::apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
|
||||
int const last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
|
||||
|
||||
// If not lying left from any of the extemes side
|
||||
if (first_side != 1 && last_side != 1)
|
||||
{
|
||||
//std::cout << "first " << first_side << " last " << last_side << std::endl;
|
||||
|
||||
// we start at this intrusion until it is handled, and don't affect our initial left iterator
|
||||
CirclingIterator left_intrusion_it = right;
|
||||
typename boost::range_value<Intruders>::type intruder;
|
||||
collect(ring, *right, intruder, left_intrusion_it, right);
|
||||
|
||||
// Also moves these to base-level, makes sorting possible which can be done in case of self-tangencies
|
||||
// (we might postpone this action, it is often not necessary. However it is not time-consuming)
|
||||
move_along_vector<Dimension>(intruder, min_value);
|
||||
intruders.push_back(intruder);
|
||||
--right;
|
||||
}
|
||||
}
|
||||
++right;
|
||||
defensive_check_index++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline void get_intruders(Ring const& ring,
|
||||
Extremes const& extremes,
|
||||
Intruders& intruders)
|
||||
{
|
||||
std::size_t const n = boost::size(ring);
|
||||
if (n >= 3)
|
||||
{
|
||||
geometry::ever_circling_range_iterator<Ring const> left(ring);
|
||||
geometry::ever_circling_range_iterator<Ring const> right(ring);
|
||||
++right;
|
||||
|
||||
get_intruders(ring, left, right, extremes, intruders);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static inline bool right_turn(Ring const& ring, Iterator it)
|
||||
{
|
||||
typename std::iterator_traits<Iterator>::difference_type const index
|
||||
= std::distance(boost::begin(ring), it);
|
||||
geometry::ever_circling_range_iterator<Ring const> left(ring);
|
||||
geometry::ever_circling_range_iterator<Ring const> right(ring);
|
||||
left += index;
|
||||
right += index;
|
||||
|
||||
if (! extent_both_sides(ring, *it, left, right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
|
||||
int const first_side = side_strategy::apply(*(right - 1), *right, *left) * factor;
|
||||
int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor;
|
||||
|
||||
//std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl;
|
||||
|
||||
// Turn should not be left (actually, it should be right because extent removes horizontal/collinear cases)
|
||||
return first_side != 1 && last_side != 1;
|
||||
}
|
||||
|
||||
|
||||
// Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders)
|
||||
{
|
||||
std::size_t const n = boost::size(ring);
|
||||
if (n < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all maxima, usually one. In case of self-tangencies, or self-crossings,
|
||||
// the max might be is not valid. A valid max should make a right turn
|
||||
range_iterator max_it = boost::begin(ring);
|
||||
compare<Dimension> smaller;
|
||||
for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)
|
||||
{
|
||||
if (smaller(*max_it, *it) && right_turn(ring, it))
|
||||
{
|
||||
max_it = it;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_it == boost::end(ring))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typename std::iterator_traits<range_iterator>::difference_type const
|
||||
index = std::distance(boost::begin(ring), max_it);
|
||||
//std::cout << "Extreme point lies at " << index << " having " << geometry::wkt(*max_it) << std::endl;
|
||||
|
||||
geometry::ever_circling_range_iterator<Ring const> left(ring);
|
||||
geometry::ever_circling_range_iterator<Ring const> right(ring);
|
||||
left += index;
|
||||
right += index;
|
||||
|
||||
// Collect all points (often 3) in a temporary vector
|
||||
std::vector<point_type> points;
|
||||
points.reserve(3);
|
||||
if (! collect(ring, *max_it, points, left, right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//std::cout << "Built vector of " << points.size() << std::endl;
|
||||
|
||||
coordinate_type const front_value = geometry::get<Dimension>(points.front());
|
||||
coordinate_type const back_value = geometry::get<Dimension>(points.back());
|
||||
coordinate_type const base_value = (std::max)(front_value, back_value);
|
||||
if (front_value < back_value)
|
||||
{
|
||||
move_along_vector<Dimension>(points.front(), *(points.begin() + 1), base_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
move_along_vector<Dimension>(points.back(), *(points.rbegin() + 1), base_value);
|
||||
}
|
||||
|
||||
std::copy(points.begin(), points.end(), std::back_inserter(extremes));
|
||||
|
||||
get_intruders(ring, left, right, extremes, intruders);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::extreme_points
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
std::size_t Dimension,
|
||||
typename GeometryTag = typename tag<Geometry>::type
|
||||
>
|
||||
struct extreme_points
|
||||
{};
|
||||
|
||||
|
||||
template<typename Ring, std::size_t Dimension>
|
||||
struct extreme_points<Ring, Dimension, ring_tag>
|
||||
: detail::extreme_points::extreme_points_on_ring<Ring, Dimension>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Polygon, std::size_t Dimension>
|
||||
struct extreme_points<Polygon, Dimension, polygon_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders)
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
typedef detail::extreme_points::extreme_points_on_ring
|
||||
<
|
||||
ring_type, Dimension
|
||||
> ring_implementation;
|
||||
|
||||
if (! ring_implementation::apply(geometry::exterior_ring(polygon), extremes, intruders))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For a polygon, its interior rings can contain intruders
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(polygon);
|
||||
for (typename detail::interior_iterator<Polygon const>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
ring_implementation::get_intruders(*it, extremes, intruders);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Box>
|
||||
struct extreme_points<Box, 1, box_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
|
||||
{
|
||||
extremes.resize(4);
|
||||
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
|
||||
// ll,ul,ur,lr, contains too exactly the right info
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Box>
|
||||
struct extreme_points<Box, 0, box_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
|
||||
{
|
||||
extremes.resize(4);
|
||||
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
|
||||
// ll,ul,ur,lr, rotate one to start with UL and end with LL
|
||||
std::rotate(extremes.begin(), extremes.begin() + 1, extremes.end());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MultiPolygon, std::size_t Dimension>
|
||||
struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders)
|
||||
{
|
||||
// Get one for the very first polygon, that is (for the moment) enough.
|
||||
// It is not guaranteed the "extreme" then, but for the current purpose
|
||||
// (point_on_surface) it can just be this point.
|
||||
if (boost::size(multi) >= 1)
|
||||
{
|
||||
return extreme_points
|
||||
<
|
||||
typename boost::range_value<MultiPolygon const>::type,
|
||||
Dimension,
|
||||
polygon_tag
|
||||
>::apply(*boost::begin(multi), extremes, intruders);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns extreme points (for Edge=1 in dimension 1, so the top,
|
||||
for Edge=0 in dimension 0, the right side)
|
||||
\note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that.
|
||||
*/
|
||||
template <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders>
|
||||
inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// Extremes is not required to follow a geometry concept (but it should support an output iterator),
|
||||
// but its elements should fulfil the point-concept
|
||||
concepts::check<typename boost::range_value<Extremes>::type>();
|
||||
|
||||
// Intruders should contain collections which value type is point-concept
|
||||
// Extremes might be anything (supporting an output iterator), but its elements should fulfil the point-concept
|
||||
concepts::check
|
||||
<
|
||||
typename boost::range_value
|
||||
<
|
||||
typename boost::range_value<Intruders>::type
|
||||
>::type
|
||||
const
|
||||
>();
|
||||
|
||||
return dispatch::extreme_points<Geometry, Edge>::apply(geometry, extremes, intruders);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXTREME_POINTS_HPP
|
||||
+201
@@ -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
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/iterators/closing_iterator.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// TODO: move this to /util/
|
||||
template <typename T>
|
||||
inline std::pair<T, T> ordered_pair(T const& first, T const& second)
|
||||
{
|
||||
return first < second ? std::make_pair(first, second) : std::make_pair(second, first);
|
||||
}
|
||||
|
||||
namespace left_turns
|
||||
{
|
||||
|
||||
|
||||
|
||||
template <typename Vector>
|
||||
inline int get_quadrant(Vector const& vector)
|
||||
{
|
||||
// Return quadrant as layouted in the code below:
|
||||
// 3 | 0
|
||||
// -----
|
||||
// 2 | 1
|
||||
return geometry::get<1>(vector) >= 0
|
||||
? (geometry::get<0>(vector) < 0 ? 3 : 0)
|
||||
: (geometry::get<0>(vector) < 0 ? 2 : 1)
|
||||
;
|
||||
}
|
||||
|
||||
template <typename Vector>
|
||||
inline int squared_length(Vector const& vector)
|
||||
{
|
||||
return geometry::get<0>(vector) * geometry::get<0>(vector)
|
||||
+ geometry::get<1>(vector) * geometry::get<1>(vector)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct angle_less
|
||||
{
|
||||
typedef Point vector_type;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
angle_less(Point const& origin)
|
||||
: m_origin(origin)
|
||||
{}
|
||||
|
||||
template <typename Angle>
|
||||
inline bool operator()(Angle const& p, Angle const& q) const
|
||||
{
|
||||
// Vector origin -> p and origin -> q
|
||||
vector_type pv = p.point;
|
||||
vector_type qv = q.point;
|
||||
geometry::subtract_point(pv, m_origin);
|
||||
geometry::subtract_point(qv, m_origin);
|
||||
|
||||
int const quadrant_p = get_quadrant(pv);
|
||||
int const quadrant_q = get_quadrant(qv);
|
||||
if (quadrant_p != quadrant_q)
|
||||
{
|
||||
return quadrant_p < quadrant_q;
|
||||
}
|
||||
// Same quadrant, check if p is located left of q
|
||||
int const side = side_strategy_type::apply(m_origin, q.point,
|
||||
p.point);
|
||||
if (side != 0)
|
||||
{
|
||||
return side == 1;
|
||||
}
|
||||
// Collinear, check if one is incoming, incoming angles come first
|
||||
if (p.incoming != q.incoming)
|
||||
{
|
||||
return int(p.incoming) < int(q.incoming);
|
||||
}
|
||||
// Same quadrant/side/direction, return longest first
|
||||
// TODO: maybe not necessary, decide this
|
||||
int const length_p = squared_length(pv);
|
||||
int const length_q = squared_length(qv);
|
||||
if (length_p != length_q)
|
||||
{
|
||||
return squared_length(pv) > squared_length(qv);
|
||||
}
|
||||
// They are still the same. Just compare on seg_id
|
||||
return p.seg_id < q.seg_id;
|
||||
}
|
||||
|
||||
private:
|
||||
Point m_origin;
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct angle_equal_to
|
||||
{
|
||||
typedef Point vector_type;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
inline angle_equal_to(Point const& origin)
|
||||
: m_origin(origin)
|
||||
{}
|
||||
|
||||
template <typename Angle>
|
||||
inline bool operator()(Angle const& p, Angle const& q) const
|
||||
{
|
||||
// Vector origin -> p and origin -> q
|
||||
vector_type pv = p.point;
|
||||
vector_type qv = q.point;
|
||||
geometry::subtract_point(pv, m_origin);
|
||||
geometry::subtract_point(qv, m_origin);
|
||||
|
||||
if (get_quadrant(pv) != get_quadrant(qv))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Same quadrant, check if p/q are collinear
|
||||
int const side = side_strategy_type::apply(m_origin, q.point,
|
||||
p.point);
|
||||
return side == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Point m_origin;
|
||||
};
|
||||
|
||||
template <typename AngleCollection, typename Turns>
|
||||
inline void get_left_turns(AngleCollection const& sorted_angles,
|
||||
Turns& turns)
|
||||
{
|
||||
std::set<std::size_t> good_incoming;
|
||||
std::set<std::size_t> good_outgoing;
|
||||
|
||||
for (typename boost::range_iterator<AngleCollection const>::type it =
|
||||
sorted_angles.begin(); it != sorted_angles.end(); ++it)
|
||||
{
|
||||
if (!it->blocked)
|
||||
{
|
||||
if (it->incoming)
|
||||
{
|
||||
good_incoming.insert(it->turn_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
good_outgoing.insert(it->turn_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (good_incoming.empty() || good_outgoing.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (typename boost::range_iterator<AngleCollection const>::type it =
|
||||
sorted_angles.begin(); it != sorted_angles.end(); ++it)
|
||||
{
|
||||
if (good_incoming.count(it->turn_index) == 0
|
||||
|| good_outgoing.count(it->turn_index) == 0)
|
||||
{
|
||||
turns[it->turn_index].remove_on_multi = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns the number of clusters
|
||||
template <typename Point, typename AngleCollection>
|
||||
inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin)
|
||||
{
|
||||
// Assign same cluster_index for all turns in same direction
|
||||
BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u);
|
||||
|
||||
angle_equal_to<Point> comparator(origin);
|
||||
typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
|
||||
|
||||
std::size_t cluster_index = 0;
|
||||
it->cluster_index = cluster_index;
|
||||
typename boost::range_iterator<AngleCollection>::type previous = it++;
|
||||
for (; it != sorted.end(); ++it)
|
||||
{
|
||||
if (!comparator(*previous, *it))
|
||||
{
|
||||
cluster_index++;
|
||||
previous = it;
|
||||
}
|
||||
it->cluster_index = cluster_index;
|
||||
}
|
||||
return cluster_index + 1;
|
||||
}
|
||||
|
||||
template <typename AngleCollection>
|
||||
inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u && cluster_size > 0);
|
||||
|
||||
std::vector<std::pair<bool, bool> > directions;
|
||||
for (std::size_t i = 0; i < cluster_size; i++)
|
||||
{
|
||||
directions.push_back(std::make_pair(false, false));
|
||||
}
|
||||
|
||||
for (typename boost::range_iterator<AngleCollection const>::type it = sorted.begin();
|
||||
it != sorted.end(); ++it)
|
||||
{
|
||||
if (it->incoming)
|
||||
{
|
||||
directions[it->cluster_index].first = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
directions[it->cluster_index].second = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
|
||||
it != sorted.end(); ++it)
|
||||
{
|
||||
signed_size_type cluster_index = static_cast<signed_size_type>(it->cluster_index);
|
||||
signed_size_type previous_index = cluster_index - 1;
|
||||
if (previous_index < 0)
|
||||
{
|
||||
previous_index = cluster_size - 1;
|
||||
}
|
||||
signed_size_type next_index = cluster_index + 1;
|
||||
if (next_index >= static_cast<signed_size_type>(cluster_size))
|
||||
{
|
||||
next_index = 0;
|
||||
}
|
||||
|
||||
if (directions[cluster_index].first
|
||||
&& directions[cluster_index].second)
|
||||
{
|
||||
it->blocked = true;
|
||||
}
|
||||
else if (!directions[cluster_index].first
|
||||
&& directions[cluster_index].second
|
||||
&& directions[previous_index].second)
|
||||
{
|
||||
// Only outgoing, previous was also outgoing: block this one
|
||||
it->blocked = true;
|
||||
}
|
||||
else if (directions[cluster_index].first
|
||||
&& !directions[cluster_index].second
|
||||
&& !directions[previous_index].first
|
||||
&& directions[previous_index].second)
|
||||
{
|
||||
// Only incoming, previous was only outgoing: block this one
|
||||
it->blocked = true;
|
||||
}
|
||||
else if (directions[cluster_index].first
|
||||
&& !directions[cluster_index].second
|
||||
&& directions[next_index].first
|
||||
&& !directions[next_index].second)
|
||||
{
|
||||
// Only incoming, next also incoming, block this one
|
||||
it->blocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
|
||||
template <typename AngleCollection, typename Point>
|
||||
inline bool has_rounding_issues(AngleCollection const& angles, Point const& origin)
|
||||
{
|
||||
for (typename boost::range_iterator<AngleCollection const>::type it =
|
||||
angles.begin(); it != angles.end(); ++it)
|
||||
{
|
||||
// Vector origin -> p and origin -> q
|
||||
typedef Point vector_type;
|
||||
vector_type v = it->point;
|
||||
geometry::subtract_point(v, origin);
|
||||
return geometry::math::abs(geometry::get<0>(v)) <= 1
|
||||
|| geometry::math::abs(geometry::get<1>(v)) <= 1
|
||||
;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace left_turns
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
|
||||
@@ -0,0 +1,64 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Box, std::size_t Dimension>
|
||||
struct get_max_size_box
|
||||
{
|
||||
static inline typename coordinate_type<Box>::type apply(Box const& box)
|
||||
{
|
||||
typename coordinate_type<Box>::type s
|
||||
= geometry::math::abs(geometry::get<1, Dimension>(box) - geometry::get<0, Dimension>(box));
|
||||
|
||||
return (std::max)(s, get_max_size_box<Box, Dimension - 1>::apply(box));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct get_max_size_box<Box, 0>
|
||||
{
|
||||
static inline typename coordinate_type<Box>::type apply(Box const& box)
|
||||
{
|
||||
return geometry::math::abs(geometry::get<1, 0>(box) - geometry::get<0, 0>(box));
|
||||
}
|
||||
};
|
||||
|
||||
// This might be implemented later on for other geometries too.
|
||||
// Not dispatched yet.
|
||||
template <typename Box>
|
||||
inline typename coordinate_type<Box>::type get_max_size(Box const& box)
|
||||
{
|
||||
return get_max_size_box<Box, dimension<Box>::value - 1>::apply(box);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
|
||||
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
|
||||
# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
|
||||
# include <boost/geometry/io/dsv/write.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
|
||||
|
||||
/*!
|
||||
\brief Overlay Invalid Input Exception
|
||||
\ingroup overlay
|
||||
\details The overlay_invalid_input_exception is thrown at invalid input
|
||||
*/
|
||||
class overlay_invalid_input_exception : public geometry::exception
|
||||
{
|
||||
public:
|
||||
|
||||
inline overlay_invalid_input_exception() {}
|
||||
|
||||
virtual char const* what() const throw()
|
||||
{
|
||||
return "Boost.Geometry Overlay invalid input exception";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, typename Strategy, typename RobustPolicy>
|
||||
inline bool has_self_intersections(Geometry const& geometry,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
bool throw_on_self_intersection = true)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef turn_info
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::deque<turn_info> turns;
|
||||
detail::disjoint::disjoint_interrupt_policy policy;
|
||||
|
||||
geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
|
||||
bool first = true;
|
||||
#endif
|
||||
for(typename std::deque<turn_info>::const_iterator it = boost::begin(turns);
|
||||
it != boost::end(turns); ++it)
|
||||
{
|
||||
turn_info const& info = *it;
|
||||
bool const both_union_turn =
|
||||
info.operations[0].operation == detail::overlay::operation_union
|
||||
&& info.operations[1].operation == detail::overlay::operation_union;
|
||||
bool const both_intersection_turn =
|
||||
info.operations[0].operation == detail::overlay::operation_intersection
|
||||
&& info.operations[1].operation == detail::overlay::operation_intersection;
|
||||
|
||||
bool const valid = (both_union_turn || both_intersection_turn)
|
||||
&& (info.method == detail::overlay::method_touch
|
||||
|| info.method == detail::overlay::method_touch_interior);
|
||||
|
||||
if (! valid)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
|
||||
if (first)
|
||||
{
|
||||
std::cout << "turn points: " << std::endl;
|
||||
first = false;
|
||||
}
|
||||
std::cout << method_char(info.method);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
std::cout << " " << operation_char(info.operations[i].operation);
|
||||
std::cout << " " << info.operations[i].seg_id;
|
||||
}
|
||||
std::cout << " " << geometry::dsv(info.point) << std::endl;
|
||||
#endif
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
|
||||
if (throw_on_self_intersection)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(overlay_invalid_input_exception());
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// For backward compatibility
|
||||
template <typename Geometry>
|
||||
inline bool has_self_intersections(Geometry const& geometry,
|
||||
bool throw_on_self_intersection = true)
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef typename geometry::rescale_policy_type<point_type>::type
|
||||
rescale_policy_type;
|
||||
|
||||
typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
|
||||
|
||||
return has_self_intersections(geometry, strategy, robust_policy,
|
||||
throw_on_self_intersection);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP
|
||||
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/interior_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Structure defining the type of interior rings iterator
|
||||
\note If the Geometry is const, const iterator is defined.
|
||||
\tparam Geometry \tparam_geometry
|
||||
*/
|
||||
template <typename Geometry>
|
||||
struct interior_iterator
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
typename geometry::interior_type<Geometry>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename BaseT, typename T>
|
||||
struct copy_const
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename BaseT, typename T>
|
||||
struct copy_const<BaseT const, T>
|
||||
{
|
||||
typedef T const type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct interior_ring_iterator
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
typename copy_const
|
||||
<
|
||||
typename geometry::interior_type<Geometry>::type,
|
||||
typename boost::range_value
|
||||
<
|
||||
typename geometry::interior_type<Geometry>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERIOR_ITERATOR_HPP
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2, bool Reverse
|
||||
>
|
||||
struct intersection
|
||||
<
|
||||
Box1, Box2,
|
||||
box_tag, box_tag,
|
||||
Reverse
|
||||
> : public detail::intersection::intersection_box_box
|
||||
<
|
||||
0, geometry::dimension<Box1>::value
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_BOX_BOX_HPP
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/intersection/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/intersection/multi.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_IMPLEMENTATION_HPP
|
||||
+398
@@ -0,0 +1,398 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2017.
|
||||
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
// By default, all is forwarded to the intersection_insert-dispatcher
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type,
|
||||
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
|
||||
>
|
||||
struct intersection
|
||||
{
|
||||
template <typename RobustPolicy, typename GeometryOut, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<GeometryOut>::type OneOut;
|
||||
|
||||
intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2, OneOut,
|
||||
overlay_intersection
|
||||
>::apply(geometry1, geometry2, robust_policy,
|
||||
range::back_inserter(geometry_out), strategy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// If reversal is needed, perform it
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1, typename Tag2
|
||||
>
|
||||
struct intersection
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
Tag1, Tag2,
|
||||
true
|
||||
>
|
||||
: intersection<Geometry2, Geometry1, Tag2, Tag1, false>
|
||||
{
|
||||
template <typename RobustPolicy, typename GeometryOut, typename Strategy>
|
||||
static inline bool apply(
|
||||
Geometry1 const& g1,
|
||||
Geometry2 const& g2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry2, Geometry1,
|
||||
Tag2, Tag1,
|
||||
false
|
||||
>::apply(g2, g1, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct intersection
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename GeometryOut,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut & geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, robust_policy, geometry_out,
|
||||
strategy);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename GeometryOut
|
||||
>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
GeometryOut & geometry_out,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, robust_policy, geometry_out,
|
||||
strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct intersection
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename geometry::rescale_overlay_policy_type
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type rescale_policy_type;
|
||||
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry1,
|
||||
geometry2);
|
||||
|
||||
return resolve_strategy::intersection::apply(geometry1,
|
||||
geometry2,
|
||||
robust_policy,
|
||||
geometry_out,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
GeometryOut& m_geometry_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_geometry_out(geometry_out)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
bool operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
|
||||
geometry_out,
|
||||
strategy),
|
||||
geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
GeometryOut& m_geometry_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_geometry_out(geometry_out)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
bool operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool
|
||||
apply(Geometry1 const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
|
||||
geometry_out,
|
||||
strategy),
|
||||
geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
GeometryOut& m_geometry_out;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(GeometryOut& geometry_out, Strategy const& strategy)
|
||||
: m_geometry_out(geometry_out)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
bool operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, m_geometry_out, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename GeometryOut, typename Strategy>
|
||||
static inline bool
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
|
||||
strategy),
|
||||
geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{intersection}
|
||||
\ingroup intersection
|
||||
\details \details_calc2{intersection, spatial set theoretic intersection}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
|
||||
the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
|
||||
\tparam Strategy \tparam_strategy{Intersection}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param geometry_out The output geometry, either a multi_point, multi_polygon,
|
||||
multi_linestring, or a box (for intersection of two boxes)
|
||||
\param strategy \param_strategy{intersection}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/intersection.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename GeometryOut,
|
||||
typename Strategy
|
||||
>
|
||||
inline bool intersection(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, geometry_out, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{intersection}
|
||||
\ingroup intersection
|
||||
\details \details_calc2{intersection, spatial set theoretic intersection}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
|
||||
the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param geometry_out The output geometry, either a multi_point, multi_polygon,
|
||||
multi_linestring, or a box (for intersection of two boxes)
|
||||
|
||||
\qbk{[include reference/algorithms/intersection.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename GeometryOut
|
||||
>
|
||||
inline bool intersection(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
GeometryOut& geometry_out)
|
||||
{
|
||||
return resolve_variant::intersection
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, geometry_out, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
|
||||
+421
@@ -0,0 +1,421 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/geometry_id.hpp>
|
||||
#include <boost/geometry/core/is_areal.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
// TODO: those headers probably may be removed
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/num_points.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace intersection
|
||||
{
|
||||
|
||||
|
||||
template <typename PointOut>
|
||||
struct intersection_multi_linestring_multi_linestring_point
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiLinestring1, typename MultiLinestring2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(MultiLinestring1 const& ml1,
|
||||
MultiLinestring2 const& ml2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// Note, this loop is quadratic w.r.t. number of linestrings per input.
|
||||
// Future Enhancement: first do the sections of each, then intersect.
|
||||
for (typename boost::range_iterator
|
||||
<
|
||||
MultiLinestring1 const
|
||||
>::type it1 = boost::begin(ml1);
|
||||
it1 != boost::end(ml1);
|
||||
++it1)
|
||||
{
|
||||
for (typename boost::range_iterator
|
||||
<
|
||||
MultiLinestring2 const
|
||||
>::type it2 = boost::begin(ml2);
|
||||
it2 != boost::end(ml2);
|
||||
++it2)
|
||||
{
|
||||
out = intersection_linestring_linestring_point<PointOut>
|
||||
::apply(*it1, *it2, robust_policy, out, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename PointOut>
|
||||
struct intersection_linestring_multi_linestring_point
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Linestring, typename MultiLinestring,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Linestring const& linestring,
|
||||
MultiLinestring const& ml,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
for (typename boost::range_iterator
|
||||
<
|
||||
MultiLinestring const
|
||||
>::type it = boost::begin(ml);
|
||||
it != boost::end(ml);
|
||||
++it)
|
||||
{
|
||||
out = intersection_linestring_linestring_point<PointOut>
|
||||
::apply(linestring, *it, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// This loop is quite similar to the loop above, but beacuse the iterator
|
||||
// is second (above) or first (below) argument, it is not trivial to merge them.
|
||||
template
|
||||
<
|
||||
bool ReverseAreal,
|
||||
typename LineStringOut,
|
||||
overlay_type OverlayType
|
||||
>
|
||||
struct intersection_of_multi_linestring_with_areal
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Areal,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
for (typename boost::range_iterator
|
||||
<
|
||||
MultiLinestring const
|
||||
>::type it = boost::begin(ml);
|
||||
it != boost::end(ml);
|
||||
++it)
|
||||
{
|
||||
out = intersection_of_linestring_with_areal
|
||||
<
|
||||
ReverseAreal, LineStringOut, OverlayType
|
||||
>::apply(*it, areal, robust_policy, out, strategy);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// This one calls the one above with reversed arguments
|
||||
template
|
||||
<
|
||||
bool ReverseAreal,
|
||||
typename LineStringOut,
|
||||
overlay_type OverlayType
|
||||
>
|
||||
struct intersection_of_areal_with_multi_linestring
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Areal, typename MultiLinestring,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseAreal, LineStringOut, OverlayType
|
||||
>::apply(ml, areal, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename LinestringOut>
|
||||
struct clip_multi_linestring
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Box,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator, typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(MultiLinestring const& multi_linestring,
|
||||
Box const& box,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out, Strategy const& )
|
||||
{
|
||||
typedef typename point_type<LinestringOut>::type point_type;
|
||||
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
||||
for (typename boost::range_iterator<MultiLinestring const>::type it
|
||||
= boost::begin(multi_linestring);
|
||||
it != boost::end(multi_linestring); ++it)
|
||||
{
|
||||
out = detail::intersection::clip_range_with_box
|
||||
<LinestringOut>(box, *it, robust_policy, out, lb_strategy);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::intersection
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// Linear
|
||||
template
|
||||
<
|
||||
typename MultiLinestring1, typename MultiLinestring2,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
MultiLinestring1, MultiLinestring2,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_linestring_tag, multi_linestring_tag, point_tag,
|
||||
false, false, false
|
||||
> : detail::intersection::intersection_multi_linestring_multi_linestring_point
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Linestring, typename MultiLinestring,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Linestring, MultiLinestring,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
linestring_tag, multi_linestring_tag, point_tag,
|
||||
false, false, false
|
||||
> : detail::intersection::intersection_linestring_multi_linestring_point
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Box,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
MultiLinestring, Box,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_linestring_tag, box_tag, linestring_tag,
|
||||
false, true, false
|
||||
> : detail::intersection::clip_multi_linestring
|
||||
<
|
||||
GeometryOut
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Linestring, typename MultiPolygon,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Linestring, MultiPolygon,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
ReverseLinestring, ReverseMultiPolygon, ReverseOut,
|
||||
linestring_tag, multi_polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
> : detail::intersection::intersection_of_linestring_with_areal
|
||||
<
|
||||
ReverseMultiPolygon,
|
||||
GeometryOut,
|
||||
OverlayType
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
// Derives from areal/mls because runtime arguments are in that order.
|
||||
// areal/mls reverses it itself to mls/areal
|
||||
template
|
||||
<
|
||||
typename Polygon, typename MultiLinestring,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Polygon, MultiLinestring,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
ReversePolygon, ReverseMultiLinestring, ReverseOut,
|
||||
polygon_tag, multi_linestring_tag, linestring_tag,
|
||||
true, false, false
|
||||
> : detail::intersection::intersection_of_areal_with_multi_linestring
|
||||
<
|
||||
ReversePolygon,
|
||||
GeometryOut,
|
||||
OverlayType
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Ring,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
MultiLinestring, Ring,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
ReverseMultiLinestring, ReverseRing, ReverseOut,
|
||||
multi_linestring_tag, ring_tag, linestring_tag,
|
||||
false, true, false
|
||||
> : detail::intersection::intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseRing,
|
||||
GeometryOut,
|
||||
OverlayType
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename Polygon,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
MultiLinestring, Polygon,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
ReverseMultiLinestring, ReverseRing, ReverseOut,
|
||||
multi_linestring_tag, polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
> : detail::intersection::intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseRing,
|
||||
GeometryOut,
|
||||
OverlayType
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiLinestring, typename MultiPolygon,
|
||||
typename GeometryOut,
|
||||
overlay_type OverlayType,
|
||||
bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
MultiLinestring, MultiPolygon,
|
||||
GeometryOut,
|
||||
OverlayType,
|
||||
ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut,
|
||||
multi_linestring_tag, multi_polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
> : detail::intersection::intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseMultiPolygon,
|
||||
GeometryOut,
|
||||
OverlayType
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_MULTI_HPP
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/is_simple.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace is_simple
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct always_simple
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry const&, Strategy const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::is_simple
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// A point is always simple
|
||||
template <typename Point>
|
||||
struct is_simple<Point, point_tag>
|
||||
: detail::is_simple::always_simple<Point>
|
||||
{};
|
||||
|
||||
|
||||
// A valid segment is always simple.
|
||||
// A segment is a curve.
|
||||
// A curve is simple if it does not pass through the same point twice,
|
||||
// with the possible exception of its two endpoints
|
||||
//
|
||||
// Reference: OGC 06-103r4 (6.1.6.1)
|
||||
template <typename Segment>
|
||||
struct is_simple<Segment, segment_tag>
|
||||
: detail::is_simple::always_simple<Segment>
|
||||
{};
|
||||
|
||||
|
||||
// A valid box is always simple
|
||||
// A box is a Polygon, and it satisfies the conditions for Polygon validity.
|
||||
//
|
||||
// Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)
|
||||
template <typename Box>
|
||||
struct is_simple<Box, box_tag>
|
||||
: detail::is_simple::always_simple<Box>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_ALWAYS_SIMPLE_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user