Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
@@ -0,0 +1,28 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
#include <boost/geometry/algorithms/detail/distance/implementation.hpp>
#include <boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp>
//#include <boost/geometry/algorithms/detail/closest_points/linear_to_box.hpp>
//#include <boost/geometry/algorithms/detail/closest_points/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp>
//#include <boost/geometry/algorithms/detail/closest_points/segment_to_box.hpp>
//#include <boost/geometry/algorithms/detail/closest_points/box_to_box.hpp>
#include <boost/geometry/strategies/closest_points/cartesian.hpp>
#include <boost/geometry/strategies/closest_points/geographic.hpp>
#include <boost/geometry/strategies/closest_points/spherical.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
@@ -0,0 +1,225 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
#include <boost/concept_check.hpp>
#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/closest_points/services.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// If reversal is needed, perform it
template
<
typename Geometry1,
typename Geometry2,
typename Tag1,
typename Tag2
>
struct closest_points
<
Geometry1, Geometry2,
Tag1, Tag2, true
>
: closest_points<Geometry2, Geometry1, Tag2, Tag1, false>
{
template <typename Segment, typename Strategy>
static inline void apply(Geometry1 const& g1, Geometry2 const& g2,
Segment& shortest_seg, Strategy const& strategy)
{
closest_points
<
Geometry2, Geometry1, Tag2, Tag1, false
>::apply(g2, g1, shortest_seg, strategy);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
template<typename Strategy>
struct closest_points
{
template <typename Geometry1, typename Geometry2, typename Segment>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Segment& shortest_seg,
Strategy const& strategy)
{
dispatch::closest_points
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, shortest_seg, strategy);
}
};
template <>
struct closest_points<default_strategy>
{
template <typename Geometry1, typename Geometry2, typename Segment>
static inline void
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Segment& shortest_seg,
default_strategy)
{
using strategy_type = typename strategies::closest_points::services::default_strategy
<
Geometry1, Geometry2
>::type;
dispatch::closest_points
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, shortest_seg, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct closest_points
{
template <typename Segment, typename Strategy>
static inline void apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Segment& shortest_seg,
Strategy const& strategy)
{
resolve_strategy::closest_points
<
Strategy
>::apply(geometry1, geometry2, shortest_seg, strategy);
}
};
//TODO: Add support for DG/GC
} // namespace resolve_variant
/*!
\brief Calculate the closest points between two geometries \brief_strategy
\ingroup closest_points
\details
\details The free function closest_points calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Segment Any type fulfilling a Segment Concept
\tparam Strategy \tparam_strategy{Closest Points}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param shortest_seg Output segment containing the closest points
\param strategy \param_strategy{closest_points}
\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 Example]
[closest_points_strategy]
[closest_points_strategy_output]
[heading See also]
\* [link geometry.reference.algorithms.distance distance]
}
*/
template <typename Geometry1, typename Geometry2, typename Segment, typename Strategy>
inline void closest_points(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Segment& shortest_seg,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
detail::throw_on_empty_input(geometry1);
detail::throw_on_empty_input(geometry2);
resolve_variant::closest_points
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, shortest_seg, strategy);
}
/*!
\brief Compute the closest points between two geometries.
\ingroup closest_points
\details The free function closest_points calculates the closest points between two geometries. \details_default_strategy
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Segment Any type fulfilling a Segment Concept
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param shortest_seg Output segment containing the closest points
\qbk{
[heading Example]
[closest_points]
[closest_points_output]
[heading See also]
\* [link geometry.reference.algorithms.distance distance]
}
*/
template <typename Geometry1, typename Geometry2, typename Segment>
inline void closest_points(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Segment& shortest_seg)
{
closest_points(geometry1, geometry2, shortest_seg, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
@@ -0,0 +1,261 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
#include <boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/geometries.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_points
{
struct linear_to_areal
{
template <typename Linear, typename Areal, typename Segment, typename Strategies>
static inline void apply(Linear const& linear,
Areal const& areal,
Segment& shortest_seg,
Strategies const& strategies)
{
using most_precise_type = typename select_coordinate_type<Linear, Areal>::type;
using point_type = typename std::conditional
<
std::is_same<typename coordinate_type<Linear>::type, most_precise_type>::value,
typename point_type<Linear>::type,
typename point_type<Areal>::type
>::type;
using linestring_type = geometry::model::linestring<point_type>;
/* TODO: currently intersection does not support some cases of tupled input
* such as linestring - multipolygon
* this could be implemented directly with dynamic geometries
using polygon_type = geometry::model::polygon<point_type>;
std::tuple
<
geometry::model::multi_point<point_type>,
geometry::model::multi_linestring<linestring_type>,
geometry::model::multi_polygon<polygon_type>
> tp;
bool intersect_tp = geometry::intersection(linear, areal, tp, strategies);
*/
geometry::model::multi_point<point_type> mp_out;
geometry::intersection(linear, areal, mp_out, strategies);
if (! boost::empty(mp_out))
{
set_segment_from_points::apply(*boost::begin(mp_out),
*boost::begin(mp_out),
shortest_seg);
return;
}
// if there are no intersection points then check if the linear geometry
// (or part of it) is inside the areal and return any point of this part
geometry::model::multi_linestring<linestring_type> ln_out;
geometry::intersection(linear, areal, ln_out, strategies);
if (! boost::empty(ln_out))
{
set_segment_from_points::apply(*boost::begin(*boost::begin(ln_out)),
*boost::begin(*boost::begin(ln_out)),
shortest_seg);
return;
}
linear_to_linear::apply(linear, areal, shortest_seg, strategies, false);
}
};
struct areal_to_linear
{
template <typename Linear, typename Areal, typename Segment, typename Strategies>
static inline void apply(Areal const& areal,
Linear const& linear,
Segment& shortest_seg,
Strategies const& strategies)
{
linear_to_areal::apply(linear, areal, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
struct segment_to_areal
{
template <typename Segment, typename Areal, typename OutSegment, typename Strategies>
static inline void apply(Segment const& segment,
Areal const& areal,
OutSegment& shortest_seg,
Strategies const& strategies,
bool = false)
{
using linestring_type = geometry::model::linestring<typename point_type<Segment>::type>;
linestring_type linestring;
convert(segment, linestring);
linear_to_areal::apply(linestring, areal, shortest_seg, strategies);
}
};
struct areal_to_segment
{
template <typename Areal, typename Segment, typename OutSegment, typename Strategies>
static inline void apply(Areal const& areal,
Segment const& segment,
OutSegment& shortest_seg,
Strategies const& strategies,
bool = false)
{
segment_to_areal::apply(segment, areal, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
struct areal_to_areal
{
template <typename Areal1, typename Areal2, typename Segment, typename Strategies>
static inline void apply(Areal1 const& areal1,
Areal2 const& areal2,
Segment& shortest_seg,
Strategies const& strategies)
{
using most_precise_type = typename select_coordinate_type<Areal1, Areal2>::type;
using point_type = typename std::conditional
<
std::is_same<typename coordinate_type<Areal1>::type, most_precise_type>::value,
typename point_type<Areal1>::type,
typename point_type<Areal2>::type
>::type;
using linestring_type = geometry::model::linestring<point_type>;
using polygon_type = geometry::model::polygon<point_type>;
/* TODO: currently intersection does not support tupled input
* this should be implemented directly with dynamic geometries
*/
geometry::model::multi_point<point_type> mp_out;
geometry::intersection(areal1, areal2, mp_out, strategies);
if (! boost::empty(mp_out))
{
set_segment_from_points::apply(*boost::begin(mp_out),
*boost::begin(mp_out),
shortest_seg);
return;
}
// if there are no intersection points then the linear geometry (or part of it)
// is inside the areal; return any point of this part
geometry::model::multi_linestring<linestring_type> ln_out;
geometry::intersection(areal1, areal2, ln_out, strategies);
if (! boost::empty(ln_out))
{
set_segment_from_points::apply(*boost::begin(*boost::begin(ln_out)),
*boost::begin(*boost::begin(ln_out)),
shortest_seg);
return;
}
geometry::model::multi_polygon<polygon_type> pl_out;
geometry::intersection(areal1, areal2, pl_out, strategies);
if (! boost::empty(pl_out))
{
set_segment_from_points::apply(
*boost::begin(boost::geometry::exterior_ring(*boost::begin(pl_out))),
*boost::begin(boost::geometry::exterior_ring(*boost::begin(pl_out))),
shortest_seg);
return;
}
linear_to_linear::apply(areal1, areal2, shortest_seg, strategies, false);
}
};
}} // namespace detail::closest_points
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Areal>
struct closest_points
<
Linear, Areal,
linear_tag, areal_tag,
false
>
: detail::closest_points::linear_to_areal
{};
template <typename Areal, typename Linear>
struct closest_points
<
Areal, Linear,
areal_tag, linear_tag,
false
>
: detail::closest_points::areal_to_linear
{};
template <typename Segment, typename Areal>
struct closest_points
<
Segment, Areal,
segment_tag, areal_tag,
false
>
: detail::closest_points::segment_to_areal
{};
template <typename Areal, typename Segment>
struct closest_points
<
Areal, Segment,
areal_tag, segment_tag,
false
>
: detail::closest_points::areal_to_segment
{};
template <typename Areal1, typename Areal2>
struct closest_points
<
Areal1, Areal2,
areal_tag, areal_tag,
false
>
: detail::closest_points::areal_to_areal
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
@@ -0,0 +1,155 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
#include <boost/geometry/algorithms/num_segments.hpp>
#include <boost/geometry/core/point_type.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 closest_points
{
struct linear_to_linear
{
template <typename Linear1, typename Linear2, typename Segment, typename Strategies>
static inline void apply(Linear1 const& linear1,
Linear2 const& linear2,
Segment& shortest_seg,
Strategies const& strategies,
bool = false)
{
if (geometry::num_points(linear1) == 1)
{
dispatch::closest_points
<
typename point_type<Linear1>::type,
Linear2
>::apply(*points_begin(linear1), linear2, shortest_seg, strategies);
return;
}
if (geometry::num_points(linear2) == 1)
{
dispatch::closest_points
<
typename point_type<Linear2>::type,
Linear1
>::apply(*points_begin(linear2), linear1, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
return;
}
if (geometry::num_segments(linear1) < geometry::num_segments(linear2))
{
point_or_segment_range_to_geometry_rtree::apply(
geometry::segments_begin(linear2),
geometry::segments_end(linear2),
linear1,
shortest_seg,
strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
return;
}
point_or_segment_range_to_geometry_rtree::apply(
geometry::segments_begin(linear1),
geometry::segments_end(linear1),
linear2,
shortest_seg,
strategies);
}
};
struct segment_to_linear
{
template <typename Segment, typename Linear, typename OutSegment, typename Strategies>
static inline void apply(Segment const& segment,
Linear const& linear,
OutSegment& shortest_seg,
Strategies const& strategies,
bool = false)
{
using linestring_type = geometry::model::linestring
<typename point_type<Segment>::type>;
linestring_type linestring;
convert(segment, linestring);
linear_to_linear::apply(linestring, linear, shortest_seg, strategies);
}
};
struct linear_to_segment
{
template <typename Linear, typename Segment, typename OutSegment, typename Strategies>
static inline void apply(Linear const& linear,
Segment const& segment,
OutSegment& shortest_seg,
Strategies const& strategies,
bool = false)
{
segment_to_linear::apply(segment, linear, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
}} // namespace detail::closest_points
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear1, typename Linear2>
struct closest_points
<
Linear1, Linear2,
linear_tag, linear_tag,
false
> : detail::closest_points::linear_to_linear
{};
template <typename Segment, typename Linear>
struct closest_points
<
Segment, Linear,
segment_tag, linear_tag,
false
> : detail::closest_points::segment_to_linear
{};
template <typename Linear, typename Segment>
struct closest_points
<
Linear, Segment,
linear_tag, segment_tag,
false
> : detail::closest_points::linear_to_segment
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
@@ -0,0 +1,327 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
#include <iterator>
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/linestring.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_points
{
struct multipoint_to_multipoint
{
template
<
typename MultiPoint1,
typename MultiPoint2,
typename Segment,
typename Strategies
>
static inline void apply(MultiPoint1 const& multipoint1,
MultiPoint2 const& multipoint2,
Segment& shortest_seg,
Strategies const& strategies)
{
if (boost::size(multipoint1) < boost::size(multipoint2))
{
point_or_segment_range_to_geometry_rtree::apply(
boost::begin(multipoint2),
boost::end(multipoint2),
multipoint1,
shortest_seg,
strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
return;
}
point_or_segment_range_to_geometry_rtree::apply(
boost::begin(multipoint1),
boost::end(multipoint1),
multipoint2,
shortest_seg,
strategies);
}
};
struct multipoint_to_linear
{
template
<
typename MultiPoint,
typename Linear,
typename Segment,
typename Strategies
>
static inline void apply(MultiPoint const& multipoint,
Linear const& linear,
Segment& shortest_seg,
Strategies const& strategies)
{
point_or_segment_range_to_geometry_rtree::apply(
boost::begin(multipoint),
boost::end(multipoint),
linear,
shortest_seg,
strategies);
}
};
struct linear_to_multipoint
{
template
<
typename Linear,
typename MultiPoint,
typename Segment,
typename Strategies
>
static inline void apply(Linear const& linear,
MultiPoint const& multipoint,
Segment& shortest_seg,
Strategies const& strategies)
{
multipoint_to_linear::apply(multipoint, linear, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
struct segment_to_multipoint
{
template
<
typename Segment,
typename MultiPoint,
typename OutSegment,
typename Strategies
>
static inline void apply(Segment const& segment,
MultiPoint const& multipoint,
OutSegment& shortest_seg,
Strategies const& strategies)
{
using linestring_type = geometry::model::linestring
<
typename point_type<Segment>::type
>;
linestring_type linestring;
convert(segment, linestring);
multipoint_to_linear::apply(multipoint, linestring, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
struct multipoint_to_segment
{
template
<
typename MultiPoint,
typename Segment,
typename OutSegment,
typename Strategies
>
static inline void apply(MultiPoint const& multipoint,
Segment const& segment,
OutSegment& shortest_seg,
Strategies const& strategies)
{
using linestring_type = geometry::model::linestring
<
typename point_type<Segment>::type
>;
linestring_type linestring;
convert(segment, linestring);
multipoint_to_linear::apply(multipoint, linestring, shortest_seg,
strategies);
}
};
struct multipoint_to_areal
{
private:
template <typename Areal, typename Strategies>
struct covered_by_areal
{
covered_by_areal(Areal const& areal, Strategies const& strategy)
: m_areal(areal), m_strategy(strategy)
{}
template <typename Point>
inline bool operator()(Point const& point) const
{
return geometry::covered_by(point, m_areal, m_strategy);
}
Areal const& m_areal;
Strategies const& m_strategy;
};
public:
template
<
typename MultiPoint,
typename Areal,
typename Segment,
typename Strategies
>
static inline void apply(MultiPoint const& multipoint,
Areal const& areal,
Segment& shortest_seg,
Strategies const& strategies)
{
covered_by_areal<Areal, Strategies> predicate(areal, strategies);
auto it = std::find_if(
boost::begin(multipoint),
boost::end(multipoint),
predicate);
if (it != boost::end(multipoint))
{
return set_segment_from_points::apply(*it, *it, shortest_seg);
}
point_or_segment_range_to_geometry_rtree::apply(
boost::begin(multipoint),
boost::end(multipoint),
areal,
shortest_seg,
strategies);
}
};
struct areal_to_multipoint
{
template
<
typename Areal,
typename MultiPoint,
typename Segment,
typename Strategies
>
static inline void apply(Areal const& areal,
MultiPoint const& multipoint,
Segment& shortest_seg,
Strategies const& strategies)
{
multipoint_to_areal::apply(multipoint, areal, shortest_seg, strategies);
detail::closest_points::swap_segment_points::apply(shortest_seg);
}
};
}} // namespace detail::closest_points
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename MultiPoint1, typename MultiPoint2>
struct closest_points
<
MultiPoint1, MultiPoint2,
multi_point_tag, multi_point_tag,
false
> : detail::closest_points::multipoint_to_multipoint
{};
template <typename MultiPoint, typename Linear>
struct closest_points
<
MultiPoint, Linear,
multi_point_tag, linear_tag,
false
> : detail::closest_points::multipoint_to_linear
{};
template <typename Linear, typename MultiPoint>
struct closest_points
<
Linear, MultiPoint,
linear_tag, multi_point_tag,
false
> : detail::closest_points::linear_to_multipoint
{};
template <typename MultiPoint, typename Segment>
struct closest_points
<
MultiPoint, Segment,
multi_point_tag, segment_tag,
false
> : detail::closest_points::multipoint_to_segment
{};
template <typename Segment, typename MultiPoint>
struct closest_points
<
Segment, MultiPoint,
segment_tag, multi_point_tag,
false
> : detail::closest_points::segment_to_multipoint
{};
template <typename MultiPoint, typename Areal>
struct closest_points
<
MultiPoint, Areal,
multi_point_tag, areal_tag,
false
> : detail::closest_points::multipoint_to_areal
{};
template <typename Areal, typename MultiPoint>
struct closest_points
<
Areal, MultiPoint,
areal_tag, multi_point_tag,
false
> : detail::closest_points::areal_to_multipoint
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
@@ -0,0 +1,456 @@
// Boost.Geometry
// Copyright (c) 2021-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_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/closest_points/utilities.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/closest_points.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/radian_access.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 closest_points
{
struct point_to_point
{
template <typename P1, typename P2, typename Segment, typename Strategies>
static inline void apply(P1 const& p1, P2 const& p2,
Segment& shortest_seg, Strategies const&)
{
set_segment_from_points::apply(p1, p2, shortest_seg);
}
};
struct point_to_segment
{
template <typename Point, typename Segment, typename OutputSegment, typename Strategies>
static inline void apply(Point const& point, Segment const& segment,
OutputSegment& shortest_seg, 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);
auto closest_point = strategies.closest_points(point, segment)
.apply(point, p[0], p[1]);
set_segment_from_points::apply(point, closest_point, shortest_seg);
}
};
/*
struct point_to_box
{
template<typename Point, typename Box, typename Strategies>
static inline auto apply(Point const& point, Box const& box,
Strategies const& strategies)
{
boost::ignore_unused(strategies);
return strategies.closest_points(point, box).apply(point, box);
}
};
*/
template <closure_selector Closure>
class point_to_range
{
public:
template <typename Point, typename Range, typename Segment, typename Strategies>
static inline void apply(Point const& point, Range const& range,
Segment& shortest_seg,
Strategies const& strategies)
{
using point_to_point_range = detail::closest_feature::point_to_point_range
<
Point, Range, Closure
>;
if (boost::size(range) == 0)
{
set_segment_from_points::apply(point, point, shortest_seg);
return;
}
closest_points::creturn_t<Point, Range, Strategies> cd_min;
auto comparable_distance = strategy::distance::services::get_comparable
<
decltype(strategies.distance(point, range))
>::apply(strategies.distance(point, range));
auto closest_segment = point_to_point_range::apply(point,
boost::begin(range),
boost::end(range),
comparable_distance,
cd_min);
auto closest_point = strategies.closest_points(point, range)
.apply(point, *closest_segment.first, *closest_segment.second);
set_segment_from_points::apply(point, closest_point, shortest_seg);
}
};
template<closure_selector Closure>
struct point_to_ring
{
template <typename Point, typename Ring, typename Segment, typename Strategies>
static inline auto apply(Point const& point,
Ring const& ring,
Segment& shortest_seg,
Strategies const& strategies)
{
if (within::within_point_geometry(point, ring, strategies))
{
set_segment_from_points::apply(point, point, shortest_seg);
}
else
{
point_to_range
<
closure<Ring>::value
>::apply(point, ring, shortest_seg, strategies);
}
}
};
template <closure_selector Closure>
class point_to_polygon
{
template <typename Polygon>
struct distance_to_interior_rings
{
template
<
typename Point,
typename InteriorRingIterator,
typename Segment,
typename Strategies
>
static inline void apply(Point const& point,
InteriorRingIterator first,
InteriorRingIterator last,
Segment& shortest_seg,
Strategies const& strategies)
{
using per_ring = point_to_range<Closure>;
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 is its distance to the polygon's
// hole boundary
per_ring::apply(point, *it, shortest_seg, strategies);
return;
}
}
set_segment_from_points::apply(point, point, shortest_seg);
}
template
<
typename Point,
typename InteriorRings,
typename Segment,
typename Strategies
>
static inline void apply(Point const& point, InteriorRings const& interior_rings,
Segment& shortest_seg, Strategies const& strategies)
{
apply(point,
boost::begin(interior_rings),
boost::end(interior_rings),
shortest_seg,
strategies);
}
};
public:
template
<
typename Point,
typename Polygon,
typename Segment,
typename Strategies
>
static inline void apply(Point const& point,
Polygon const& polygon,
Segment& shortest_seg,
Strategies const& strategies)
{
using per_ring = point_to_range<Closure>;
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
per_ring::apply(point, exterior_ring(polygon), shortest_seg, strategies);
return;
}
// Check interior rings
distance_to_interior_rings<Polygon>::apply(point,
interior_rings(polygon),
shortest_seg,
strategies);
}
};
template
<
typename MultiGeometry,
bool CheckCoveredBy = std::is_same
<
typename tag<MultiGeometry>::type, multi_polygon_tag
>::value
>
class point_to_multigeometry
{
private:
using geometry_to_range = detail::closest_feature::geometry_to_range;
public:
template
<
typename Point,
typename Segment,
typename Strategies
>
static inline void apply(Point const& point,
MultiGeometry const& multigeometry,
Segment& shortest_seg,
Strategies const& strategies)
{
using selector_type = distance::iterator_selector<MultiGeometry const>;
closest_points::creturn_t<Point, MultiGeometry, Strategies> cd;
auto comparable_distance = strategy::distance::services::get_comparable
<
decltype(strategies.distance(point, multigeometry))
>::apply(strategies.distance(point, multigeometry));
typename selector_type::iterator_type it_min
= geometry_to_range::apply(point,
selector_type::begin(multigeometry),
selector_type::end(multigeometry),
comparable_distance,
cd);
dispatch::closest_points
<
Point,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type
>::apply(point, *it_min, shortest_seg, strategies);
}
};
// this is called only for multipolygons, hence the change in the
// template parameter name MultiGeometry to MultiPolygon
template <typename MultiPolygon>
struct point_to_multigeometry<MultiPolygon, true>
{
template
<
typename Point,
typename Segment,
typename Strategies
>
static inline void apply(Point const& point,
MultiPolygon const& multipolygon,
Segment& shortest_seg,
Strategies const& strategies)
{
if (within::covered_by_point_geometry(point, multipolygon, strategies))
{
set_segment_from_points::apply(point, point, shortest_seg);
return;
}
return point_to_multigeometry
<
MultiPolygon, false
>::apply(point, multipolygon, shortest_seg, strategies);
}
};
}} // namespace detail::closest_points
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename P1, typename P2>
struct closest_points
<
P1, P2, point_tag, point_tag, false
> : detail::closest_points::point_to_point
{};
template <typename Point, typename Linestring>
struct closest_points
<
Point, Linestring, point_tag, linestring_tag, false
> : detail::closest_points::point_to_range<closed>
{};
template <typename Point, typename Ring>
struct closest_points
<
Point, Ring, point_tag, ring_tag, false
> : detail::closest_points::point_to_ring
<
closure<Ring>::value
>
{};
template <typename Point, typename Polygon>
struct closest_points
<
Point, Polygon, point_tag, polygon_tag, false
> : detail::closest_points::point_to_polygon
<
closure<Polygon>::value
>
{};
template <typename Point, typename Segment>
struct closest_points
<
Point, Segment, point_tag, segment_tag, false
> : detail::closest_points::point_to_segment
{};
/*
template <typename Point, typename Box>
struct closest_points
<
Point, Box, point_tag, box_tag,
strategy_tag_distance_point_box, false
> : detail::closest_points::point_to_box<Point, Box>
{};
*/
template<typename Point, typename MultiPoint>
struct closest_points
<
Point, MultiPoint, point_tag, multi_point_tag, false
> : detail::closest_points::point_to_multigeometry<MultiPoint>
{};
template<typename Point, typename MultiLinestring>
struct closest_points
<
Point, MultiLinestring, point_tag, multi_linestring_tag, false
> : detail::closest_points::point_to_multigeometry<MultiLinestring>
{};
template<typename Point, typename MultiPolygon>
struct closest_points
<
Point, MultiPolygon, point_tag, multi_polygon_tag, false
> : detail::closest_points::point_to_multigeometry<MultiPolygon>
{};
template <typename Point, typename Linear>
struct closest_points
<
Point, Linear, point_tag, linear_tag, false
> : closest_points
<
Point, Linear,
point_tag, typename tag<Linear>::type, false
>
{};
template <typename Point, typename Areal>
struct closest_points
<
Point, Areal, point_tag, areal_tag, false
> : closest_points
<
Point, Areal,
point_tag, typename tag<Areal>::type, false
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
@@ -0,0 +1,110 @@
// Boost.Geometry
// Copyright (c) 2021-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
#include <iterator>
#include <utility>
#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_points/utilities.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/dispatch/closest_points.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/iterators/detail/has_one_element.hpp>
#include <boost/geometry/strategies/distance.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_points
{
class point_or_segment_range_to_geometry_rtree
{
public:
template
<
typename PointOrSegmentIterator,
typename Geometry,
typename Segment,
typename Strategies
>
static inline void apply(PointOrSegmentIterator first,
PointOrSegmentIterator last,
Geometry const& geometry,
Segment& shortest_seg,
Strategies const& strategies)
{
typedef typename std::iterator_traits
<
PointOrSegmentIterator
>::value_type point_or_segment_type;
typedef distance::iterator_selector<Geometry const> selector_type;
typedef detail::closest_feature::range_to_range_rtree range_to_range;
BOOST_GEOMETRY_ASSERT( first != last );
//TODO: Is this special case needed?
//if ( detail::has_one_element(first, last) )
//{
// dispatch::closest_points
// <
// point_or_segment_type, Geometry
// >::apply(*first, geometry, shortest_seg, strategies);
//}
closest_points::creturn_t<point_or_segment_type, Geometry, Strategies> cd;
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),
strategies,
cd);
dispatch::closest_points
<
point_or_segment_type,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type
>::apply(closest_features.first,
*closest_features.second,
shortest_seg,
strategies);
}
};
}} // namespace detail::closest_points
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
@@ -0,0 +1,145 @@
// Boost.Geometry
// Copyright (c) 2021-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
#include <algorithm>
#include <iterator>
#include <boost/core/addressof.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/intersects.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/util/condition.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace closest_points
{
// compute segment-segment closest-points
class segment_to_segment
{
public:
template <typename Segment1, typename Segment2, typename OutputSegment, typename Strategies>
static inline void apply(Segment1 const& segment1, Segment2 const& segment2,
OutputSegment& shortest_seg,
Strategies const& strategies)
{
using intersection_return_type = segment_intersection_points
<
typename point_type<Segment1>::type
>;
using intersection_policy = policies::relate::segments_intersection_points
<
intersection_return_type
>;
detail::segment_as_subrange<Segment1> sub_range1(segment1);
detail::segment_as_subrange<Segment2> sub_range2(segment2);
auto is = strategies.relate().apply(sub_range1, sub_range2,
intersection_policy());
if (is.count > 0)
{
set_segment_from_points::apply(is.intersections[0],
is.intersections[0],
shortest_seg);
return;
}
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]);
auto cp0 = strategies.closest_points(q[0], segment1).apply(q[0], p[0], p[1]);
auto cp1 = strategies.closest_points(q[1], segment1).apply(q[1], p[0], p[1]);
auto cp2 = strategies.closest_points(p[0], segment2).apply(p[0], q[0], q[1]);
auto cp3 = strategies.closest_points(p[1], segment2).apply(p[1], q[0], q[1]);
closest_points::creturn_t<Segment1, Segment2, Strategies> d[4];
auto const cds = strategies::distance::detail::make_comparable(strategies)
.distance(detail::dummy_point(), detail::dummy_point());
d[0] = cds.apply(cp0, q[0]);
d[1] = cds.apply(cp1, q[1]);
d[2] = cds.apply(p[0], cp2);
d[3] = cds.apply(p[1], cp3);
std::size_t imin = std::distance(boost::addressof(d[0]), std::min_element(d, d + 4));
switch (imin)
{
case 0:
set_segment_from_points::apply(cp0, q[0], shortest_seg);
return;
case 1:
set_segment_from_points::apply(cp1, q[1], shortest_seg);
return;
case 2:
set_segment_from_points::apply(p[0], cp2, shortest_seg);
return;
default:
set_segment_from_points::apply(p[1], cp3, shortest_seg);
return;
}
}
};
}} // namespace detail::closest_points
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// segment-segment
template <typename Segment1, typename Segment2>
struct closest_points
<
Segment1, Segment2, segment_tag, segment_tag, false
> : detail::closest_points::segment_to_segment
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
@@ -0,0 +1,69 @@
// Boost.Geometry
// Copyright (c) 2021-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/util/algorithm.hpp>
#include <boost/geometry/strategies/distance.hpp>
namespace boost { namespace geometry
{
namespace detail { namespace closest_points
{
struct set_segment_from_points
{
template <typename Point1, typename Point2, typename Segment>
static inline void apply(Point1 const& p1, Point2 const& p2, Segment& segment)
{
assign_point_to_index<0>(p1, segment);
assign_point_to_index<1>(p2, segment);
}
};
struct swap_segment_points
{
template <typename Segment>
static inline void apply(Segment& segment)
{
geometry::detail::for_each_dimension<Segment>([&](auto index)
{
auto temp = get<0,index>(segment);
set<0,index>(segment, get<1,index>(segment));
set<1,index>(segment, temp);
});
}
};
template <typename Geometry1, typename Geometry2, typename Strategies>
using distance_strategy_t = decltype(
std::declval<Strategies>().distance(std::declval<Geometry1>(), std::declval<Geometry2>()));
template <typename Geometry1, typename Geometry2, typename Strategies>
using creturn_t = typename strategy::distance::services::return_type
<
typename strategy::distance::services::comparable_type
<
distance_strategy_t<Geometry1, Geometry2, Strategies>
>::type,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type;
}} // namespace detail::closest_points
}} // namespace boost::geometry
#endif //BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP