123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- // 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
|