%PDF- %PDF-
| Direktori : /backups/router/usr/local/include/boost/geometry/algorithms/detail/distance/ |
| Current File : //backups/router/usr/local/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp |
// 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-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
#include <iterator>
#include <type_traits>
#include <boost/core/ignore_unused.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/dispatch/distance.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/strategies/distance.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template
<
typename P1, typename P2, typename Strategies,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
>
struct point_to_point
{
static inline
auto apply(P1 const& p1, P2 const& p2, Strategies const& strategies)
{
boost::ignore_unused(strategies);
return strategies.distance(p1, p2).apply(p1, p2);
}
};
// TEMP?
// called by geometry_to_range
template <typename P1, typename P2, typename Strategy>
struct point_to_point<P1, P2, Strategy, false>
{
static inline
auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
{
boost::ignore_unused(strategy);
return strategy.apply(p1, p2);
}
};
template
<
typename Point, typename Segment, typename Strategies,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
>
struct point_to_segment
{
static inline auto apply(Point const& point, Segment const& segment,
Strategies const& strategies)
{
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(strategies);
return strategies.distance(point, segment).apply(point, p[0], p[1]);
}
};
// TEMP?
// called by geometry_to_range
template <typename Point, typename Segment, typename Strategy>
struct point_to_segment<Point, Segment, Strategy, false>
{
static inline auto 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 Strategies,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
>
struct point_to_box
{
static inline auto apply(Point const& point, Box const& box,
Strategies const& strategies)
{
boost::ignore_unused(strategies);
return strategies.distance(point, box).apply(point, box);
}
};
// TEMP?
// called by geometry_to_range
template <typename Point, typename Box, typename Strategy>
struct point_to_box<Point, Box, Strategy, false>
{
static inline auto apply(Point const& point, Box const& box,
Strategy const& strategy)
{
boost::ignore_unused(strategy);
return strategy.apply(point, box);
}
};
template
<
typename Point,
typename Range,
closure_selector Closure,
typename Strategies
>
class point_to_range
{
private:
typedef distance::strategy_t<Point, Range, Strategies> strategy_type;
typedef detail::closest_feature::point_to_point_range
<
Point, Range, Closure
> point_to_point_range;
public:
typedef distance::return_t<Point, Range, Strategies> return_type;
static inline return_type apply(Point const& point, Range const& range,
Strategies const& strategies)
{
if (boost::size(range) == 0)
{
return return_type(0);
}
distance::creturn_t<Point, Range, Strategies> 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),
strategy::distance::services::get_comparable
<
strategy_type
>::apply(strategies.distance(point, range)),
cd_min);
return
is_comparable<strategy_type>::value
?
cd_min
:
strategies.distance(point, range).apply(point, *it_pair.first, *it_pair.second);
}
};
template
<
typename Point,
typename Ring,
closure_selector Closure,
typename Strategies
>
struct point_to_ring
{
typedef distance::return_t<Point, Ring, Strategies> return_type;
static inline return_type apply(Point const& point,
Ring const& ring,
Strategies const& strategies)
{
if (within::within_point_geometry(point, ring, strategies))
{
return return_type(0);
}
return point_to_range
<
Point, Ring, closure<Ring>::value, Strategies
>::apply(point, ring, strategies);
}
};
template
<
typename Point,
typename Polygon,
closure_selector Closure,
typename Strategies
>
class point_to_polygon
{
public:
typedef distance::return_t<Point, Polygon, Strategies> return_type;
private:
typedef point_to_range
<
Point, typename ring_type<Polygon>::type, Closure, Strategies
> per_ring;
struct distance_to_interior_rings
{
template <typename InteriorRingIterator>
static inline return_type apply(Point const& point,
InteriorRingIterator first,
InteriorRingIterator last,
Strategies const& strategies)
{
for (InteriorRingIterator it = first; it != last; ++it)
{
if (within::within_point_geometry(point, *it, strategies))
{
// 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, strategies);
}
}
return return_type(0);
}
template <typename InteriorRings>
static inline return_type apply(Point const& point, InteriorRings const& interior_rings,
Strategies const& strategies)
{
return apply(point,
boost::begin(interior_rings),
boost::end(interior_rings),
strategies);
}
};
public:
static inline return_type apply(Point const& point,
Polygon const& polygon,
Strategies const& strategies)
{
if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
strategies))
{
// 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), strategies);
}
// Check interior rings
return distance_to_interior_rings::apply(point,
interior_rings(polygon),
strategies);
}
};
template
<
typename Point,
typename MultiGeometry,
typename Strategies,
bool CheckCoveredBy = std::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;
typedef distance::strategy_t<Point, MultiGeometry, Strategies> strategy_type;
public:
typedef distance::return_t<Point, MultiGeometry, Strategies> return_type;
static inline return_type apply(Point const& point,
MultiGeometry const& multigeometry,
Strategies const& strategies)
{
typedef iterator_selector<MultiGeometry const> selector_type;
distance::creturn_t<Point, MultiGeometry, Strategies> cd;
typename selector_type::iterator_type it_min
= geometry_to_range::apply(point,
selector_type::begin(multigeometry),
selector_type::end(multigeometry),
strategy::distance::services::get_comparable
<
strategy_type
>::apply(strategies.distance(point, multigeometry)),
cd);
// TODO - It would be possible to use a tool similar to result_from_distance
// but working in the opposite way, i.e. calculating the distance
// value from comparable distance value. This way the additional distance
// call would not be needed.
return
is_comparable<strategy_type>::value
?
cd
:
dispatch::distance
<
Point,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type,
Strategies
>::apply(point, *it_min, strategies);
}
};
// this is called only for multipolygons, hence the change in the
// template parameter name MultiGeometry to MultiPolygon
template <typename Point, typename MultiPolygon, typename Strategies>
struct point_to_multigeometry<Point, MultiPolygon, Strategies, true>
{
typedef distance::return_t<Point, MultiPolygon, Strategies> return_type;
static inline return_type apply(Point const& point,
MultiPolygon const& multipolygon,
Strategies const& strategies)
{
if (within::covered_by_point_geometry(point, multipolygon, strategies))
{
return return_type(0);
}
return point_to_multigeometry
<
Point, MultiPolygon, Strategies, false
>::apply(point, multipolygon, strategies);
}
};
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
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>
{};
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>
{};
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
>
{};
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
>
{};
template <typename Point, typename Segment, typename Strategy>
struct distance
<
Point, Segment, Strategy, point_tag, segment_tag,
strategy_tag_distance_point_segment, false
> : detail::distance::point_to_segment<Point, Segment, Strategy>
{};
template <typename Point, typename Box, typename Strategy>
struct distance
<
Point, Box, Strategy, point_tag, box_tag,
strategy_tag_distance_point_box, false
> : detail::distance::point_to_box<Point, Box, Strategy>
{};
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