update boost
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
// 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.
|
||||
|
||||
// This file was modified by Oracle on 2014-2023.
|
||||
// Modifications copyright (c) 2014-2023, 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
|
||||
|
||||
@@ -21,20 +21,19 @@
|
||||
#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/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.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/algorithms/detail/signed_size_type.hpp>
|
||||
#include <boost/geometry/core/mutable_range.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/visit.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // for backward compatibility
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/geometries/variant.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
@@ -46,20 +45,20 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace append
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_no_action
|
||||
{
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry& , Point const& ,
|
||||
int = 0, int = 0)
|
||||
signed_size_type = -1, signed_size_type = 0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point
|
||||
struct to_range_point
|
||||
{
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry& geometry, Point const& point,
|
||||
int = 0, int = 0)
|
||||
signed_size_type = -1, signed_size_type = 0)
|
||||
{
|
||||
typename geometry::point_type<Geometry>::type copy;
|
||||
geometry::detail::conversion::convert_point_to_point(point, copy);
|
||||
@@ -68,287 +67,191 @@ struct append_point
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range
|
||||
struct to_range_range
|
||||
{
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
static inline void apply(Geometry& geometry, Range const& range,
|
||||
int = 0, int = 0)
|
||||
signed_size_type = -1, signed_size_type = 0)
|
||||
{
|
||||
for (typename boost::range_iterator<Range const>::type
|
||||
it = boost::begin(range);
|
||||
it != boost::end(range);
|
||||
++it)
|
||||
using point_type = typename boost::range_value<Range>::type;
|
||||
|
||||
auto const end = boost::end(range);
|
||||
for (auto it = boost::begin(range); it != end; ++it)
|
||||
{
|
||||
append_point<Geometry, point_type>::apply(geometry, *it);
|
||||
to_range_point::apply<Geometry, point_type>(geometry, *it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon, typename Point>
|
||||
struct point_to_polygon
|
||||
struct to_polygon_point
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef typename ring_return_type<Polygon>::type exterior_ring_type;
|
||||
typedef typename interior_return_type<Polygon>::type interior_ring_range_type;
|
||||
|
||||
template <typename Polygon, typename Point>
|
||||
static inline void apply(Polygon& polygon, Point const& point,
|
||||
int ring_index, int = 0)
|
||||
signed_size_type ring_index, signed_size_type = 0)
|
||||
{
|
||||
using ring_type = typename ring_type<Polygon>::type;
|
||||
|
||||
if (ring_index == -1)
|
||||
{
|
||||
exterior_ring_type ext_ring = exterior_ring(polygon);
|
||||
append_point<ring_type, Point>::apply(
|
||||
ext_ring, point);
|
||||
auto&& ext_ring = exterior_ring(polygon);
|
||||
to_range_point::apply<ring_type, Point>(ext_ring, point);
|
||||
}
|
||||
else if (ring_index < int(num_interior_rings(polygon)))
|
||||
else if (ring_index < signed_size_type(num_interior_rings(polygon)))
|
||||
{
|
||||
interior_ring_range_type int_rings = interior_rings(polygon);
|
||||
append_point<ring_type, Point>::apply(
|
||||
range::at(int_rings, ring_index), point);
|
||||
auto&& int_rings = interior_rings(polygon);
|
||||
to_range_point::apply<ring_type, Point>(range::at(int_rings, ring_index), point);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon, typename Range>
|
||||
struct range_to_polygon
|
||||
struct to_polygon_range
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef typename ring_return_type<Polygon>::type exterior_ring_type;
|
||||
typedef typename interior_return_type<Polygon>::type interior_ring_range_type;
|
||||
|
||||
template <typename Polygon, typename Range>
|
||||
static inline void apply(Polygon& polygon, Range const& range,
|
||||
int ring_index, int = 0)
|
||||
signed_size_type ring_index, signed_size_type = 0)
|
||||
{
|
||||
using ring_type = typename ring_type<Polygon>::type;
|
||||
using exterior_ring_type = typename ring_return_type<Polygon>::type;
|
||||
using interior_ring_range_type = typename interior_return_type<Polygon>::type;
|
||||
|
||||
if (ring_index == -1)
|
||||
{
|
||||
exterior_ring_type ext_ring = exterior_ring(polygon);
|
||||
append_range<ring_type, Range>::apply(
|
||||
ext_ring, range);
|
||||
to_range_range::apply<ring_type, Range>(ext_ring, range);
|
||||
}
|
||||
else if (ring_index < int(num_interior_rings(polygon)))
|
||||
else if (ring_index < signed_size_type(num_interior_rings(polygon)))
|
||||
{
|
||||
interior_ring_range_type int_rings = interior_rings(polygon);
|
||||
append_range<ring_type, Range>::apply(
|
||||
range::at(int_rings, ring_index), range);
|
||||
to_range_range::apply<ring_type, Range>(range::at(int_rings, ring_index), range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::append
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
namespace splitted_dispatch
|
||||
{
|
||||
|
||||
template <typename Tag, typename Geometry, typename Point>
|
||||
struct append_point
|
||||
: detail::append::append_no_action<Geometry, Point>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point<linestring_tag, Geometry, Point>
|
||||
: detail::append::append_point<Geometry, Point>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point<ring_tag, Geometry, Point>
|
||||
: detail::append::append_point<Geometry, Point>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename Point>
|
||||
struct append_point<polygon_tag, Polygon, Point>
|
||||
: detail::append::point_to_polygon<Polygon, Point>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Tag, typename Geometry, typename Range>
|
||||
struct append_range
|
||||
: detail::append::append_no_action<Geometry, Range>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range<linestring_tag, Geometry, Range>
|
||||
: detail::append::append_range<Geometry, Range>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range<ring_tag, Geometry, Range>
|
||||
: detail::append::append_range<Geometry, Range>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename Range>
|
||||
struct append_range<polygon_tag, Polygon, Range>
|
||||
: detail::append::range_to_polygon<Polygon, Range>
|
||||
{};
|
||||
|
||||
} // namespace splitted_dispatch
|
||||
|
||||
|
||||
// Default: append a range (or linestring or ring or whatever) to any geometry
|
||||
template
|
||||
<
|
||||
typename Geometry, typename RangeOrPoint,
|
||||
typename TagRangeOrPoint = typename tag<RangeOrPoint>::type
|
||||
>
|
||||
struct append
|
||||
: splitted_dispatch::append_range<typename tag<Geometry>::type, Geometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
// Specialization for point to append a point to any geometry
|
||||
template <typename Geometry, typename RangeOrPoint>
|
||||
struct append<Geometry, RangeOrPoint, point_tag>
|
||||
: splitted_dispatch::append_point<typename tag<Geometry>::type, Geometry, RangeOrPoint>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace append
|
||||
{
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_to_multigeometry
|
||||
template <typename Policy>
|
||||
struct to_multigeometry
|
||||
{
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
static inline void apply(MultiGeometry& multigeometry,
|
||||
RangeOrPoint const& range_or_point,
|
||||
int ring_index, int multi_index)
|
||||
signed_size_type ring_index, signed_size_type multi_index)
|
||||
{
|
||||
|
||||
dispatch::append
|
||||
Policy::template apply
|
||||
<
|
||||
typename boost::range_value<MultiGeometry>::type,
|
||||
RangeOrPoint
|
||||
>::apply(range::at(multigeometry, multi_index), range_or_point, ring_index);
|
||||
>(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 RangeOrPoint,
|
||||
typename Tag = typename geometry::tag<Geometry>::type,
|
||||
typename OtherTag = typename geometry::tag<RangeOrPoint>::type
|
||||
>
|
||||
struct append
|
||||
: detail::append::append_no_action
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append_point<multi_point_tag, Geometry, Point>
|
||||
: detail::append::append_point<Geometry, Point>
|
||||
struct append<Geometry, Point, linestring_tag, point_tag>
|
||||
: detail::append::to_range_point
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range>
|
||||
struct append_range<multi_point_tag, Geometry, Range>
|
||||
: detail::append::append_range<Geometry, Range>
|
||||
template <typename Geometry, typename Point>
|
||||
struct append<Geometry, Point, ring_tag, point_tag>
|
||||
: detail::append::to_range_point
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_point<multi_linestring_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
template <typename Polygon, typename Point>
|
||||
struct append<Polygon, Point, polygon_tag, point_tag>
|
||||
: detail::append::to_polygon_point
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_range<multi_linestring_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
template <typename Geometry, typename Range, typename RangeTag>
|
||||
struct append<Geometry, Range, linestring_tag, RangeTag>
|
||||
: detail::append::to_range_range
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_point<multi_polygon_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
template <typename Geometry, typename Range, typename RangeTag>
|
||||
struct append<Geometry, Range, ring_tag, RangeTag>
|
||||
: detail::append::to_range_range
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
struct append_range<multi_polygon_tag, MultiGeometry, RangeOrPoint>
|
||||
: detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint>
|
||||
template <typename Polygon, typename Range, typename RangeTag>
|
||||
struct append<Polygon, Range, polygon_tag, RangeTag>
|
||||
: detail::append::to_polygon_range
|
||||
{};
|
||||
|
||||
} // namespace splitted_dispatch
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append<Geometry, Point, multi_point_tag, point_tag>
|
||||
: detail::append::to_range_point
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range, typename RangeTag>
|
||||
struct append<Geometry, Range, multi_point_tag, RangeTag>
|
||||
: detail::append::to_range_range
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename Point>
|
||||
struct append<MultiGeometry, Point, multi_linestring_tag, point_tag>
|
||||
: detail::append::to_multigeometry<detail::append::to_range_point>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename Range, typename RangeTag>
|
||||
struct append<MultiGeometry, Range, multi_linestring_tag, RangeTag>
|
||||
: detail::append::to_multigeometry<detail::append::to_range_range>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename Point>
|
||||
struct append<MultiGeometry, Point, multi_polygon_tag, point_tag>
|
||||
: detail::append::to_multigeometry<detail::append::to_polygon_point>
|
||||
{};
|
||||
|
||||
template <typename MultiGeometry, typename Range, typename RangeTag>
|
||||
struct append<MultiGeometry, Range, multi_polygon_tag, RangeTag>
|
||||
: detail::append::to_multigeometry<detail::append::to_polygon_range>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry, typename RangeOrPoint, typename OtherTag>
|
||||
struct append<Geometry, RangeOrPoint, dynamic_geometry_tag, OtherTag>
|
||||
{
|
||||
static inline void apply(Geometry& geometry,
|
||||
RangeOrPoint const& range_or_point,
|
||||
signed_size_type ring_index, signed_size_type multi_index)
|
||||
{
|
||||
traits::visit<Geometry>::apply([&](auto & g)
|
||||
{
|
||||
append
|
||||
<
|
||||
std::remove_reference_t<decltype(g)>, RangeOrPoint
|
||||
>::apply(g, range_or_point, ring_index, multi_index);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: It's unclear how append should work for GeometryCollection because
|
||||
// it can hold multiple different geometries.
|
||||
|
||||
} // 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
|
||||
@@ -365,10 +268,14 @@ struct append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
*/
|
||||
template <typename Geometry, typename RangeOrPoint>
|
||||
inline void append(Geometry& geometry, RangeOrPoint const& range_or_point,
|
||||
int ring_index = -1, int multi_index = 0)
|
||||
signed_size_type ring_index = -1, signed_size_type multi_index = 0)
|
||||
{
|
||||
resolve_variant::append<Geometry>
|
||||
::apply(geometry, range_or_point, ring_index, multi_index);
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::append
|
||||
<
|
||||
Geometry, RangeOrPoint
|
||||
>::apply(geometry, range_or_point, ring_index, multi_index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2017-2022 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017-2023.
|
||||
// Modifications copyright (c) 2017-2023 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -19,14 +20,11 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range/functions.hpp>
|
||||
#include <boost/range/metafunctions.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
@@ -35,25 +33,28 @@
|
||||
#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/core/visit.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/algorithms/detail/visit.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
#include <boost/geometry/strategies/area_result.hpp>
|
||||
#include <boost/geometry/strategies/default_area_result.hpp>
|
||||
#include <boost/geometry/algorithms/area_result.hpp>
|
||||
#include <boost/geometry/algorithms/default_area_result.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area/services.hpp>
|
||||
#include <boost/geometry/strategies/area/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/area/geographic.hpp>
|
||||
#include <boost/geometry/strategies/area/spherical.hpp>
|
||||
#include <boost/geometry/strategies/concepts/area_concept.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/concepts/area_concept.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/order_as_direction.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -66,61 +67,48 @@ 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&)
|
||||
template <typename Box, typename Strategies>
|
||||
static inline auto
|
||||
apply(Box const& box, Strategies const& strategies)
|
||||
{
|
||||
// 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));
|
||||
return strategies.area(box).apply(box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
iterate_direction Direction,
|
||||
closure_selector Closure
|
||||
>
|
||||
struct ring_area
|
||||
{
|
||||
template <typename Ring, typename Strategy>
|
||||
static inline typename area_result<Ring, Strategy>::type
|
||||
apply(Ring const& ring, Strategy const& strategy)
|
||||
template <typename Ring, typename Strategies>
|
||||
static inline typename area_result<Ring, Strategies>::type
|
||||
apply(Ring const& ring, Strategies const& strategies)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Ring, Strategy>) );
|
||||
using strategy_type = decltype(strategies.area(ring));
|
||||
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Ring, strategy_type>) );
|
||||
assert_dimension<Ring, 2>();
|
||||
|
||||
// Ignore warning (because using static method sometimes) on strategy
|
||||
boost::ignore_unused(strategy);
|
||||
boost::ignore_unused(strategies);
|
||||
|
||||
// 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)
|
||||
if (boost::size(ring) < detail::minimum_ring_size<Ring>::value)
|
||||
{
|
||||
return typename area_result<Ring, Strategy>::type();
|
||||
return typename area_result<Ring, Strategies>::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;
|
||||
detail::closed_clockwise_view<Ring const> const view(ring);
|
||||
auto it = boost::begin(view);
|
||||
auto const end = boost::end(view);
|
||||
|
||||
rview_type rview(ring);
|
||||
view_type view(rview);
|
||||
typename Strategy::template state<Ring> state;
|
||||
iterator_type it = boost::begin(view);
|
||||
iterator_type end = boost::end(view);
|
||||
strategy_type const strategy = strategies.area(ring);
|
||||
typename strategy_type::template state<Ring> state;
|
||||
|
||||
for (iterator_type previous = it++;
|
||||
it != end;
|
||||
++previous, ++it)
|
||||
for (auto previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
strategy.apply(*previous, *it, state);
|
||||
}
|
||||
@@ -167,10 +155,6 @@ 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
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
@@ -181,13 +165,10 @@ struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
|
||||
static inline typename area_result<Polygon, Strategy>::type
|
||||
apply(Polygon const& polygon, Strategy const& strategy)
|
||||
{
|
||||
return calculate_polygon_sum::apply<
|
||||
typename area_result<Polygon, Strategy>::type,
|
||||
detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Polygon>::value>::value,
|
||||
geometry::closure<Polygon>::value
|
||||
>
|
||||
return calculate_polygon_sum::apply
|
||||
<
|
||||
typename area_result<Polygon, Strategy>::type,
|
||||
detail::area::ring_area
|
||||
>(polygon, strategy);
|
||||
}
|
||||
};
|
||||
@@ -216,7 +197,11 @@ struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Strategy>
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct area
|
||||
{
|
||||
template <typename Geometry>
|
||||
@@ -227,16 +212,30 @@ struct area
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct area<Strategy, false>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static auto apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
using strategies::area::services::strategy_converter;
|
||||
return dispatch::area
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct area<default_strategy>
|
||||
struct area<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline typename area_result<Geometry>::type
|
||||
apply(Geometry const& geometry, default_strategy)
|
||||
{
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
typedef typename strategies::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
Geometry
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy_type());
|
||||
@@ -247,10 +246,10 @@ struct area<default_strategy>
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
|
||||
struct area
|
||||
{
|
||||
template <typename Strategy>
|
||||
@@ -261,37 +260,40 @@ struct area
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
struct area<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
|
||||
|
||||
template <typename Strategy>
|
||||
struct visitor
|
||||
: boost::static_visitor<typename area_result<variant_type, Strategy>::type>
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry>
|
||||
typename area_result<variant_type, Strategy>::type
|
||||
operator()(Geometry const& geometry) const
|
||||
typename area_result<Geometry, Strategy>::type result = 0;
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
return area<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline typename area_result<variant_type, Strategy>::type
|
||||
apply(variant_type const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
result = area<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
|
||||
}, geometry);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
template <typename Geometry>
|
||||
struct area<Geometry, geometry_collection_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
typename area_result<Geometry, Strategy>::type result = 0;
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
result += area<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
|
||||
return true;
|
||||
}, geometry);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -323,7 +325,7 @@ area(Geometry const& geometry)
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_variant::area<Geometry>::apply(geometry, default_strategy());
|
||||
return resolve_dynamic::area<Geometry>::apply(geometry, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -359,7 +361,7 @@ area(Geometry const& geometry, Strategy const& strategy)
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_variant::area<Geometry>::apply(geometry, strategy);
|
||||
return resolve_dynamic::area<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
141
linx64/include/boost/geometry/algorithms/area_result.hpp
Normal file
141
linx64/include/boost/geometry/algorithms/area_result.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2020-2023.
|
||||
// Modifications copyright (c) 2020-2023 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_AREA_RESULT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_AREA_RESULT_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area/services.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace area
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct area_result
|
||||
{
|
||||
typedef decltype(std::declval<Strategy>().area(std::declval<Geometry>())) strategy_type;
|
||||
typedef typename strategy_type::template result_type<Geometry>::type type;
|
||||
};
|
||||
|
||||
template <typename Geometry, typename Strategy>
|
||||
struct area_result<Geometry, Strategy, false>
|
||||
{
|
||||
typedef typename Strategy::template result_type<Geometry>::type type;
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct default_area_result
|
||||
: area_result
|
||||
<
|
||||
Geometry,
|
||||
typename geometry::strategies::area::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Curr, typename Next>
|
||||
struct more_precise_coordinate_type
|
||||
: std::is_same
|
||||
<
|
||||
typename geometry::coordinate_type<Curr>::type,
|
||||
typename geometry::select_most_precise
|
||||
<
|
||||
typename geometry::coordinate_type<Curr>::type,
|
||||
typename geometry::coordinate_type<Next>::type
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Curr, typename Next>
|
||||
struct more_precise_default_area_result
|
||||
: std::is_same
|
||||
<
|
||||
typename default_area_result<Curr>::type,
|
||||
typename geometry::select_most_precise
|
||||
<
|
||||
typename default_area_result<Curr>::type,
|
||||
typename default_area_result<Next>::type
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace detail::area
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
/*!
|
||||
\brief Meta-function defining return type of area function
|
||||
\ingroup area
|
||||
\note The return-type is defined by Geometry and Strategy
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Strategy = default_strategy
|
||||
>
|
||||
struct area_result
|
||||
: detail::area::area_result
|
||||
<
|
||||
typename detail::select_geometry_type
|
||||
<
|
||||
Geometry,
|
||||
detail::area::more_precise_coordinate_type
|
||||
>::type,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct area_result<Geometry, default_strategy>
|
||||
: detail::area::default_area_result
|
||||
<
|
||||
typename detail::select_geometry_type
|
||||
<
|
||||
Geometry,
|
||||
detail::area::more_precise_default_area_result
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_RESULT_HPP
|
||||
@@ -5,6 +5,11 @@
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2020-2023.
|
||||
// Modifications copyright (c) 2020-2023 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
@@ -15,35 +20,21 @@
|
||||
#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/append.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/convert.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/core/static_assert.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -230,40 +221,36 @@ struct assign
|
||||
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>)
|
||||
);
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(
|
||||
same_point_order,
|
||||
"Assign is not supported for different point orders.",
|
||||
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>)
|
||||
);
|
||||
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(
|
||||
same_closure,
|
||||
"Assign is not supported for different closures.",
|
||||
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
|
||||
{
|
||||
@@ -275,7 +262,7 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
(geometry1, m_geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
@@ -283,19 +270,19 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, 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
|
||||
{
|
||||
@@ -307,7 +294,7 @@ struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
(m_geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline void
|
||||
apply(Geometry1& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
|
||||
@@ -315,8 +302,8 @@ struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
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)> >
|
||||
{
|
||||
@@ -335,7 +322,7 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM
|
||||
(geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
|
||||
@@ -343,9 +330,9 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM
|
||||
return boost::apply_visitor(visitor(), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Assigns one geometry to another geometry
|
||||
|
||||
221
linx64/include/boost/geometry/algorithms/azimuth.hpp
Normal file
221
linx64/include/boost/geometry/algorithms/azimuth.hpp
Normal file
@@ -0,0 +1,221 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014-2023.
|
||||
// Modifications copyright (c) 2014-2023, 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_AZIMUTH_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/azimuth/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/azimuth/geographic.hpp>
|
||||
#include <boost/geometry/strategies/azimuth/spherical.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
} // namespace detail
|
||||
#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 azimuth : not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct azimuth<Point1, Point2, point_tag, point_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static auto apply(Point1 const& p1, Point2 const& p2, Strategy const& strategy)
|
||||
{
|
||||
typedef typename decltype(strategy.azimuth())::template result_type
|
||||
<
|
||||
typename coordinate_type<Point1>::type,
|
||||
typename coordinate_type<Point2>::type
|
||||
>::type calc_t;
|
||||
|
||||
calc_t result = 0;
|
||||
calc_t const x1 = geometry::get_as_radian<0>(p1);
|
||||
calc_t const y1 = geometry::get_as_radian<1>(p1);
|
||||
calc_t const x2 = geometry::get_as_radian<0>(p2);
|
||||
calc_t const y2 = geometry::get_as_radian<1>(p2);
|
||||
|
||||
strategy.azimuth().apply(x1, y1, x2, y2, result);
|
||||
|
||||
// NOTE: It is not clear which units we should use for the result.
|
||||
// For now radians are always returned but a user could expect
|
||||
// e.g. something like this:
|
||||
/*
|
||||
bool const both_degree = std::is_same
|
||||
<
|
||||
typename detail::cs_angular_units<Point1>::type,
|
||||
geometry::degree
|
||||
>::value
|
||||
&& std::is_same
|
||||
<
|
||||
typename detail::cs_angular_units<Point2>::type,
|
||||
geometry::degree
|
||||
>::value;
|
||||
if (both_degree)
|
||||
{
|
||||
result *= math::r2d<calc_t>();
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct azimuth
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
|
||||
{
|
||||
return dispatch::azimuth<P1, P2>::apply(p1, p2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct azimuth<Strategy, false>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
|
||||
{
|
||||
using strategies::azimuth::services::strategy_converter;
|
||||
return dispatch::azimuth
|
||||
<
|
||||
P1, P2
|
||||
>::apply(p1, p2, strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct azimuth<default_strategy, false>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
static auto apply(P1 const& p1, P2 const& p2, default_strategy)
|
||||
{
|
||||
typedef typename strategies::azimuth::services::default_strategy
|
||||
<
|
||||
P1, P2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::azimuth<P1, P2>::apply(p1, p2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Calculate azimuth of a segment defined by a pair of points.
|
||||
\ingroup azimuth
|
||||
\tparam Point1 Type of the first point of a segment.
|
||||
\tparam Point2 Type of the second point of a segment.
|
||||
\param point1 First point of a segment.
|
||||
\param point2 Second point of a segment.
|
||||
\return Azimuth in radians.
|
||||
|
||||
\qbk{[include reference/algorithms/azimuth.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[azimuth]
|
||||
[azimuth_output]
|
||||
}
|
||||
*/
|
||||
template <typename Point1, typename Point2>
|
||||
inline auto azimuth(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
concepts::check<Point1 const>();
|
||||
concepts::check<Point2 const>();
|
||||
|
||||
return resolve_strategy::azimuth
|
||||
<
|
||||
default_strategy
|
||||
>::apply(point1, point2, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Calculate azimuth of a segment defined by a pair of points.
|
||||
\ingroup azimuth
|
||||
\tparam Point1 Type of the first point of a segment.
|
||||
\tparam Point2 Type of the second point of a segment.
|
||||
\tparam Strategy Type of an umbrella strategy defining azimuth strategy.
|
||||
\param point1 First point of a segment.
|
||||
\param point2 Second point of a segment.
|
||||
\param strategy Umbrella strategy defining azimuth strategy.
|
||||
\return Azimuth in radians.
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/azimuth.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[azimuth_strategy]
|
||||
[azimuth_strategy_output]
|
||||
}
|
||||
*/
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
inline auto azimuth(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Point1 const>();
|
||||
concepts::check<Point2 const>();
|
||||
|
||||
return resolve_strategy::azimuth<Strategy>::apply(point1, point2, strategy);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP
|
||||
@@ -4,8 +4,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2017-2022.
|
||||
// Modifications copyright (c) 2017-2022 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
|
||||
@@ -18,245 +18,7 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Input,
|
||||
typename Output,
|
||||
typename TagIn = typename tag<Input>::type,
|
||||
typename TagOut = typename tag<Output>::type
|
||||
>
|
||||
struct buffer: not_implemented<TagIn, TagOut>
|
||||
{};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct buffer<BoxIn, BoxOut, box_tag, box_tag>
|
||||
{
|
||||
template <typename Distance>
|
||||
static inline void apply(BoxIn const& box_in, Distance const& distance,
|
||||
Distance const& , BoxOut& box_out)
|
||||
{
|
||||
detail::buffer::buffer_box(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct buffer
|
||||
{
|
||||
template <typename Distance, typename GeometryOut>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Distance const& distance,
|
||||
Distance const& chord_length,
|
||||
GeometryOut& out)
|
||||
{
|
||||
dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Distance, typename GeometryOut>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Distance const& m_distance;
|
||||
Distance const& m_chord_length;
|
||||
GeometryOut& m_out;
|
||||
|
||||
visitor(Distance const& distance,
|
||||
Distance const& chord_length,
|
||||
GeometryOut& out)
|
||||
: m_distance(distance),
|
||||
m_chord_length(chord_length),
|
||||
m_out(out)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry) const
|
||||
{
|
||||
buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Distance, typename GeometryOut>
|
||||
static inline void apply(
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Distance const& distance,
|
||||
Distance const& chord_length,
|
||||
GeometryOut& out
|
||||
)
|
||||
{
|
||||
boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{buffer, \det_buffer}.
|
||||
\tparam Input \tparam_geometry
|
||||
\tparam Output \tparam_geometry
|
||||
\tparam Distance \tparam_numeric
|
||||
\param geometry_in \param_geometry
|
||||
\param geometry_out \param_geometry
|
||||
\param distance The distance to be used for the buffer
|
||||
\param chord_length (optional) The length of the chord's in the generated arcs around points or bends
|
||||
|
||||
\qbk{[include reference/algorithms/buffer.qbk]}
|
||||
*/
|
||||
template <typename Input, typename Output, typename Distance>
|
||||
inline void buffer(Input const& geometry_in, Output& geometry_out,
|
||||
Distance const& distance, Distance const& chord_length = -1)
|
||||
{
|
||||
concepts::check<Input const>();
|
||||
concepts::check<Output>();
|
||||
|
||||
resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
|
||||
\tparam Input \tparam_geometry
|
||||
\tparam Output \tparam_geometry
|
||||
\tparam Distance \tparam_numeric
|
||||
\param geometry \param_geometry
|
||||
\param distance The distance to be used for the buffer
|
||||
\param chord_length (optional) The length of the chord's in the generated arcs
|
||||
around points or bends (RESERVED, NOT YET USED)
|
||||
\return \return_calc{buffer}
|
||||
*/
|
||||
template <typename Output, typename Input, typename Distance>
|
||||
Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
|
||||
{
|
||||
concepts::check<Input const>();
|
||||
concepts::check<Output>();
|
||||
|
||||
Output geometry_out;
|
||||
|
||||
resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);
|
||||
|
||||
return geometry_out;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{buffer, \det_buffer}.
|
||||
\tparam GeometryIn \tparam_geometry
|
||||
\tparam MultiPolygon \tparam_geometry{MultiPolygon}
|
||||
\tparam DistanceStrategy A strategy defining distance (or radius)
|
||||
\tparam SideStrategy A strategy defining creation along sides
|
||||
\tparam JoinStrategy A strategy defining creation around convex corners
|
||||
\tparam EndStrategy A strategy defining creation at linestring ends
|
||||
\tparam PointStrategy A strategy defining creation around points
|
||||
\param geometry_in \param_geometry
|
||||
\param geometry_out output multi polygon (or std:: collection of polygons),
|
||||
will contain a buffered version of the input geometry
|
||||
\param distance_strategy The distance strategy to be used
|
||||
\param side_strategy The side strategy to be used
|
||||
\param join_strategy The join strategy to be used
|
||||
\param end_strategy The end strategy to be used
|
||||
\param point_strategy The point strategy to be used
|
||||
|
||||
\qbk{distinguish,with strategies}
|
||||
\qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename GeometryIn,
|
||||
typename MultiPolygon,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy
|
||||
>
|
||||
inline void buffer(GeometryIn const& geometry_in,
|
||||
MultiPolygon& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
typedef typename boost::range_value<MultiPolygon>::type polygon_type;
|
||||
concepts::check<GeometryIn const>();
|
||||
concepts::check<polygon_type>();
|
||||
|
||||
typedef typename point_type<GeometryIn>::type point_type;
|
||||
typedef typename rescale_policy_type<point_type>::type rescale_policy_type;
|
||||
|
||||
geometry_out.clear();
|
||||
|
||||
if (geometry::is_empty(geometry_in))
|
||||
{
|
||||
// Then output geometry is kept empty as well
|
||||
return;
|
||||
}
|
||||
|
||||
model::box<point_type> box;
|
||||
geometry::envelope(geometry_in, box);
|
||||
geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
|
||||
|
||||
typename strategy::intersection::services::default_strategy
|
||||
<
|
||||
typename cs_tag<GeometryIn>::type
|
||||
>::type intersection_strategy;
|
||||
|
||||
rescale_policy_type rescale_policy
|
||||
= boost::geometry::get_rescale_policy<rescale_policy_type>(box);
|
||||
|
||||
detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
|
||||
distance_strategy,
|
||||
side_strategy,
|
||||
join_strategy,
|
||||
end_strategy,
|
||||
point_strategy,
|
||||
intersection_strategy,
|
||||
rescale_policy);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/algorithms/detail/buffer/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/implementation.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
// 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
|
||||
// This file was modified by Oracle on 2014-2023.
|
||||
// Modifications copyright (c) 2014-2023 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.
|
||||
@@ -25,41 +25,39 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.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/core/visit.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#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/centroid/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/centroid/geographic.hpp>
|
||||
#include <boost/geometry/strategies/centroid/spherical.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/strategies/detail.hpp>
|
||||
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -116,56 +114,24 @@ struct centroid_point
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Indexed, Point
|
||||
>::apply(indexed, centroid);
|
||||
>::type coordinate_type;
|
||||
|
||||
detail::for_each_dimension<Indexed>([&](auto dimension)
|
||||
{
|
||||
coordinate_type const c1 = get<min_corner, dimension>(indexed);
|
||||
coordinate_type const c2 = get<max_corner, dimension>(indexed);
|
||||
coordinate_type const two = 2;
|
||||
set<dimension>(centroid, (c1 + c2) / two);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -201,25 +167,19 @@ inline bool range_ok(Range const& range, Point& centroid)
|
||||
/*!
|
||||
\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>
|
||||
template<typename Ring, typename PointTransformer, typename Strategy, typename State>
|
||||
static inline void apply(Ring const& ring,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
typename Strategy::state_type& state)
|
||||
State& 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);
|
||||
detail::closed_view<Ring const> const view(ring);
|
||||
auto it = boost::begin(view);
|
||||
auto const end = boost::end(view);
|
||||
|
||||
if (it != end)
|
||||
{
|
||||
@@ -231,6 +191,7 @@ struct centroid_range_state
|
||||
typename PointTransformer::result_type
|
||||
pt = transformer.apply(*it);
|
||||
|
||||
using point_type = typename geometry::point_type<Ring const>::type;
|
||||
strategy.apply(static_cast<point_type const&>(previous_pt),
|
||||
static_cast<point_type const&>(pt),
|
||||
state);
|
||||
@@ -241,7 +202,6 @@ struct centroid_range_state
|
||||
}
|
||||
};
|
||||
|
||||
template <closure_selector Closure>
|
||||
struct centroid_range
|
||||
{
|
||||
template<typename Range, typename Point, typename Strategy>
|
||||
@@ -252,11 +212,15 @@ struct centroid_range
|
||||
{
|
||||
// prepare translation transformer
|
||||
translating_transformer<Range> transformer(*boost::begin(range));
|
||||
|
||||
typename Strategy::state_type state;
|
||||
centroid_range_state<Closure>::apply(range, transformer,
|
||||
strategy, state);
|
||||
|
||||
|
||||
typename Strategy::template state_type
|
||||
<
|
||||
typename geometry::point_type<Range>::type,
|
||||
Point
|
||||
>::type state;
|
||||
|
||||
centroid_range_state::apply(range, transformer, strategy, state);
|
||||
|
||||
if ( strategy.result(state, centroid) )
|
||||
{
|
||||
// translate the result back
|
||||
@@ -277,24 +241,19 @@ struct centroid_range
|
||||
*/
|
||||
struct centroid_polygon_state
|
||||
{
|
||||
template<typename Polygon, typename PointTransformer, typename Strategy>
|
||||
template<typename Polygon, typename PointTransformer, typename Strategy, typename State>
|
||||
static inline void apply(Polygon const& poly,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
typename Strategy::state_type& state)
|
||||
State& state)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;
|
||||
centroid_range_state::apply(exterior_ring(poly), transformer, strategy, state);
|
||||
|
||||
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)
|
||||
auto const& rings = interior_rings(poly);
|
||||
auto const end = boost::end(rings);
|
||||
for (auto it = boost::begin(rings); it != end; ++it)
|
||||
{
|
||||
per_ring::apply(*it, transformer, strategy, state);
|
||||
centroid_range_state::apply(*it, transformer, strategy, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -310,10 +269,15 @@ struct centroid_polygon
|
||||
// prepare translation transformer
|
||||
translating_transformer<Polygon>
|
||||
transformer(*boost::begin(exterior_ring(poly)));
|
||||
|
||||
typename Strategy::state_type state;
|
||||
|
||||
typename Strategy::template state_type
|
||||
<
|
||||
typename geometry::point_type<Polygon>::type,
|
||||
Point
|
||||
>::type state;
|
||||
|
||||
centroid_polygon_state::apply(poly, transformer, strategy, state);
|
||||
|
||||
|
||||
if ( strategy.result(state, centroid) )
|
||||
{
|
||||
// translate the result back
|
||||
@@ -333,11 +297,11 @@ struct centroid_polygon
|
||||
*/
|
||||
struct centroid_multi_point_state
|
||||
{
|
||||
template <typename Point, typename PointTransformer, typename Strategy>
|
||||
template <typename Point, typename PointTransformer, typename Strategy, typename State>
|
||||
static inline void apply(Point const& point,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
typename Strategy::state_type& state)
|
||||
State& state)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
strategy.apply(static_cast<Point const&>(transformer.apply(point)),
|
||||
@@ -374,23 +338,24 @@ struct centroid_multi
|
||||
// prepare translation transformer
|
||||
translating_transformer<Multi> transformer(multi);
|
||||
|
||||
typename Strategy::state_type state;
|
||||
typename Strategy::template state_type
|
||||
<
|
||||
typename geometry::point_type<Multi>::type,
|
||||
Point
|
||||
>::type state;
|
||||
|
||||
for (typename boost::range_iterator<Multi const>::type
|
||||
it = boost::begin(multi);
|
||||
it != boost::end(multi);
|
||||
++it)
|
||||
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
|
||||
{
|
||||
Policy::apply(*it, transformer, strategy, state);
|
||||
}
|
||||
|
||||
if ( strategy.result(state, centroid) )
|
||||
if (strategy.result(state, centroid))
|
||||
{
|
||||
// translate the result back
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -399,18 +364,30 @@ struct centroid_multi
|
||||
template <typename Algorithm>
|
||||
struct centroid_linear_areal
|
||||
{
|
||||
template <typename Geometry, typename Point, typename Strategy>
|
||||
template <typename Geometry, typename Point, typename Strategies>
|
||||
static inline void apply(Geometry const& geom,
|
||||
Point& centroid,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( ! Algorithm::apply(geom, centroid, strategy) )
|
||||
if ( ! Algorithm::apply(geom, centroid, strategies.centroid(geom)) )
|
||||
{
|
||||
geometry::point_on_border(centroid, geom);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Algorithm>
|
||||
struct centroid_pointlike
|
||||
{
|
||||
template <typename Geometry, typename Point, typename Strategies>
|
||||
static inline void apply(Geometry const& geom,
|
||||
Point& centroid,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
Algorithm::apply(geom, centroid, strategies.centroid(geom));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::centroid
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
@@ -447,7 +424,7 @@ template <typename Ring>
|
||||
struct centroid<Ring, ring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_range<geometry::closure<Ring>::value>
|
||||
detail::centroid::centroid_range
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -455,7 +432,7 @@ template <typename Linestring>
|
||||
struct centroid<Linestring, linestring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_range<closed>
|
||||
detail::centroid::centroid_range
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -473,7 +450,7 @@ struct centroid<MultiLinestring, multi_linestring_tag>
|
||||
<
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_range_state<closed>
|
||||
detail::centroid::centroid_range_state
|
||||
>
|
||||
>
|
||||
{};
|
||||
@@ -491,9 +468,12 @@ struct centroid<MultiPolygon, multi_polygon_tag>
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct centroid<MultiPoint, multi_point_tag>
|
||||
: detail::centroid::centroid_multi
|
||||
: detail::centroid::centroid_pointlike
|
||||
<
|
||||
detail::centroid::centroid_multi_point_state
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_multi_point_state
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -504,84 +484,81 @@ struct centroid<MultiPoint, multi_point_tag>
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
template <typename Geometry>
|
||||
template
|
||||
<
|
||||
typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct centroid
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry const& geometry, Point& out, Strategies const& strategies)
|
||||
{
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct centroid<Strategy, false>
|
||||
{
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
|
||||
{
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategy);
|
||||
using strategies::centroid::services::strategy_converter;
|
||||
dispatch::centroid
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, out, strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
template <>
|
||||
struct centroid<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry, 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;
|
||||
typedef typename strategies::centroid::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type strategies_type;
|
||||
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategy_type());
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategies_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_dynamic {
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
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);
|
||||
resolve_strategy::centroid<Strategy>::apply(geometry, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
struct centroid<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Point& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
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);
|
||||
centroid<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -602,10 +579,9 @@ struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
|
||||
*/
|
||||
template<typename Geometry, typename Point, typename Strategy>
|
||||
inline void centroid(Geometry const& geometry, Point& c,
|
||||
Strategy const& strategy)
|
||||
inline void centroid(Geometry const& geometry, Point& c, Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::centroid<Geometry>::apply(geometry, c, strategy);
|
||||
resolve_dynamic::centroid<Geometry>::apply(geometry, c, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2020-2023.
|
||||
// Modifications copyright (c) 2020-2023, 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
@@ -15,19 +20,16 @@
|
||||
#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 <type_traits>
|
||||
|
||||
#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/core/visit.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // for backward compatibility
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
@@ -54,14 +56,14 @@ struct polygon_clear
|
||||
{
|
||||
traits::clear
|
||||
<
|
||||
typename boost::remove_reference
|
||||
typename std::remove_reference
|
||||
<
|
||||
typename traits::interior_mutable_type<Polygon>::type
|
||||
>::type
|
||||
>::apply(interior_rings(polygon));
|
||||
traits::clear
|
||||
<
|
||||
typename boost::remove_reference
|
||||
typename std::remove_reference
|
||||
<
|
||||
typename traits::ring_mutable_type<Polygon>::type
|
||||
>::type
|
||||
@@ -133,40 +135,31 @@ struct clear<Geometry, multi_tag>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
static void apply(Geometry& geometry)
|
||||
{
|
||||
traits::visit<Geometry>::apply([](auto & g)
|
||||
{
|
||||
clear<std::remove_reference_t<decltype(g)>>::apply(g);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear
|
||||
struct clear<Geometry, geometry_collection_tag>
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
static void apply(Geometry& geometry)
|
||||
{
|
||||
dispatch::clear<Geometry>::apply(geometry);
|
||||
traits::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
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
/*!
|
||||
@@ -187,7 +180,7 @@ inline void clear(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
resolve_variant::clear<Geometry>::apply(geometry);
|
||||
dispatch::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
|
||||
|
||||
16
linx64/include/boost/geometry/algorithms/closest_points.hpp
Normal file
16
linx64/include/boost/geometry/algorithms/closest_points.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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_CLOSEST_POINTS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINTS_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/closest_points/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_points/implementation.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINTS_HPP
|
||||
@@ -5,8 +5,9 @@
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017-2023.
|
||||
// Modifications copyright (c) 2017-2023, 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -21,38 +22,33 @@
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#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/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/for_each.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.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>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -128,7 +124,7 @@ struct segment_to_range
|
||||
{
|
||||
traits::resize<Range>::apply(range, 2);
|
||||
|
||||
typename boost::range_iterator<Range>::type it = boost::begin(range);
|
||||
auto it = boost::begin(range);
|
||||
|
||||
assign_point_from_index<0>(segment, *it);
|
||||
++it;
|
||||
@@ -144,17 +140,6 @@ template
|
||||
>
|
||||
struct range_to_range
|
||||
{
|
||||
typedef typename reversible_view
|
||||
<
|
||||
Range1 const,
|
||||
Reverse ? iterate_reverse : iterate_forward
|
||||
>::type rview_type;
|
||||
typedef typename closeable_view
|
||||
<
|
||||
rview_type const,
|
||||
geometry::closure<Range1>::value
|
||||
>::type view_type;
|
||||
|
||||
struct default_policy
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
@@ -163,7 +148,7 @@ struct range_to_range
|
||||
geometry::detail::conversion::convert_point_to_point(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static inline void apply(Range1 const& source, Range2& destination)
|
||||
{
|
||||
apply(source, destination, default_policy());
|
||||
@@ -175,11 +160,16 @@ struct range_to_range
|
||||
{
|
||||
geometry::clear(destination);
|
||||
|
||||
rview_type rview(source);
|
||||
using view_type = detail::closed_clockwise_view
|
||||
<
|
||||
Range1 const,
|
||||
geometry::closure<Range1>::value,
|
||||
Reverse ? counterclockwise : clockwise
|
||||
>;
|
||||
|
||||
// We consider input always as closed, and skip last
|
||||
// point for open output.
|
||||
view_type view(rview);
|
||||
view_type const view(source);
|
||||
|
||||
typedef typename boost::range_size<Range1>::type size_type;
|
||||
size_type n = boost::size(view);
|
||||
@@ -192,8 +182,7 @@ struct range_to_range
|
||||
// but ok, sice below it == end()
|
||||
|
||||
size_type i = 0;
|
||||
for (typename boost::range_iterator<view_type const>::type it
|
||||
= boost::begin(view);
|
||||
for (auto it = boost::begin(view);
|
||||
it != boost::end(view) && i < n;
|
||||
++it, ++i)
|
||||
{
|
||||
@@ -227,21 +216,17 @@ struct polygon_to_polygon
|
||||
// Container should be resizeable
|
||||
traits::resize
|
||||
<
|
||||
typename boost::remove_reference
|
||||
typename std::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);
|
||||
auto const& rings_source = interior_rings(source);
|
||||
auto&& 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);
|
||||
auto it_source = boost::begin(rings_source);
|
||||
auto it_dest = boost::begin(rings_dest);
|
||||
|
||||
for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
|
||||
{
|
||||
@@ -269,10 +254,8 @@ struct multi_to_multi: private Policy
|
||||
{
|
||||
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);
|
||||
auto it1 = boost::begin(multi1);
|
||||
auto it2 = boost::begin(multi2);
|
||||
|
||||
for (; it1 != boost::end(multi1); ++it1, ++it2)
|
||||
{
|
||||
@@ -290,16 +273,25 @@ struct multi_to_multi: private Policy
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
// TODO: We could use std::is_assignable instead of std::is_same.
|
||||
// Then we should rather check ! std::is_array<Geometry2>::value
|
||||
// which is Destination.
|
||||
|
||||
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
|
||||
bool UseAssignment = std::is_same<Geometry1, Geometry2>::value
|
||||
&& !std::is_array<Geometry1>::value
|
||||
>
|
||||
struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >
|
||||
struct convert
|
||||
: not_implemented
|
||||
<
|
||||
Tag1, Tag2,
|
||||
std::integral_constant<std::size_t, DimensionCount>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
@@ -457,7 +449,7 @@ struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
|
||||
|
||||
// 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
|
||||
// version types might be the same and therefore we call std::is_same again
|
||||
|
||||
template <typename Multi1, typename Multi2, std::size_t DimensionCount>
|
||||
struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2014, 2015, 2020.
|
||||
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -20,356 +21,7 @@
|
||||
#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
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convex_hull/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017-2023.
|
||||
// Modifications copyright (c) 2017-2023 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -21,33 +22,31 @@
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/correct_closure.hpp>
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/mutable_range.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/correct_closure.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
|
||||
#include <boost/geometry/util/order_as_direction.hpp>
|
||||
#include <boost/geometry/algorithms/detail/visit.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/visit.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/area/geographic.hpp>
|
||||
#include <boost/geometry/strategies/area/spherical.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -62,92 +61,56 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace correct
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_nop
|
||||
{
|
||||
template <typename Strategy>
|
||||
template <typename Geometry, typename Strategy>
|
||||
static inline void apply(Geometry& , Strategy const& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct correct_box_loop
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
static inline void apply(Box& box)
|
||||
{
|
||||
if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
|
||||
{
|
||||
// Swap the coordinates
|
||||
coordinate_type max_value = get<min_corner, Dimension>(box);
|
||||
coordinate_type min_value = get<max_corner, Dimension>(box);
|
||||
set<min_corner, Dimension>(box, min_value);
|
||||
set<max_corner, Dimension>(box, max_value);
|
||||
}
|
||||
|
||||
correct_box_loop
|
||||
<
|
||||
Box, Dimension + 1, DimensionCount
|
||||
>::apply(box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename Box, std::size_t DimensionCount>
|
||||
struct correct_box_loop<Box, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Box& )
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Correct a box: make min/max correct
|
||||
template <typename Box>
|
||||
struct correct_box
|
||||
{
|
||||
template <typename Strategy>
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Box& box, Strategy const& )
|
||||
{
|
||||
using coordinate_type = typename geometry::coordinate_type<Box>::type;
|
||||
|
||||
// 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);
|
||||
detail::for_each_dimension<Box>([&](auto dimension)
|
||||
{
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Close a ring, if not closed
|
||||
template <typename Ring, template <typename> class Predicate>
|
||||
template <typename Predicate = std::less<>>
|
||||
struct correct_ring
|
||||
{
|
||||
typedef typename point_type<Ring>::type point_type;
|
||||
typedef typename coordinate_type<Ring>::type coordinate_type;
|
||||
|
||||
typedef detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Ring>::value>::value,
|
||||
geometry::closure<Ring>::value
|
||||
> ring_area_type;
|
||||
|
||||
|
||||
template <typename Strategy>
|
||||
template <typename Ring, typename Strategy>
|
||||
static inline void apply(Ring& r, Strategy const& strategy)
|
||||
{
|
||||
// Correct closure if necessary
|
||||
detail::correct_closure::close_or_open_ring<Ring>::apply(r);
|
||||
detail::correct_closure::close_or_open_ring::apply(r);
|
||||
|
||||
// NOTE: calculate_point_order should probably be used here instead.
|
||||
|
||||
// Check area
|
||||
typedef typename area_result<Ring, Strategy>::type area_result_type;
|
||||
Predicate<area_result_type> predicate;
|
||||
area_result_type const zero = 0;
|
||||
if (predicate(ring_area_type::apply(r, strategy), zero))
|
||||
using area_t = typename area_result<Ring, Strategy>::type;
|
||||
area_t const zero = 0;
|
||||
if (Predicate()(detail::area::ring_area::apply(r, strategy), zero))
|
||||
{
|
||||
std::reverse(boost::begin(r), boost::end(r));
|
||||
}
|
||||
@@ -156,30 +119,18 @@ struct correct_ring
|
||||
|
||||
// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all
|
||||
// inner rings counter clockwise (or vice versa depending on orientation)
|
||||
template <typename Polygon>
|
||||
struct correct_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
template <typename Strategy>
|
||||
template <typename Polygon, typename Strategy>
|
||||
static inline void apply(Polygon& poly, Strategy const& strategy)
|
||||
{
|
||||
correct_ring
|
||||
<
|
||||
ring_type,
|
||||
std::less
|
||||
>::apply(exterior_ring(poly), strategy);
|
||||
correct_ring<std::less<>>::apply(exterior_ring(poly), strategy);
|
||||
|
||||
typename interior_return_type<Polygon>::type
|
||||
rings = interior_rings(poly);
|
||||
for (typename detail::interior_iterator<Polygon>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
auto&& rings = interior_rings(poly);
|
||||
auto const end = boost::end(rings);
|
||||
for (auto it = boost::begin(rings); it != end; ++it)
|
||||
{
|
||||
correct_ring
|
||||
<
|
||||
ring_type,
|
||||
std::greater
|
||||
>::apply(*it, strategy);
|
||||
correct_ring<std::greater<>>::apply(*it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -199,62 +150,51 @@ struct correct: not_implemented<Tag>
|
||||
|
||||
template <typename Point>
|
||||
struct correct<Point, point_tag>
|
||||
: detail::correct::correct_nop<Point>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
template <typename LineString>
|
||||
struct correct<LineString, linestring_tag>
|
||||
: detail::correct::correct_nop<LineString>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct correct<Segment, segment_tag>
|
||||
: detail::correct::correct_nop<Segment>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct correct<Box, box_tag>
|
||||
: detail::correct::correct_box<Box>
|
||||
: detail::correct::correct_box
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct correct<Ring, ring_tag>
|
||||
: detail::correct::correct_ring
|
||||
<
|
||||
Ring,
|
||||
std::less
|
||||
>
|
||||
: detail::correct::correct_ring<>
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct correct<Polygon, polygon_tag>
|
||||
: detail::correct::correct_polygon<Polygon>
|
||||
: detail::correct::correct_polygon
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct correct<MultiPoint, multi_point_tag>
|
||||
: detail::correct::correct_nop<MultiPoint>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLineString>
|
||||
struct correct<MultiLineString, multi_linestring_tag>
|
||||
: detail::correct::correct_nop<MultiLineString>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct<Geometry, multi_polygon_tag>
|
||||
: detail::multi_modify
|
||||
<
|
||||
Geometry,
|
||||
detail::correct::correct_polygon
|
||||
<
|
||||
typename boost::range_value<Geometry>::type
|
||||
>
|
||||
>
|
||||
: detail::multi_modify<detail::correct::correct_polygon>
|
||||
{};
|
||||
|
||||
|
||||
@@ -262,45 +202,96 @@ struct correct<Geometry, multi_polygon_tag>
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct correct
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
dispatch::correct<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct correct<Strategy, false>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
// NOTE: calculate_point_order strategy should probably be used here instead.
|
||||
using geometry::strategies::area::services::strategy_converter;
|
||||
dispatch::correct<Geometry>::apply(geometry, strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct correct<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline void apply(Geometry& geometry, default_strategy const& )
|
||||
{
|
||||
// NOTE: calculate_point_order strategy should probably be used here instead.
|
||||
using strategy_type = typename strategies::area::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type;
|
||||
dispatch::correct<Geometry>::apply(geometry, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
dispatch::correct<Geometry>::apply(geometry, strategy);
|
||||
concepts::check<Geometry>();
|
||||
resolve_strategy::correct<Strategy>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
struct correct<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
static inline void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry& geometry) const
|
||||
traits::visit<Geometry>::apply([&](auto & g)
|
||||
{
|
||||
correct<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
template <typename Geometry>
|
||||
struct correct<Geometry, geometry_collection_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
detail::visit_breadth_first([&](auto & g)
|
||||
{
|
||||
correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
|
||||
return true;
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -318,14 +309,7 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
inline void correct(Geometry& geometry)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type strategy_type;
|
||||
|
||||
resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
|
||||
resolve_dynamic::correct<Geometry>::apply(geometry, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -347,7 +331,7 @@ inline void correct(Geometry& geometry)
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline void correct(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::correct<Geometry>::apply(geometry, strategy);
|
||||
resolve_dynamic::correct<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2020-2023.
|
||||
// Modifications copyright (c) 2020-2023 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)
|
||||
@@ -9,26 +14,18 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -43,59 +40,55 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace correct_closure
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct nop
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline void apply(Geometry& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Close a ring, if not closed, or open it
|
||||
template <typename Ring>
|
||||
struct close_or_open_ring
|
||||
{
|
||||
template <typename Ring>
|
||||
static inline void apply(Ring& r)
|
||||
{
|
||||
if (boost::size(r) <= 2)
|
||||
auto size = boost::size(r);
|
||||
if (size <= 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool const disjoint = geometry::disjoint(*boost::begin(r),
|
||||
*(boost::end(r) - 1));
|
||||
closure_selector const s = geometry::closure<Ring>::value;
|
||||
// TODO: This requires relate(pt, pt) strategy
|
||||
bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
|
||||
closure_selector const closure = geometry::closure<Ring>::value;
|
||||
|
||||
if (disjoint && s == closed)
|
||||
if (disjoint && closure == closed)
|
||||
{
|
||||
// Close it by adding first point
|
||||
geometry::append(r, *boost::begin(r));
|
||||
}
|
||||
else if (! disjoint && s != closed)
|
||||
else if (! disjoint && closure == open)
|
||||
{
|
||||
// Open it by removing last point
|
||||
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
|
||||
range::resize(r, size - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Close/open exterior ring and all its interior rings
|
||||
template <typename Polygon>
|
||||
struct close_or_open_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
template <typename Polygon>
|
||||
static inline void apply(Polygon& poly)
|
||||
{
|
||||
close_or_open_ring<ring_type>::apply(exterior_ring(poly));
|
||||
close_or_open_ring::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)
|
||||
auto&& rings = interior_rings(poly);
|
||||
auto const end = boost::end(rings);
|
||||
for (auto it = boost::begin(rings); it != end; ++it)
|
||||
{
|
||||
close_or_open_ring<ring_type>::apply(*it);
|
||||
close_or_open_ring::apply(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -114,45 +107,45 @@ struct correct_closure: not_implemented<Tag>
|
||||
|
||||
template <typename Point>
|
||||
struct correct_closure<Point, point_tag>
|
||||
: detail::correct_closure::nop<Point>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
template <typename LineString>
|
||||
struct correct_closure<LineString, linestring_tag>
|
||||
: detail::correct_closure::nop<LineString>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct correct_closure<Segment, segment_tag>
|
||||
: detail::correct_closure::nop<Segment>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct correct_closure<Box, box_tag>
|
||||
: detail::correct_closure::nop<Box>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct correct_closure<Ring, ring_tag>
|
||||
: detail::correct_closure::close_or_open_ring<Ring>
|
||||
: detail::correct_closure::close_or_open_ring
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct correct_closure<Polygon, polygon_tag>
|
||||
: detail::correct_closure::close_or_open_polygon<Polygon>
|
||||
: detail::correct_closure::close_or_open_polygon
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct correct_closure<MultiPoint, multi_point_tag>
|
||||
: detail::correct_closure::nop<MultiPoint>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLineString>
|
||||
struct correct_closure<MultiLineString, multi_linestring_tag>
|
||||
: detail::correct_closure::nop<MultiLineString>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
|
||||
@@ -160,11 +153,7 @@ template <typename Geometry>
|
||||
struct correct_closure<Geometry, multi_polygon_tag>
|
||||
: detail::multi_modify
|
||||
<
|
||||
Geometry,
|
||||
detail::correct_closure::close_or_open_polygon
|
||||
<
|
||||
typename boost::range_value<Geometry>::type
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -176,7 +165,7 @@ struct correct_closure<Geometry, multi_polygon_tag>
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct_closure
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
@@ -186,29 +175,37 @@ struct correct_closure
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct correct_closure<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
struct correct_closure<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
struct visitor: boost::static_visitor<void>
|
||||
static void apply(Geometry& geometry)
|
||||
{
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry& geometry) const
|
||||
traits::visit<Geometry>::apply([](auto & g)
|
||||
{
|
||||
correct_closure<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
|
||||
template <typename Geometry>
|
||||
struct correct_closure<Geometry, geometry_collection_tag>
|
||||
{
|
||||
static void apply(Geometry& geometry)
|
||||
{
|
||||
visitor vis;
|
||||
boost::apply_visitor(vis, geometry);
|
||||
detail::visit_breadth_first([](auto & g)
|
||||
{
|
||||
correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
|
||||
return true;
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
// TODO: This algorithm should use relate(pt, pt) strategy
|
||||
|
||||
|
||||
/*!
|
||||
\brief Closes or opens a geometry, according to its type
|
||||
\details Corrects a geometry w.r.t. closure points to all rings which do not
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2013-2022.
|
||||
// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2014-2022.
|
||||
// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -22,15 +22,18 @@
|
||||
|
||||
#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/gc_topological_dimension.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
|
||||
#include <boost/geometry/algorithms/relate.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/relate/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/relate/geographic.hpp>
|
||||
#include <boost/geometry/strategies/relate/spherical.hpp>
|
||||
#include <boost/geometry/views/detail/geometry_collection_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -58,6 +61,82 @@ struct crosses
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct crosses<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
int const dimension1 = detail::gc_topological_dimension(geometry1);
|
||||
int const dimension2 = detail::gc_topological_dimension(geometry2);
|
||||
|
||||
if (dimension1 >= 0 && dimension2 >= 0)
|
||||
{
|
||||
if (dimension1 < dimension2)
|
||||
{
|
||||
return detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_crosses_d1_le_d2_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
else if (dimension1 > dimension2)
|
||||
{
|
||||
return detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_crosses_d2_le_d1_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
else if (dimension1 == 1 && dimension2 == 1)
|
||||
{
|
||||
return detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_crosses_d1_1_d2_1_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1>
|
||||
struct crosses<Geometry1, Geometry2, Tag1, geometry_collection_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using gc1_view_t = detail::geometry_collection_view<Geometry1>;
|
||||
return crosses
|
||||
<
|
||||
gc1_view_t, Geometry2
|
||||
>::apply(gc1_view_t(geometry1), geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag2>
|
||||
struct crosses<Geometry1, Geometry2, geometry_collection_tag, Tag2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using gc2_view_t = detail::geometry_collection_view<Geometry2>;
|
||||
return crosses
|
||||
<
|
||||
Geometry1, gc2_view_t
|
||||
>::apply(geometry1, gc2_view_t(geometry2), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
@@ -65,9 +144,14 @@ struct crosses
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct crosses
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
@@ -75,148 +159,146 @@ struct crosses
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return dispatch::crosses<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
|
||||
return dispatch::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct crosses<Strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
//using strategies::crosses::services::strategy_converter;
|
||||
using strategies::relate::services::strategy_converter;
|
||||
return crosses
|
||||
<
|
||||
decltype(strategy_converter<Strategy>::get(strategy))
|
||||
>::apply(geometry1, geometry2,
|
||||
strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct crosses<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
//typedef typename strategies::crosses::services::default_strategy
|
||||
typedef typename strategies::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return apply(geometry1, geometry2, strategy_type());
|
||||
return crosses
|
||||
<
|
||||
strategy_type
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
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,
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type
|
||||
>
|
||||
struct crosses
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::crosses
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, 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)
|
||||
|
||||
template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
|
||||
struct crosses<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(DynamicGeometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool result = false;
|
||||
traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
result = resolve_strategy::crosses
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, geometry2, strategy);
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
|
||||
struct crosses<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
DynamicGeometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool result = false;
|
||||
traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::crosses
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, g2, strategy);
|
||||
}, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename DynamicGeometry1, typename DynamicGeometry2>
|
||||
struct crosses<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(DynamicGeometry1 const& geometry1,
|
||||
DynamicGeometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool result = false;
|
||||
traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::crosses
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{crosses}
|
||||
\ingroup crosses
|
||||
@@ -236,7 +318,7 @@ inline bool crosses(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::crosses
|
||||
return resolve_dynamic::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
@@ -252,11 +334,16 @@ inline bool crosses(Geometry1 const& geometry1,
|
||||
\return \return_check2{crosses}
|
||||
|
||||
\qbk{[include reference/algorithms/crosses.qbk]}
|
||||
\qbk{
|
||||
[heading Examples]
|
||||
[crosses]
|
||||
[crosses_output]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::crosses
|
||||
return resolve_dynamic::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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_DEFAULT_AREA_RESULT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DEFAULT_AREA_RESULT_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/area_result.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Meta-function defining return type of area function, using the default strategy
|
||||
\ingroup area
|
||||
\note The strategy defines the return-type (so this situation is different
|
||||
from length, where distance is sqr/sqrt, but length always squared)
|
||||
*/
|
||||
|
||||
template <typename Geometry>
|
||||
struct default_area_result
|
||||
: area_result<Geometry>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DEFAULT_AREA_RESULT_HPP
|
||||
@@ -1,7 +1,9 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2017-2023, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
@@ -11,25 +13,29 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/densify.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/visit.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/visit.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/densify/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/densify/geographic.hpp>
|
||||
#include <boost/geometry/strategies/densify/spherical.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/util/constexpr.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -68,24 +74,24 @@ inline void convert_and_push_back(Range & range, Point const& p)
|
||||
template <bool AppendLastPoint = true>
|
||||
struct densify_range
|
||||
{
|
||||
template <typename FwdRng, typename MutRng, typename T, typename Strategy>
|
||||
template <typename FwdRng, typename MutRng, typename T, typename Strategies>
|
||||
static inline void apply(FwdRng const& rng, MutRng & rng_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
T const& len, Strategies const& strategies)
|
||||
{
|
||||
typedef typename boost::range_iterator<FwdRng const>::type iterator_t;
|
||||
typedef typename boost::range_value<FwdRng>::type point_t;
|
||||
|
||||
iterator_t it = boost::begin(rng);
|
||||
iterator_t end = boost::end(rng);
|
||||
auto it = boost::begin(rng);
|
||||
auto const end = boost::end(rng);
|
||||
|
||||
if (it == end) // empty(rng)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto strategy = strategies.densify(rng);
|
||||
push_back_policy<MutRng> policy(rng_out);
|
||||
|
||||
iterator_t prev = it;
|
||||
auto prev = it;
|
||||
for ( ++it ; it != end ; prev = it++)
|
||||
{
|
||||
point_t const& p0 = *prev;
|
||||
@@ -96,7 +102,7 @@ struct densify_range
|
||||
strategy.apply(p0, p1, policy, len);
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(AppendLastPoint))
|
||||
if BOOST_GEOMETRY_CONSTEXPR (AppendLastPoint)
|
||||
{
|
||||
convert_and_push_back(rng_out, *prev); // back(rng)
|
||||
}
|
||||
@@ -106,25 +112,25 @@ struct densify_range
|
||||
template <bool IsClosed1, bool IsClosed2> // false, X
|
||||
struct densify_ring
|
||||
{
|
||||
template <typename Geometry, typename GeometryOut, typename T, typename Strategy>
|
||||
template <typename Geometry, typename GeometryOut, typename T, typename Strategies>
|
||||
static inline void apply(Geometry const& ring, GeometryOut & ring_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
T const& len, Strategies const& strategies)
|
||||
{
|
||||
geometry::detail::densify::densify_range<true>
|
||||
::apply(ring, ring_out, len, strategy);
|
||||
::apply(ring, ring_out, len, strategies);
|
||||
|
||||
if (boost::size(ring) <= 1)
|
||||
return;
|
||||
|
||||
typedef typename point_type<Geometry>::type point_t;
|
||||
point_t const& p0 = range::back(ring);
|
||||
point_t const& p1 = range::front(ring);
|
||||
auto const& p0 = range::back(ring);
|
||||
auto const& p1 = range::front(ring);
|
||||
|
||||
auto strategy = strategies.densify(ring);
|
||||
push_back_policy<GeometryOut> policy(ring_out);
|
||||
|
||||
strategy.apply(p0, p1, policy, len);
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(IsClosed2))
|
||||
if BOOST_GEOMETRY_CONSTEXPR (IsClosed2)
|
||||
{
|
||||
convert_and_push_back(ring_out, p1);
|
||||
}
|
||||
@@ -141,6 +147,15 @@ struct densify_ring<true, false>
|
||||
: densify_range<false>
|
||||
{};
|
||||
|
||||
struct densify_convert
|
||||
{
|
||||
template <typename GeometryIn, typename GeometryOut, typename T, typename Strategy>
|
||||
static void apply(GeometryIn const& in, GeometryOut &out,
|
||||
T const& , Strategy const& )
|
||||
{
|
||||
geometry::convert(in, out);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::densify
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
@@ -162,6 +177,26 @@ struct densify
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, point_tag, point_tag>
|
||||
: geometry::detail::densify::densify_convert
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, segment_tag, segment_tag>
|
||||
: geometry::detail::densify::densify_convert
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, box_tag, box_tag>
|
||||
: geometry::detail::densify::densify_convert
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, multi_point_tag, multi_point_tag>
|
||||
: geometry::detail::densify::densify_convert
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
|
||||
: geometry::detail::densify::densify_range<>
|
||||
@@ -260,43 +295,72 @@ struct densify<Geometry, GeometryOut, multi_polygon_tag, multi_polygon_tag>
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct densify
|
||||
{
|
||||
template <typename Geometry, typename Distance, typename Strategy>
|
||||
template <typename Geometry, typename Distance>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
dispatch::densify
|
||||
<
|
||||
Geometry, Geometry
|
||||
>::apply(geometry, out, max_distance, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct densify<Strategy, false>
|
||||
{
|
||||
template <typename Geometry, typename Distance>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
dispatch::densify<Geometry, Geometry>
|
||||
::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
using strategies::densify::services::strategy_converter;
|
||||
|
||||
dispatch::densify
|
||||
<
|
||||
Geometry, Geometry
|
||||
>::apply(geometry, out, max_distance,
|
||||
strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct densify<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry, typename Distance>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
default_strategy)
|
||||
default_strategy const&)
|
||||
{
|
||||
typedef typename strategy::densify::services::default_strategy
|
||||
typedef typename strategies::densify::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
/*BOOST_CONCEPT_ASSERT(
|
||||
(concepts::DensifyStrategy<strategy_type>)
|
||||
);*/
|
||||
Geometry
|
||||
>::type strategies_type;
|
||||
|
||||
apply(geometry, out, max_distance, strategy_type());
|
||||
dispatch::densify
|
||||
<
|
||||
Geometry, Geometry
|
||||
>::apply(geometry, out, max_distance, strategies_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_dynamic {
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct densify
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
@@ -305,47 +369,55 @@ struct densify
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_strategy::densify::apply(geometry, out, max_distance, strategy);
|
||||
resolve_strategy::densify
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
struct densify<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Distance const& m_max_distance;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Distance const& max_distance, Strategy const& strategy)
|
||||
: m_max_distance(max_distance)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry, Geometry& out) const
|
||||
{
|
||||
densify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Distance, typename Strategy>
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
|
||||
apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(
|
||||
visitor<Distance, Strategy>(max_distance, strategy),
|
||||
geometry,
|
||||
out
|
||||
);
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
using geom_t = util::remove_cref_t<decltype(g)>;
|
||||
geom_t o;
|
||||
densify<geom_t>::apply(g, o, max_distance, strategy);
|
||||
out = std::move(o);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
template <typename Geometry>
|
||||
struct densify<Geometry, geometry_collection_tag>
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
static inline void
|
||||
apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
using geom_t = util::remove_cref_t<decltype(g)>;
|
||||
geom_t o;
|
||||
densify<geom_t>::apply(g, o, max_distance, strategy);
|
||||
traits::emplace_back<Geometry>::apply(out, std::move(o));
|
||||
return true;
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -391,7 +463,7 @@ inline void densify(Geometry const& geometry,
|
||||
|
||||
geometry::clear(out);
|
||||
|
||||
resolve_variant::densify
|
||||
resolve_dynamic::densify
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, out, max_distance, strategy);
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
// 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
|
||||
@@ -4,6 +4,10 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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.
|
||||
|
||||
@@ -17,8 +21,12 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -49,10 +57,14 @@ 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);
|
||||
detail::for_each_dimension<Geometry>([&](auto dimension)
|
||||
{
|
||||
geometry::set<Index, dimension>(geometry,
|
||||
boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>(geometry::get<dimension>(point)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +89,14 @@ 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);
|
||||
detail::for_each_dimension<Geometry>([&](auto dimension)
|
||||
{
|
||||
geometry::set<dimension>(point,
|
||||
boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<Point>::type
|
||||
>(geometry::get<Index, dimension>(geometry)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2018-2021.
|
||||
// Modifications copyright (c) 2018-2021, 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
|
||||
@@ -21,26 +22,24 @@
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#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/static_assert.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -51,33 +50,18 @@ 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);
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const zero = 0;
|
||||
detail::for_each_dimension<Point>([&](auto dimension)
|
||||
{
|
||||
set<dimension>(point, zero);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,15 +72,15 @@ 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;
|
||||
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
|
||||
|
||||
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, geometry::bounds<bound_type>::highest()
|
||||
);
|
||||
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, geometry::bounds<bound_type>::lowest()
|
||||
);
|
||||
coordinate_type const highest = geometry::bounds<coordinate_type>::highest();
|
||||
coordinate_type const lowest = geometry::bounds<coordinate_type>::lowest();
|
||||
detail::for_each_dimension<BoxOrSegment>([&](auto dimension)
|
||||
{
|
||||
set<0, dimension>(geometry, highest);
|
||||
set<1, dimension>(geometry, lowest);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
@@ -109,12 +93,12 @@ struct assign_zero_box_or_segment
|
||||
{
|
||||
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()
|
||||
);
|
||||
coordinate_type const zero = 0;
|
||||
detail::for_each_dimension<BoxOrSegment>([&](auto dimension)
|
||||
{
|
||||
set<0, dimension>(geometry, zero);
|
||||
set<1, dimension>(geometry, zero);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,90 +123,6 @@ inline void assign_box_2d_corner(Box const& box, Point& point)
|
||||
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
@@ -254,11 +154,9 @@ 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>)
|
||||
);
|
||||
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
|
||||
"Not or not yet implemented for this Geometry type.",
|
||||
GeometryTag, Geometry, std::integral_constant<std::size_t, DimensionCount>);
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2016, 2017.
|
||||
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
#include <boost/geometry/formulas/vincenty_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/srs/spheroid.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// An azimuth is an angle between a vector/segment from origin to a point of
|
||||
// interest and a reference vector. Typically north-based azimuth is used.
|
||||
// North direction is used as a reference, angle is measured clockwise
|
||||
// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS
|
||||
// the reference vector is Y axis, angle is measured clockwise.
|
||||
// http://en.wikipedia.org/wiki/Azimuth
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace detail_dispatch
|
||||
{
|
||||
|
||||
template <typename ReturnType, typename Tag>
|
||||
struct azimuth
|
||||
: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, geographic_tag>
|
||||
{
|
||||
template <typename P1, typename P2, typename Spheroid>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)
|
||||
{
|
||||
return geometry::formula::vincenty_inverse<ReturnType, false, true>().apply
|
||||
( get_as_radian<0>(p1), get_as_radian<1>(p1),
|
||||
get_as_radian<0>(p2), get_as_radian<1>(p2),
|
||||
spheroid ).azimuth;
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return apply(p1, p2, srs::spheroid<ReturnType>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, spherical_equatorial_tag>
|
||||
{
|
||||
template <typename P1, typename P2, typename Sphere>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
|
||||
{
|
||||
return geometry::formula::spherical_azimuth<ReturnType, false>
|
||||
( get_as_radian<0>(p1), get_as_radian<1>(p1),
|
||||
get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth;
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return apply(p1, p2, 0); // dummy model
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, spherical_polar_tag>
|
||||
: azimuth<ReturnType, spherical_equatorial_tag>
|
||||
{};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct azimuth<ReturnType, cartesian_tag>
|
||||
{
|
||||
template <typename P1, typename P2, typename Plane>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/)
|
||||
{
|
||||
ReturnType x = get<0>(p2) - get<0>(p1);
|
||||
ReturnType y = get<1>(p2) - get<1>(p1);
|
||||
|
||||
// NOTE: azimuth 0 is at Y axis, increasing right
|
||||
// as in spherical/geographic where 0 is at North axis
|
||||
return atan2(x, y);
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
static inline ReturnType apply(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return apply(p1, p2, 0); // dummy model
|
||||
}
|
||||
};
|
||||
|
||||
} // detail_dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Calculate azimuth between two points.
|
||||
/// The result is in radians.
|
||||
template <typename ReturnType, typename Point1, typename Point2>
|
||||
inline ReturnType azimuth(Point1 const& p1, Point2 const& p2)
|
||||
{
|
||||
return detail_dispatch::azimuth
|
||||
<
|
||||
ReturnType,
|
||||
typename geometry::cs_tag<Point1>::type
|
||||
>::apply(p1, p2);
|
||||
}
|
||||
|
||||
/// Calculate azimuth between two points.
|
||||
/// The result is in radians.
|
||||
template <typename ReturnType, typename Point1, typename Point2, typename Model>
|
||||
inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model)
|
||||
{
|
||||
return detail_dispatch::azimuth
|
||||
<
|
||||
ReturnType,
|
||||
typename geometry::cs_tag<Point1>::type
|
||||
>::apply(p1, p2, model);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
0
linx64/include/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
Executable file → Normal file
0
linx64/include/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
Executable file → Normal file
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2022-2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017-2022.
|
||||
// Modifications copyright (c) 2017-2022 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,
|
||||
@@ -16,30 +17,38 @@
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/direction_code.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/simplify.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/geometries/linestring.hpp>
|
||||
#include <boost/geometry/geometries/ring.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/simplify.hpp>
|
||||
#include <boost/geometry/util/constexpr.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/type_traits.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/normalized_view.hpp>
|
||||
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -49,10 +58,11 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <typename Range, typename DistanceStrategy>
|
||||
inline void simplify_input(Range const& range,
|
||||
DistanceStrategy const& distance,
|
||||
Range& simplified)
|
||||
template <typename RangeIn, typename DistanceStrategy, typename RangeOut, typename Strategies>
|
||||
inline void simplify_input(RangeIn const& range,
|
||||
DistanceStrategy const& distance,
|
||||
RangeOut& simplified,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// We have to simplify the ring before to avoid very small-scaled
|
||||
// features in the original (convex/concave/convex) being enlarged
|
||||
@@ -64,19 +74,10 @@ inline void simplify_input(Range const& range,
|
||||
// look better.
|
||||
// It also gets rid of duplicate points
|
||||
|
||||
typedef typename geometry::point_type<Range>::type point_type;
|
||||
typedef typename strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, segment_tag, point_type
|
||||
>::type ds_strategy_type;
|
||||
typedef strategy::simplify::douglas_peucker
|
||||
<
|
||||
point_type, ds_strategy_type
|
||||
> strategy_type;
|
||||
|
||||
geometry::detail::simplify::simplify_range<2>::apply(range,
|
||||
simplified, distance.simplify_distance(),
|
||||
strategy_type());
|
||||
detail::simplify::douglas_peucker(),
|
||||
strategies);
|
||||
|
||||
}
|
||||
|
||||
@@ -92,10 +93,11 @@ struct buffer_range
|
||||
typename Collection,
|
||||
typename Point,
|
||||
typename DistanceStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline
|
||||
void add_join(Collection& collection,
|
||||
@@ -108,26 +110,15 @@ struct buffer_range
|
||||
output_point_type const& perp2,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& ,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
output_point_type intersection_point;
|
||||
geometry::assign_zero(intersection_point);
|
||||
|
||||
geometry::strategy::buffer::join_selector join
|
||||
= get_join_type(penultimate_input, previous_input, input, strategy);
|
||||
if (join == geometry::strategy::buffer::join_convex)
|
||||
{
|
||||
// Calculate the intersection-point formed by the two sides.
|
||||
// It might be that the two sides are not convex, but continue
|
||||
// or spikey, we then change the join-type
|
||||
join = line_line_intersection::apply(
|
||||
perp1, perp2, prev_perp1, prev_perp2,
|
||||
intersection_point);
|
||||
|
||||
}
|
||||
geometry::strategy::buffer::join_selector const join
|
||||
= get_join_type(penultimate_input, previous_input, input,
|
||||
strategies);
|
||||
|
||||
switch(join)
|
||||
{
|
||||
@@ -161,37 +152,48 @@ struct buffer_range
|
||||
{
|
||||
// The corner is convex, we create a join
|
||||
// TODO (future) - avoid a separate vector, add the piece directly
|
||||
std::vector<output_point_type> range_out;
|
||||
if (join_strategy.apply(intersection_point,
|
||||
previous_input, prev_perp2, perp1,
|
||||
distance.apply(previous_input, input, side),
|
||||
range_out))
|
||||
output_point_type intersection_point;
|
||||
if (line_line_intersection::apply(prev_perp1, prev_perp2,
|
||||
perp1, perp2, previous_input,
|
||||
segment_strategy.equidistant(),
|
||||
intersection_point))
|
||||
{
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_join,
|
||||
previous_input, range_out);
|
||||
std::vector<output_point_type> range_out;
|
||||
if (join_strategy.apply(intersection_point,
|
||||
previous_input, prev_perp2, perp1,
|
||||
distance.apply(previous_input, input, side),
|
||||
range_out))
|
||||
{
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_join,
|
||||
previous_input, range_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
// Returns true if collinear point p2 continues after p0 and p1.
|
||||
// If it turns back (spike), it returns false.
|
||||
static inline bool same_direction(output_point_type const& p0,
|
||||
output_point_type const& p1,
|
||||
output_point_type const& p2)
|
||||
{
|
||||
typedef typename cs_tag<output_point_type>::type cs_tag;
|
||||
return direction_code<cs_tag>(p0, p1, p2) == 1;
|
||||
}
|
||||
|
||||
template <typename Strategies>
|
||||
static inline geometry::strategy::buffer::join_selector get_join_type(
|
||||
output_point_type const& p0,
|
||||
output_point_type const& p1,
|
||||
output_point_type const& p2,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
int const side = strategy.apply(p0, p1, p2);
|
||||
int const side = strategies.side().apply(p0, p1, p2);
|
||||
return side == -1 ? geometry::strategy::buffer::join_convex
|
||||
: side == 1 ? geometry::strategy::buffer::join_concave
|
||||
: parallel_continue
|
||||
(
|
||||
get<0>(p2) - get<0>(p1),
|
||||
get<1>(p2) - get<1>(p1),
|
||||
get<0>(p1) - get<0>(p0),
|
||||
get<1>(p1) - get<1>(p0)
|
||||
) ? geometry::strategy::buffer::join_continue
|
||||
: same_direction(p0, p1, p2) ? geometry::strategy::buffer::join_continue
|
||||
: geometry::strategy::buffer::join_spike;
|
||||
}
|
||||
|
||||
@@ -200,28 +202,28 @@ struct buffer_range
|
||||
typename Collection,
|
||||
typename Iterator,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
Strategies const& strategies,
|
||||
bool linear,
|
||||
output_point_type& first_p1,
|
||||
output_point_type& first_p2,
|
||||
output_point_type& last_p1,
|
||||
output_point_type& last_p2)
|
||||
{
|
||||
boost::ignore_unused(side_strategy);
|
||||
boost::ignore_unused(segment_strategy);
|
||||
|
||||
typedef typename std::iterator_traits
|
||||
<
|
||||
@@ -263,7 +265,7 @@ struct buffer_range
|
||||
{
|
||||
generated_side.clear();
|
||||
geometry::strategy::buffer::result_code error_code
|
||||
= side_strategy.apply(*prev, *it, side,
|
||||
= segment_strategy.apply(*prev, *it, side,
|
||||
distance_strategy, generated_side);
|
||||
|
||||
if (error_code == geometry::strategy::buffer::result_no_output)
|
||||
@@ -289,15 +291,15 @@ struct buffer_range
|
||||
*prev, last_p1, last_p2,
|
||||
*it, generated_side.front(), generated_side.back(),
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
distance_strategy, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies);
|
||||
}
|
||||
|
||||
collection.add_side_piece(*prev, *it, generated_side, first);
|
||||
collection.add_side_piece(*prev, *it, generated_side, first, distance_strategy.empty(side));
|
||||
|
||||
if (first && mark_flat)
|
||||
{
|
||||
collection.mark_flat_start();
|
||||
collection.mark_flat_start(*prev);
|
||||
}
|
||||
|
||||
penultimate_point = *prev;
|
||||
@@ -316,7 +318,7 @@ struct buffer_range
|
||||
|
||||
if (mark_flat)
|
||||
{
|
||||
collection.mark_flat_end();
|
||||
collection.mark_flat_end(ultimate_point);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -335,32 +337,29 @@ struct buffer_multi
|
||||
<
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Multi const& multi,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
for (typename boost::range_iterator<Multi const>::type
|
||||
it = boost::begin(multi);
|
||||
it != boost::end(multi);
|
||||
++it)
|
||||
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
|
||||
{
|
||||
Policy::apply(*it, collection,
|
||||
distance_strategy, side_strategy,
|
||||
distance_strategy, segment_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategy);
|
||||
robust_policy, strategies);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -423,21 +422,21 @@ struct buffer_inserter<point_tag, Point, RingOutput>
|
||||
<
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Point const& point, Collection& collection,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& ,
|
||||
SegmentStrategy const& ,
|
||||
JoinStrategy const& ,
|
||||
EndStrategy const& ,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& ,
|
||||
Strategy const& ) // side strategy
|
||||
Strategies const& )
|
||||
{
|
||||
detail::buffer::buffer_point
|
||||
<
|
||||
@@ -455,28 +454,28 @@ template
|
||||
>
|
||||
struct buffer_inserter_ring
|
||||
{
|
||||
typedef typename point_type<RingOutput>::type output_point_type;
|
||||
using output_point_type = typename point_type<RingOutput>::type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Collection,
|
||||
typename Iterator,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
output_point_type first_p1, first_p2, last_p1, last_p2;
|
||||
|
||||
@@ -485,8 +484,8 @@ struct buffer_inserter_ring
|
||||
geometry::strategy::buffer::result_code result
|
||||
= buffer_range::iterate(collection, begin, end,
|
||||
side,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
distance_strategy, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies,
|
||||
false, first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
// Generate closing join
|
||||
@@ -497,8 +496,8 @@ struct buffer_inserter_ring
|
||||
*(end - 1), last_p1, last_p2,
|
||||
*(begin + 1), first_p1, first_p2,
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
distance_strategy, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies);
|
||||
}
|
||||
|
||||
// Buffer is closed automatically by last closing corner
|
||||
@@ -509,51 +508,58 @@ struct buffer_inserter_ring
|
||||
<
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
RingInput simplified;
|
||||
detail::buffer::simplify_input(ring, distance, simplified);
|
||||
// Use helper geometry to support non-mutable input Rings
|
||||
using simplified_ring_t = model::ring
|
||||
<
|
||||
output_point_type,
|
||||
point_order<RingInput>::value != counterclockwise,
|
||||
closure<RingInput>::value != open
|
||||
>;
|
||||
simplified_ring_t simplified;
|
||||
detail::buffer::simplify_input(ring, distance, simplified, strategies);
|
||||
|
||||
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
|
||||
|
||||
std::size_t n = boost::size(simplified);
|
||||
std::size_t const min_points = core_detail::closure::minimum_ring_size
|
||||
<
|
||||
geometry::closure<RingInput>::value
|
||||
geometry::closure<simplified_ring_t>::value
|
||||
>::value;
|
||||
|
||||
if (n >= min_points)
|
||||
{
|
||||
detail::normalized_view<RingInput const> view(simplified);
|
||||
detail::closed_clockwise_view<simplified_ring_t const> view(simplified);
|
||||
if (distance.negative())
|
||||
{
|
||||
// Walk backwards (rings will be reversed afterwards)
|
||||
code = iterate(collection, boost::rbegin(view), boost::rend(view),
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
distance, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies);
|
||||
}
|
||||
else
|
||||
{
|
||||
code = iterate(collection, boost::begin(view), boost::end(view),
|
||||
geometry::strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
distance, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,30 +588,30 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
|
||||
<
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
collection.start_new_ring(distance.negative());
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
|
||||
collection, distance,
|
||||
side_strategy, join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategy);
|
||||
collection.finish_ring(code);
|
||||
segment_strategy, join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategies);
|
||||
collection.finish_ring(code, ring, false, false);
|
||||
return code;
|
||||
}
|
||||
};
|
||||
@@ -617,34 +623,33 @@ template
|
||||
>
|
||||
struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type output_ring_type;
|
||||
typedef typename point_type<output_ring_type>::type output_point_type;
|
||||
typedef typename point_type<Linestring>::type input_point_type;
|
||||
using output_ring_type = typename ring_type<Polygon>::type;
|
||||
using output_point_type = typename point_type<output_ring_type>::type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Collection,
|
||||
typename Iterator,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
Strategies const& strategies,
|
||||
output_point_type& first_p1)
|
||||
{
|
||||
input_point_type const& ultimate_point = *(end - 1);
|
||||
input_point_type const& penultimate_point = *(end - 2);
|
||||
output_point_type const& ultimate_point = *(end - 1);
|
||||
output_point_type const& penultimate_point = *(end - 2);
|
||||
|
||||
// For the end-cap, we need to have the last perpendicular point on the
|
||||
// other side of the linestring. If it is the second pass (right),
|
||||
@@ -659,7 +664,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
{
|
||||
std::vector<output_point_type> generated_side;
|
||||
geometry::strategy::buffer::result_code code
|
||||
= side_strategy.apply(ultimate_point, penultimate_point,
|
||||
= segment_strategy.apply(ultimate_point, penultimate_point,
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance_strategy, generated_side);
|
||||
if (code != geometry::strategy::buffer::result_normal)
|
||||
@@ -675,8 +680,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
geometry::strategy::buffer::result_code result
|
||||
= detail::buffer::buffer_range<output_ring_type>::iterate(collection,
|
||||
begin, end, side,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
distance_strategy, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies,
|
||||
true, first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
if (result == geometry::strategy::buffer::result_normal)
|
||||
@@ -693,25 +698,26 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
<
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline geometry::strategy::buffer::result_code apply(Linestring const& linestring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
Linestring simplified;
|
||||
detail::buffer::simplify_input(linestring, distance, simplified);
|
||||
// Use helper geometry to support non-mutable input Linestrings
|
||||
model::linestring<output_point_type> simplified;
|
||||
detail::buffer::simplify_input(linestring, distance, simplified, strategies);
|
||||
|
||||
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
|
||||
std::size_t n = boost::size(simplified);
|
||||
@@ -722,8 +728,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
code = iterate(collection,
|
||||
boost::begin(simplified), boost::end(simplified),
|
||||
geometry::strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
distance, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies,
|
||||
first_p1);
|
||||
|
||||
if (code == geometry::strategy::buffer::result_normal)
|
||||
@@ -731,8 +737,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
code = iterate(collection,
|
||||
boost::rbegin(simplified), boost::rend(simplified),
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
distance, segment_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategies,
|
||||
first_p1);
|
||||
}
|
||||
collection.finish_ring(code);
|
||||
@@ -770,23 +776,23 @@ private:
|
||||
typename Iterator,
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline
|
||||
void iterate(Iterator begin, Iterator end,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
Strategies const& strategies,
|
||||
bool is_interior)
|
||||
{
|
||||
for (Iterator it = begin; it != end; ++it)
|
||||
@@ -799,11 +805,11 @@ private:
|
||||
|
||||
collection.start_new_ring(deflate);
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= policy::apply(*it, collection, distance, side_strategy,
|
||||
= policy::apply(*it, collection, distance, segment_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategy);
|
||||
robust_policy, strategies);
|
||||
|
||||
collection.finish_ring(code, is_interior);
|
||||
collection.finish_ring(code, *it, is_interior, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -812,28 +818,28 @@ private:
|
||||
typename InteriorRings,
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline
|
||||
void apply_interior_rings(InteriorRings const& interior_rings,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
iterate(boost::begin(interior_rings), boost::end(interior_rings),
|
||||
collection, distance, side_strategy,
|
||||
collection, distance, segment_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategy, true);
|
||||
robust_policy, strategies, true);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -841,40 +847,40 @@ public:
|
||||
<
|
||||
typename Collection,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(PolygonInput const& polygon,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
Strategies const& strategies)
|
||||
{
|
||||
{
|
||||
collection.start_new_ring(distance.negative());
|
||||
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= policy::apply(exterior_ring(polygon), collection,
|
||||
distance, side_strategy,
|
||||
distance, segment_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategy);
|
||||
robust_policy, strategies);
|
||||
|
||||
collection.finish_ring(code, false,
|
||||
collection.finish_ring(code, exterior_ring(polygon), false,
|
||||
geometry::num_interior_rings(polygon) > 0u);
|
||||
}
|
||||
|
||||
apply_interior_rings(interior_rings(polygon),
|
||||
collection, distance, side_strategy,
|
||||
collection, distance, segment_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, strategy);
|
||||
robust_policy, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -915,41 +921,38 @@ template
|
||||
typename GeometryInput,
|
||||
typename OutputIterator,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename IntersectionStrategy,
|
||||
typename Strategies,
|
||||
typename RobustPolicy,
|
||||
typename VisitPiecesPolicy
|
||||
>
|
||||
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
Strategies const& strategies,
|
||||
RobustPolicy const& robust_policy,
|
||||
VisitPiecesPolicy& visit_pieces_policy
|
||||
)
|
||||
{
|
||||
boost::ignore_unused(visit_pieces_policy);
|
||||
|
||||
typedef detail::buffer::buffered_piece_collection
|
||||
<
|
||||
typename geometry::ring_type<GeometryOutput>::type,
|
||||
IntersectionStrategy,
|
||||
RobustPolicy
|
||||
> collection_type;
|
||||
collection_type collection(intersection_strategy, robust_policy);
|
||||
using collection_type = detail::buffer::buffered_piece_collection
|
||||
<
|
||||
typename geometry::ring_type<GeometryOutput>::type,
|
||||
Strategies,
|
||||
DistanceStrategy,
|
||||
RobustPolicy
|
||||
>;
|
||||
collection_type collection(strategies, distance_strategy, robust_policy);
|
||||
collection_type const& const_collection = collection;
|
||||
|
||||
bool const areal = boost::is_same
|
||||
<
|
||||
typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,
|
||||
areal_tag
|
||||
>::type::value;
|
||||
static constexpr bool areal = util::is_areal<GeometryInput>::value;
|
||||
|
||||
dispatch::buffer_inserter
|
||||
<
|
||||
@@ -961,17 +964,18 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
GeometryInput,
|
||||
GeometryOutput
|
||||
>::apply(geometry_input, collection,
|
||||
distance_strategy, side_strategy, join_strategy,
|
||||
end_strategy, point_strategy,
|
||||
robust_policy, intersection_strategy.get_side_strategy());
|
||||
distance_strategy, segment_strategy, join_strategy,
|
||||
end_strategy, point_strategy,
|
||||
robust_policy, strategies);
|
||||
|
||||
collection.get_turns();
|
||||
collection.classify_turns();
|
||||
if (BOOST_GEOMETRY_CONDITION(areal))
|
||||
if BOOST_GEOMETRY_CONSTEXPR (areal)
|
||||
{
|
||||
collection.check_remaining_points(distance_strategy);
|
||||
collection.check_turn_in_original();
|
||||
}
|
||||
|
||||
collection.verify_turns();
|
||||
|
||||
// Visit the piece collection. This does nothing (by default), but
|
||||
// optionally a debugging tool can be attached (e.g. console or svg),
|
||||
// or the piece collection can be unit-tested
|
||||
@@ -985,6 +989,11 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
// phase 1: turns (after enrichment/clustering)
|
||||
visit_pieces_policy.apply(const_collection, 1);
|
||||
|
||||
if BOOST_GEOMETRY_CONSTEXPR (areal)
|
||||
{
|
||||
collection.deflate_check_turns();
|
||||
}
|
||||
|
||||
collection.traverse();
|
||||
|
||||
// Reverse all offsetted rings / traversed rings if:
|
||||
@@ -992,8 +1001,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
// - the output is counter clockwise
|
||||
// and avoid reversing twice
|
||||
bool reverse = distance_strategy.negative() && areal;
|
||||
if (BOOST_GEOMETRY_CONDITION(
|
||||
geometry::point_order<GeometryOutput>::value == counterclockwise))
|
||||
if BOOST_GEOMETRY_CONSTEXPR (geometry::point_order<GeometryOutput>::value == counterclockwise)
|
||||
{
|
||||
reverse = ! reverse;
|
||||
}
|
||||
@@ -1002,9 +1010,12 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
collection.reverse();
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal))
|
||||
if BOOST_GEOMETRY_CONSTEXPR (areal)
|
||||
{
|
||||
collection.discard_nonintersecting_deflated_rings();
|
||||
if (distance_strategy.negative())
|
||||
{
|
||||
collection.discard_nonintersecting_deflated_rings();
|
||||
}
|
||||
}
|
||||
|
||||
collection.template assign<GeometryOutput>(out);
|
||||
@@ -1020,27 +1031,27 @@ template
|
||||
typename GeometryInput,
|
||||
typename OutputIterator,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename SegmentStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename IntersectionStrategy,
|
||||
typename Strategies,
|
||||
typename RobustPolicy
|
||||
>
|
||||
inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
SegmentStrategy const& segment_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
Strategies const& strategies,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
detail::buffer::visit_pieces_default_policy visitor;
|
||||
buffer_inserter<GeometryOutput>(geometry_input, out,
|
||||
distance_strategy, side_strategy, join_strategy,
|
||||
distance_strategy, segment_strategy, join_strategy,
|
||||
end_strategy, point_strategy,
|
||||
intersection_strategy, robust_policy, visitor);
|
||||
strategies, robust_policy, visitor);
|
||||
}
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017-2020.
|
||||
// Modifications copyright (c) 2017-2020, 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,
|
||||
@@ -15,12 +15,11 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
@@ -36,12 +35,6 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
enum intersection_location_type
|
||||
{
|
||||
location_ok, inside_buffer, location_discard
|
||||
};
|
||||
|
||||
class backtrack_for_buffer
|
||||
{
|
||||
public :
|
||||
@@ -146,8 +139,8 @@ struct buffer_turn_operation
|
||||
{}
|
||||
};
|
||||
|
||||
// Version for buffer including type of location, is_opposite, and helper variables
|
||||
template <typename Point, typename RobustPoint, typename SegmentRatio>
|
||||
// Version of turn_info for buffer with its turn index and other helper variables
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct buffer_turn_info
|
||||
: public detail::overlay::turn_info
|
||||
<
|
||||
@@ -157,73 +150,144 @@ struct buffer_turn_info
|
||||
>
|
||||
{
|
||||
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
|
||||
std::size_t turn_index;
|
||||
|
||||
RobustPoint robust_point;
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
|
||||
// Will (most probably) be removed later
|
||||
RobustPoint mapped_robust_point; // alas... we still need to adapt our points, offsetting them 1 integer to be co-located with neighbours
|
||||
#endif
|
||||
|
||||
|
||||
inline RobustPoint const& get_robust_point() const
|
||||
{
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
|
||||
return mapped_robust_point;
|
||||
#endif
|
||||
return robust_point;
|
||||
}
|
||||
|
||||
intersection_location_type location;
|
||||
|
||||
robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
|
||||
|
||||
std::size_t count_within;
|
||||
// Information if turn can be used. It is not traversable if it is within
|
||||
// another piece, or within the original (depending on deflation),
|
||||
// or (for deflate) if there are not enough points to traverse it.
|
||||
bool is_turn_traversable;
|
||||
|
||||
bool is_linear_end_point;
|
||||
bool within_original;
|
||||
std::size_t count_on_original_boundary;
|
||||
signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
|
||||
|
||||
std::size_t count_on_offsetted;
|
||||
std::size_t count_on_helper;
|
||||
std::size_t count_within_near_offsetted;
|
||||
|
||||
bool remove_on_multi;
|
||||
|
||||
// Obsolete:
|
||||
std::size_t count_on_occupied;
|
||||
std::size_t count_on_multi;
|
||||
|
||||
inline buffer_turn_info()
|
||||
: turn_index(0)
|
||||
, location(location_ok)
|
||||
, count_within(0)
|
||||
, is_turn_traversable(true)
|
||||
, is_linear_end_point(false)
|
||||
, within_original(false)
|
||||
, count_on_original_boundary(0)
|
||||
, count_in_original(0)
|
||||
, count_on_offsetted(0)
|
||||
, count_on_helper(0)
|
||||
, count_within_near_offsetted(0)
|
||||
, remove_on_multi(false)
|
||||
, count_on_occupied(0)
|
||||
, count_on_multi(0)
|
||||
{}
|
||||
};
|
||||
|
||||
struct buffer_operation_less
|
||||
struct buffer_less
|
||||
{
|
||||
template <typename Turn>
|
||||
inline bool operator()(Turn const& left, Turn const& right) const
|
||||
template <typename Indexed>
|
||||
inline bool operator()(Indexed const& left, Indexed const& right) const
|
||||
{
|
||||
segment_identifier const& sl = left.seg_id;
|
||||
segment_identifier const& sr = right.seg_id;
|
||||
if (! (left.subject->seg_id == right.subject->seg_id))
|
||||
{
|
||||
return left.subject->seg_id < right.subject->seg_id;
|
||||
}
|
||||
|
||||
// Sort them descending
|
||||
return sl == sr
|
||||
? left.fraction < right.fraction
|
||||
: sl < sr;
|
||||
// Both left and right are located on the SAME segment.
|
||||
if (! (left.subject->fraction == right.subject->fraction))
|
||||
{
|
||||
return left.subject->fraction < right.subject->fraction;
|
||||
}
|
||||
|
||||
return left.turn_index < right.turn_index;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct piece_get_box
|
||||
{
|
||||
explicit piece_get_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Piece>
|
||||
inline void apply(Box& total, Piece const& piece) const
|
||||
{
|
||||
assert_coordinate_type_equal(total, piece.m_piece_border.m_envelope);
|
||||
|
||||
if (piece.m_piece_border.m_has_envelope)
|
||||
{
|
||||
geometry::expand(total, piece.m_piece_border.m_envelope,
|
||||
m_strategy);
|
||||
}
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct piece_overlaps_box
|
||||
{
|
||||
explicit piece_overlaps_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Piece>
|
||||
inline bool apply(Box const& box, Piece const& piece) const
|
||||
{
|
||||
assert_coordinate_type_equal(box, piece.m_piece_border.m_envelope);
|
||||
|
||||
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;
|
||||
}
|
||||
if (! piece.m_piece_border.m_has_envelope)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.m_piece_border.m_envelope,
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct turn_get_box
|
||||
{
|
||||
explicit turn_get_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Turn>
|
||||
inline void apply(Box& total, Turn const& turn) const
|
||||
{
|
||||
assert_coordinate_type_equal(total, turn.point);
|
||||
geometry::expand(total, turn.point, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct turn_overlaps_box
|
||||
{
|
||||
explicit turn_overlaps_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Turn>
|
||||
inline bool apply(Box const& box, Turn const& turn) const
|
||||
{
|
||||
assert_coordinate_type_equal(turn.point, box);
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.point, box,
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
struct enriched_map_buffer_include_policy
|
||||
{
|
||||
template <typename Operation>
|
||||
static inline bool include(Operation const& op)
|
||||
{
|
||||
return op != detail::overlay::operation_intersection
|
||||
&& op != detail::overlay::operation_blocked;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,10 @@
|
||||
|
||||
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2020.
|
||||
// Modifications copyright (c) 2020 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)
|
||||
@@ -12,7 +16,8 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
@@ -78,11 +83,14 @@ struct buffered_ring_collection : public std::vector<Ring>
|
||||
|
||||
|
||||
// Turn off concept checking (for now)
|
||||
namespace dispatch
|
||||
namespace concepts
|
||||
{
|
||||
template <typename Geometry, bool IsConst>
|
||||
struct check<Geometry, detail::buffer::buffered_ring_collection_tag, IsConst>
|
||||
|
||||
template <typename Geometry>
|
||||
struct concept_type<Geometry, geometry::detail::buffer::buffered_ring_collection_tag>
|
||||
{
|
||||
struct dummy {};
|
||||
using type = dummy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017-2020.
|
||||
// Modifications copyright (c) 2017-2020 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,
|
||||
@@ -15,11 +15,12 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
@@ -116,7 +117,7 @@ template
|
||||
typename Pieces,
|
||||
typename Rings,
|
||||
typename Turns,
|
||||
typename IntersectionStrategy,
|
||||
typename Strategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
class piece_turn_visitor
|
||||
@@ -124,7 +125,7 @@ class piece_turn_visitor
|
||||
Pieces const& m_pieces;
|
||||
Rings const& m_rings;
|
||||
Turns& m_turns;
|
||||
IntersectionStrategy const& m_intersection_strategy;
|
||||
Strategy const& m_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
template <typename Piece>
|
||||
@@ -150,7 +151,6 @@ class piece_turn_visitor
|
||||
return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
|
||||
}
|
||||
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
|
||||
signed_size_type& index, int dir,
|
||||
@@ -194,7 +194,6 @@ class piece_turn_visitor
|
||||
{
|
||||
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;
|
||||
@@ -213,12 +212,12 @@ class piece_turn_visitor
|
||||
|
||||
// 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;
|
||||
auto it1_first = boost::begin(ring1) + sec1_first_index;
|
||||
auto 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;
|
||||
auto it2_first = boost::begin(ring2) + sec2_first_index;
|
||||
auto 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;
|
||||
@@ -246,41 +245,32 @@ class piece_turn_visitor
|
||||
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++;
|
||||
auto it1 = it1_first;
|
||||
for (auto prev1 = it1++;
|
||||
it1 != it1_beyond;
|
||||
prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
|
||||
{
|
||||
the_model.operations[1].piece_index = piece2.index;
|
||||
the_model.operations[1].seg_id = piece2.first_seg_id;
|
||||
the_model.operations[1].seg_id.segment_index = index2; // override
|
||||
geometry::recalculate(the_model.rob_pi, *prev1, m_robust_policy);
|
||||
geometry::recalculate(the_model.rob_pj, *it1, m_robust_policy);
|
||||
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
|
||||
|
||||
iterator it2 = it2_first;
|
||||
for (iterator prev2 = it2++;
|
||||
auto it2 = it2_first;
|
||||
for (auto prev2 = it2++;
|
||||
it2 != it2_beyond;
|
||||
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
|
||||
{
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range2(ring2, prev2, it2);
|
||||
geometry::recalculate(the_model.rob_qi, *prev2, m_robust_policy);
|
||||
geometry::recalculate(the_model.rob_qj, *it2, m_robust_policy);
|
||||
|
||||
// TODO: internally get_turn_info calculates robust points.
|
||||
// But they are already calculated.
|
||||
// We should be able to use them.
|
||||
// this means passing them to this visitor,
|
||||
// and iterating in sync with them...
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
detail::overlay::assign_policy_only_start_turns
|
||||
> turn_policy;
|
||||
|
||||
turn_policy::apply(unique_sub_range1, unique_sub_range2,
|
||||
the_model,
|
||||
m_intersection_strategy,
|
||||
m_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
}
|
||||
@@ -292,12 +282,12 @@ public:
|
||||
piece_turn_visitor(Pieces const& pieces,
|
||||
Rings const& ring_collection,
|
||||
Turns& turns,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_pieces(pieces)
|
||||
, m_rings(ring_collection)
|
||||
, m_turns(turns)
|
||||
, m_intersection_strategy(intersection_strategy)
|
||||
, m_strategy(strategy)
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
@@ -316,7 +306,7 @@ public:
|
||||
|| is_on_same_convex_ring(piece1, piece2)
|
||||
|| detail::disjoint::disjoint_box_box(section1.bounding_box,
|
||||
section2.bounding_box,
|
||||
m_intersection_strategy.get_disjoint_box_box_strategy()) )
|
||||
m_strategy) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
// 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-2022.
|
||||
// Modifications copyright (c) 2017-2022 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_BUFFER_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
|
||||
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/visit.hpp> // for GC
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
#include <boost/geometry/algorithms/union.hpp> // for GC
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
#include <boost/geometry/strategies/buffer/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/buffer/geographic.hpp>
|
||||
#include <boost/geometry/strategies/buffer/spherical.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct buffer_dc<BoxIn, BoxOut, box_tag, box_tag>
|
||||
{
|
||||
template <typename Distance>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& box_out,
|
||||
Distance const& distance, Distance const& )
|
||||
{
|
||||
detail::buffer::buffer_box(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Input, typename Output, typename TagIn>
|
||||
struct buffer_all<Input, Output, TagIn, multi_polygon_tag>
|
||||
{
|
||||
template
|
||||
<
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef typename boost::range_value<Output>::type polygon_type;
|
||||
|
||||
typedef typename point_type<Input>::type point_type;
|
||||
typedef typename rescale_policy_type
|
||||
<
|
||||
point_type,
|
||||
typename geometry::cs_tag<point_type>::type
|
||||
>::type rescale_policy_type;
|
||||
|
||||
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));
|
||||
|
||||
rescale_policy_type rescale_policy
|
||||
= boost::geometry::get_rescale_policy<rescale_policy_type>(
|
||||
box, strategies);
|
||||
|
||||
detail::buffer::buffer_inserter<polygon_type>(geometry_in,
|
||||
range::back_inserter(geometry_out),
|
||||
distance_strategy,
|
||||
side_strategy,
|
||||
join_strategy,
|
||||
end_strategy,
|
||||
point_strategy,
|
||||
strategies,
|
||||
rescale_policy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Input, typename Output>
|
||||
struct buffer_all<Input, Output, geometry_collection_tag, multi_polygon_tag>
|
||||
{
|
||||
template
|
||||
<
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// NOTE: The buffer normally calculates everything at once (by pieces) and traverses all
|
||||
// of them to apply the union operation. Not even by merging elements. But that is
|
||||
// complex and has led to issues as well. Here intermediate results are calculated
|
||||
// with buffer and the results are merged afterwards.
|
||||
// NOTE: This algorithm merges partial results iteratively.
|
||||
// We could first gather all of the results and after that
|
||||
// use some more optimal method like merge_elements().
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
Output buffer_result;
|
||||
buffer_all
|
||||
<
|
||||
util::remove_cref_t<decltype(g)>, Output
|
||||
>::apply(g, buffer_result, distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy, strategies);
|
||||
|
||||
if (! geometry::is_empty(buffer_result))
|
||||
{
|
||||
Output union_result;
|
||||
geometry::union_(geometry_out, buffer_result, union_result, strategies);
|
||||
geometry_out = std::move(union_result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, geometry_in);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Input, typename Output>
|
||||
struct buffer_all<Input, Output, geometry_collection_tag, geometry_collection_tag>
|
||||
{
|
||||
template
|
||||
<
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// NOTE: We could also allow returning GC containing only polygons.
|
||||
// We'd have to wrap them in model::multi_polygon and then
|
||||
// iteratively emplace_back() into the GC.
|
||||
using mpo_t = typename util::sequence_find_if
|
||||
<
|
||||
typename traits::geometry_types<Output>::type,
|
||||
util::is_multi_polygon
|
||||
>::type;
|
||||
mpo_t result;
|
||||
buffer_all
|
||||
<
|
||||
Input, mpo_t
|
||||
>::apply(geometry_in, result, distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy, strategies);
|
||||
range::emplace_back(geometry_out, std::move(result));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Input, typename Output, typename TagIn>
|
||||
struct buffer_all<Input, Output, TagIn, geometry_collection_tag>
|
||||
: buffer_all<Input, Output, geometry_collection_tag, geometry_collection_tag>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
|
||||
@@ -0,0 +1,279 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2017-2022.
|
||||
// Modifications copyright (c) 2017-2022 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_BUFFER_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/core/visit.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/strategies/buffer/services.hpp>
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Input,
|
||||
typename Output,
|
||||
typename TagIn = typename tag<Input>::type,
|
||||
typename TagOut = typename tag<Output>::type
|
||||
>
|
||||
struct buffer_dc : not_implemented<TagIn, TagOut>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Input,
|
||||
typename Output,
|
||||
typename TagIn = typename tag<Input>::type,
|
||||
typename TagOut = typename tag<Output>::type
|
||||
>
|
||||
struct buffer_all : not_implemented<TagIn, TagOut>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Input,
|
||||
typename TagIn = typename geometry::tag<Input>::type
|
||||
>
|
||||
struct buffer_dc
|
||||
{
|
||||
template <typename Output, typename Distance>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
Distance const& distance,
|
||||
Distance const& chord_length)
|
||||
{
|
||||
dispatch::buffer_dc<Input, Output>::apply(geometry_in, geometry_out, distance, chord_length);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Input>
|
||||
struct buffer_dc<Input, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Output, typename Distance>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
Distance const& distance,
|
||||
Distance const& chord_length)
|
||||
{
|
||||
traits::visit<Input>::apply([&](auto const& g)
|
||||
{
|
||||
dispatch::buffer_dc
|
||||
<
|
||||
util::remove_cref_t<decltype(g)>, Output
|
||||
>::apply(g, geometry_out, distance, chord_length);
|
||||
}, geometry_in);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Input,
|
||||
typename TagIn = typename geometry::tag<Input>::type
|
||||
>
|
||||
struct buffer_all
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Output,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy
|
||||
>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
typename strategies::buffer::services::default_strategy
|
||||
<
|
||||
Input
|
||||
>::type strategies;
|
||||
|
||||
dispatch::buffer_all
|
||||
<
|
||||
Input, Output
|
||||
>::apply(geometry_in, geometry_out, distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Input>
|
||||
struct buffer_all<Input, dynamic_geometry_tag>
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Output,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy
|
||||
>
|
||||
static inline void apply(Input const& geometry_in,
|
||||
Output& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
traits::visit<Input>::apply([&](auto const& g)
|
||||
{
|
||||
buffer_all
|
||||
<
|
||||
util::remove_cref_t<decltype(g)>
|
||||
>::apply(g, geometry_out, distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy);
|
||||
}, geometry_in);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\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_dynamic::buffer_dc<Input>::apply(geometry_in, geometry_out, distance, chord_length);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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>
|
||||
inline 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_dynamic::buffer_dc<Input>::apply(geometry, geometry_out, distance, chord_length);
|
||||
|
||||
return geometry_out;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{buffer}
|
||||
\ingroup buffer
|
||||
\details \details_calc{buffer, \det_buffer}.
|
||||
\tparam GeometryIn \tparam_geometry
|
||||
\tparam GeometryOut \tparam_geometry{GeometryOut}
|
||||
\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 geometry, e.g. multi polygon,
|
||||
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 GeometryOut,
|
||||
typename DistanceStrategy,
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy
|
||||
>
|
||||
inline void buffer(GeometryIn const& geometry_in,
|
||||
GeometryOut& geometry_out,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
concepts::check<GeometryIn const>();
|
||||
concepts::check<GeometryOut>();
|
||||
|
||||
geometry::clear(geometry_out);
|
||||
|
||||
resolve_dynamic::buffer_all
|
||||
<
|
||||
GeometryIn, GeometryOut
|
||||
>::apply(geometry_in, geometry_out, distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2012-2020 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
|
||||
@@ -9,11 +9,9 @@
|
||||
#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/algorithms/detail/make/make.hpp>
|
||||
#include <boost/geometry/arithmetic/infinite_line_functions.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
|
||||
{
|
||||
@@ -23,57 +21,91 @@ namespace boost { namespace geometry
|
||||
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 Point between_point(Point const& a, Point const& b)
|
||||
{
|
||||
Point result;
|
||||
geometry::set<0>(result, (geometry::get<0>(a) + geometry::get<0>(b)) / 2.0);
|
||||
geometry::set<1>(result, (geometry::get<1>(a) + geometry::get<1>(b)) / 2.0);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
static inline strategy::buffer::join_selector apply(Point const& pi, Point const& pj,
|
||||
Point const& qi, Point const& qj, Point& ip)
|
||||
static bool
|
||||
apply(Point const& pi, Point const& pj, Point const& qi, Point const& qj,
|
||||
Point const& vertex, bool equidistant, Point& ip)
|
||||
{
|
||||
// See http://mathworld.wolfram.com/Line-LineIntersection.html
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
// Calculates ip (below) by either intersecting p (pi, pj)
|
||||
// with q (qi, qj) or by taking a point between pj and qi (b) and
|
||||
// intersecting r (b, v), where v is the original vertex, with p (or q).
|
||||
// The reason for dual approach: p might be nearly collinear with q,
|
||||
// and in that case the intersection points can lose precision
|
||||
// (or be plainly wrong).
|
||||
// Therefore it takes the most precise option (this is usually p, r)
|
||||
//
|
||||
// /qj |
|
||||
// / |
|
||||
// / / |
|
||||
// / / |
|
||||
// / / |
|
||||
// /qi / |
|
||||
// / |
|
||||
// ip * + b * v |
|
||||
// \ |
|
||||
// \pj \ |
|
||||
// \ \ |
|
||||
// \ \ |
|
||||
// \ \ |
|
||||
// \pi \ |
|
||||
//
|
||||
// If generated sides along the segments can have an adapted distance,
|
||||
// in a custom strategy, then the calculation of the point in between
|
||||
// might be incorrect and the optimization is not used.
|
||||
|
||||
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));
|
||||
using ct = typename coordinate_type<Point>::type;
|
||||
|
||||
// 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.
|
||||
auto const p = detail::make::make_infinite_line<ct>(pi, pj);
|
||||
auto const q = detail::make::make_infinite_line<ct>(qi, qj);
|
||||
|
||||
// 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()))
|
||||
using line = decltype(p);
|
||||
using arithmetic::determinant;
|
||||
using arithmetic::assign_intersection_point;
|
||||
|
||||
// The denominator is the determinant of (a,b) values of lines p q
|
||||
// | pa pa |
|
||||
// | qb qb |
|
||||
auto const denominator_pq = determinant<line, &line::a, &line::b>(p, q);
|
||||
constexpr decltype(denominator_pq) const zero = 0;
|
||||
|
||||
if (equidistant)
|
||||
{
|
||||
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
|
||||
;
|
||||
auto const between = between_point(pj, qi);
|
||||
auto const r = detail::make::make_infinite_line<ct>(vertex, between);
|
||||
auto const denominator_pr = determinant<line, &line::a, &line::b>(p, r);
|
||||
|
||||
if (math::equals(denominator_pq, zero)
|
||||
&& math::equals(denominator_pr, zero))
|
||||
{
|
||||
// Degenerate case (for example when length results in <inf>)
|
||||
return false;
|
||||
}
|
||||
|
||||
ip = geometry::math::abs(denominator_pq) > geometry::math::abs(denominator_pr)
|
||||
? assign_intersection_point<Point>(p, q, denominator_pq)
|
||||
: assign_intersection_point<Point>(p, r, denominator_pr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (math::equals(denominator_pq, zero))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ip = assign_intersection_point<Point>(p, q, denominator_pq);
|
||||
}
|
||||
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// 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
|
||||
@@ -0,0 +1,511 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2020-2021 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2020-2022.
|
||||
// Modifications copyright (c) 2020-2022, 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_PIECE_BORDER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PIECE_BORDER_HPP
|
||||
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/config.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/buffer/buffer_policies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
template <typename It, typename T, typename Compare>
|
||||
inline bool get_range_around(It begin, It end, T const& value, Compare const& compare, It& lower, It& upper)
|
||||
{
|
||||
lower = end;
|
||||
upper = end;
|
||||
|
||||
// Get first element not smaller than value
|
||||
if (begin == end)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (compare(value, *begin))
|
||||
{
|
||||
// The value is smaller than the first item, therefore not in range
|
||||
return false;
|
||||
}
|
||||
// *(begin + std::distance(begin, end) - 1))
|
||||
if (compare(*(end - 1), value))
|
||||
{
|
||||
// The last item is larger than the value, therefore not in range
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assign the iterators.
|
||||
// lower >= begin and lower < end
|
||||
// upper > lower and upper <= end
|
||||
// lower_bound points to first element NOT LESS than value - but because
|
||||
// we want the first value LESS than value, we decrease it
|
||||
lower = std::lower_bound(begin, end, value, compare);
|
||||
// upper_bound points to first element of which value is LESS
|
||||
upper = std::upper_bound(begin, end, value, compare);
|
||||
|
||||
if (lower != begin)
|
||||
{
|
||||
--lower;
|
||||
}
|
||||
if (upper != end)
|
||||
{
|
||||
++upper;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
//! Contains the border of the piece, consisting of 4 parts:
|
||||
//! 1: the part of the offsetted ring (referenced, not copied)
|
||||
//! 2: the part of the original (one or two points)
|
||||
//! 3: the left part (from original to offsetted)
|
||||
//! 4: the right part (from offsetted to original)
|
||||
//! Besides that, it contains some properties of the piece(border);
|
||||
//! - convexity
|
||||
//! - envelope
|
||||
//! - monotonicity of the offsetted ring
|
||||
//! - min/max radius of a point buffer
|
||||
//! - if it is a "reversed" piece (linear features with partly negative buffers)
|
||||
template <typename Ring, typename Point>
|
||||
struct piece_border
|
||||
{
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
typedef typename default_comparable_distance_result<Point>::type radius_type;
|
||||
typedef typename geometry::strategy::buffer::turn_in_ring_winding<coordinate_type>::state_type state_type;
|
||||
|
||||
bool m_reversed;
|
||||
|
||||
// Points from the offsetted ring. They are not copied, this structure
|
||||
// refers to those points
|
||||
Ring const* m_ring;
|
||||
std::size_t m_begin;
|
||||
std::size_t m_end;
|
||||
|
||||
// Points from the original (one or two, depending on piece shape)
|
||||
// Note, if there are 2 points, they are REVERSED w.r.t. the original
|
||||
// Therefore here we can walk in its order.
|
||||
std::array<Point, 2> m_originals;
|
||||
std::size_t m_original_size;
|
||||
|
||||
geometry::model::box<Point> m_envelope;
|
||||
bool m_has_envelope;
|
||||
|
||||
// True if piece is determined as "convex"
|
||||
bool m_is_convex;
|
||||
|
||||
// True if offsetted part is monotonically changing in x-direction
|
||||
bool m_is_monotonic_increasing;
|
||||
bool m_is_monotonic_decreasing;
|
||||
|
||||
radius_type m_min_comparable_radius;
|
||||
radius_type m_max_comparable_radius;
|
||||
|
||||
piece_border()
|
||||
: m_reversed(false)
|
||||
, m_ring(NULL)
|
||||
, m_begin(0)
|
||||
, m_end(0)
|
||||
, m_original_size(0)
|
||||
, m_has_envelope(false)
|
||||
, m_is_convex(false)
|
||||
, m_is_monotonic_increasing(false)
|
||||
, m_is_monotonic_decreasing(false)
|
||||
, m_min_comparable_radius(0)
|
||||
, m_max_comparable_radius(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Only used for debugging (SVG)
|
||||
Ring get_full_ring() const
|
||||
{
|
||||
Ring result;
|
||||
if (ring_or_original_empty())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
std::copy(m_ring->begin() + m_begin,
|
||||
m_ring->begin() + m_end,
|
||||
std::back_inserter(result));
|
||||
std::copy(m_originals.begin(),
|
||||
m_originals.begin() + m_original_size,
|
||||
std::back_inserter(result));
|
||||
// Add the closing point
|
||||
result.push_back(*(m_ring->begin() + m_begin));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
void get_properties_of_border(bool is_point_buffer, Point const& center,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
m_has_envelope = calculate_envelope(m_envelope, strategy);
|
||||
if (m_has_envelope)
|
||||
{
|
||||
// Take roundings into account, enlarge box
|
||||
geometry::detail::expand_by_epsilon(m_envelope);
|
||||
}
|
||||
if (! ring_or_original_empty() && is_point_buffer)
|
||||
{
|
||||
// Determine min/max radius
|
||||
calculate_radii(center, m_ring->begin() + m_begin, m_ring->begin() + m_end);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
void get_properties_of_offsetted_ring_part(Strategy const& strategy)
|
||||
{
|
||||
if (! ring_or_original_empty())
|
||||
{
|
||||
m_is_convex = is_convex(strategy);
|
||||
check_monotonicity(m_ring->begin() + m_begin, m_ring->begin() + m_end);
|
||||
}
|
||||
}
|
||||
|
||||
void set_offsetted(Ring const& ring, std::size_t begin, std::size_t end)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(begin <= end);
|
||||
BOOST_GEOMETRY_ASSERT(begin < boost::size(ring));
|
||||
BOOST_GEOMETRY_ASSERT(end <= boost::size(ring));
|
||||
|
||||
m_ring = boost::addressof(ring);
|
||||
m_begin = begin;
|
||||
m_end = end;
|
||||
}
|
||||
|
||||
void add_original_point(Point const& point)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(m_original_size < 2);
|
||||
m_originals[m_original_size++] = point;
|
||||
}
|
||||
|
||||
template <typename Box, typename Strategy>
|
||||
bool calculate_envelope(Box& envelope, Strategy const& strategy) const
|
||||
{
|
||||
geometry::assign_inverse(envelope);
|
||||
if (ring_or_original_empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
expand_envelope(envelope, m_ring->begin() + m_begin, m_ring->begin() + m_end, strategy);
|
||||
expand_envelope(envelope, m_originals.begin(), m_originals.begin() + m_original_size, strategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Whatever the return value, the state should be checked.
|
||||
template <typename TurnPoint, typename State>
|
||||
bool point_on_piece(TurnPoint const& point,
|
||||
bool one_sided, bool is_linear_end_point,
|
||||
State& state) const
|
||||
{
|
||||
if (ring_or_original_empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Walk over the different parts of the ring, in clockwise order
|
||||
// For performance reasons: start with the helper part (one segment)
|
||||
// then the original part (one segment, if any), then the other helper
|
||||
// part (one segment), and only then the offsetted part
|
||||
// (probably more segments, check monotonicity)
|
||||
geometry::strategy::buffer::turn_in_ring_winding<coordinate_type> tir;
|
||||
|
||||
Point const offsetted_front = *(m_ring->begin() + m_begin);
|
||||
Point const offsetted_back = *(m_ring->begin() + m_end - 1);
|
||||
|
||||
// For onesided buffers, or turns colocated with linear end points,
|
||||
// the place on the ring is changed to offsetted (because of colocation)
|
||||
geometry::strategy::buffer::place_on_ring_type const por_original
|
||||
= adapted_place_on_ring(geometry::strategy::buffer::place_on_ring_original,
|
||||
one_sided, is_linear_end_point);
|
||||
geometry::strategy::buffer::place_on_ring_type const por_from_offsetted
|
||||
= adapted_place_on_ring(geometry::strategy::buffer::place_on_ring_from_offsetted,
|
||||
one_sided, is_linear_end_point);
|
||||
geometry::strategy::buffer::place_on_ring_type const por_to_offsetted
|
||||
= adapted_place_on_ring(geometry::strategy::buffer::place_on_ring_to_offsetted,
|
||||
one_sided, is_linear_end_point);
|
||||
|
||||
bool continue_processing = true;
|
||||
if (m_original_size == 1)
|
||||
{
|
||||
// One point. Walk from last offsetted to point, and from point to first offsetted
|
||||
continue_processing = step(point, offsetted_back, m_originals[0],
|
||||
tir, por_from_offsetted, state)
|
||||
&& step(point, m_originals[0], offsetted_front,
|
||||
tir, por_to_offsetted, state);
|
||||
}
|
||||
else if (m_original_size == 2)
|
||||
{
|
||||
// Two original points. Walk from last offsetted point to first original point,
|
||||
// then along original, then from second oginal to first offsetted point
|
||||
continue_processing = step(point, offsetted_back, m_originals[0],
|
||||
tir, por_from_offsetted, state)
|
||||
&& step(point, m_originals[0], m_originals[1],
|
||||
tir, por_original, state)
|
||||
&& step(point, m_originals[1], offsetted_front,
|
||||
tir, por_to_offsetted, state);
|
||||
}
|
||||
|
||||
if (continue_processing)
|
||||
{
|
||||
// Check the offsetted ring (in rounded joins, these might be
|
||||
// several segments)
|
||||
walk_offsetted(point, m_ring->begin() + m_begin, m_ring->begin() + m_end,
|
||||
tir, state);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Returns true if empty (no ring, or no points, or no original)
|
||||
bool ring_or_original_empty() const
|
||||
{
|
||||
return m_ring == NULL || m_begin >= m_end || m_original_size == 0;
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
static geometry::strategy::buffer::place_on_ring_type
|
||||
adapted_place_on_ring(geometry::strategy::buffer::place_on_ring_type target,
|
||||
bool one_sided, bool is_linear_end_point)
|
||||
{
|
||||
return one_sided || is_linear_end_point
|
||||
? geometry::strategy::buffer::place_on_ring_offsetted
|
||||
: target;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename TurnPoint, typename Iterator,
|
||||
typename TiRStrategy,
|
||||
typename State
|
||||
>
|
||||
bool walk_offsetted(TurnPoint const& point, Iterator begin, Iterator end,
|
||||
TiRStrategy const & strategy,
|
||||
State& state) const
|
||||
{
|
||||
Iterator it = begin;
|
||||
Iterator beyond = end;
|
||||
|
||||
// Move iterators if the offsetted ring is monotonic increasing or decreasing
|
||||
if (m_is_monotonic_increasing)
|
||||
{
|
||||
if (! get_range_around(begin, end, point, geometry::less<Point, 0>(), it, beyond))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (m_is_monotonic_decreasing)
|
||||
{
|
||||
if (! get_range_around(begin, end, point, geometry::greater<Point, 0>(), it, beyond))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator previous = it++ ; it != beyond ; ++previous, ++it )
|
||||
{
|
||||
if (! step(point, *previous, *it, strategy,
|
||||
geometry::strategy::buffer::place_on_ring_offsetted, state))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TurnPoint, typename TiRStrategy, typename State>
|
||||
bool step(TurnPoint const& point, Point const& p1, Point const& p2,
|
||||
TiRStrategy const& strategy,
|
||||
geometry::strategy::buffer::place_on_ring_type place_on_ring, State& state) const
|
||||
{
|
||||
return strategy.apply(point, p1, p2, place_on_ring, m_is_convex, state);
|
||||
}
|
||||
|
||||
template <typename It, typename Box, typename Strategy>
|
||||
void expand_envelope(Box& envelope, It begin, It end, Strategy const& strategy) const
|
||||
{
|
||||
for (It it = begin; it != end; ++it)
|
||||
{
|
||||
geometry::expand(envelope, *it, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
bool is_convex(Strategy const& strategy) const
|
||||
{
|
||||
if (ring_or_original_empty())
|
||||
{
|
||||
// Convexity is undetermined, and for this case it does not matter,
|
||||
// because it is only used for optimization in point_on_piece,
|
||||
// but that is not called if the piece border is not valid
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_end - m_begin <= 2)
|
||||
{
|
||||
// The offsetted ring part of this piece has only two points.
|
||||
// If this is true, and the original ring part has only one point,
|
||||
// a triangle and it is convex. If the original ring part has two
|
||||
// points, it is a rectangle and theoretically could be concave,
|
||||
// but because of the way the buffer is generated, that is never
|
||||
// the case.
|
||||
return true;
|
||||
}
|
||||
|
||||
// The offsetted ring part of thie piece has at least three points
|
||||
// (this is often the case in a piece marked as "join")
|
||||
|
||||
// We can assume all points of the offset ring are different, and also
|
||||
// that all points on the original are different, and that the offsetted
|
||||
// ring is different from the original(s)
|
||||
Point const offsetted_front = *(m_ring->begin() + m_begin);
|
||||
Point const offsetted_second = *(m_ring->begin() + m_begin + 1);
|
||||
|
||||
// These two points will be reassigned in every is_convex call
|
||||
Point previous = offsetted_front;
|
||||
Point current = offsetted_second;
|
||||
|
||||
// Verify the offsetted range (from the second point on), the original,
|
||||
// and loop through the first two points of the offsetted range
|
||||
bool const result = is_convex(previous, current, m_ring->begin() + m_begin + 2, m_ring->begin() + m_end, strategy)
|
||||
&& is_convex(previous, current, m_originals.begin(), m_originals.begin() + m_original_size, strategy)
|
||||
&& is_convex(previous, current, offsetted_front, strategy)
|
||||
&& is_convex(previous, current, offsetted_second, strategy);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename It, typename Strategy>
|
||||
bool is_convex(Point& previous, Point& current, It begin, It end, Strategy const& strategy) const
|
||||
{
|
||||
for (It it = begin; it != end; ++it)
|
||||
{
|
||||
if (! is_convex(previous, current, *it, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
bool is_convex(Point& previous, Point& current, Point const& next, Strategy const& strategy) const
|
||||
{
|
||||
int const side = strategy.side().apply(previous, current, next);
|
||||
if (side == 1)
|
||||
{
|
||||
// Next is on the left side of clockwise ring: piece is not convex
|
||||
return false;
|
||||
}
|
||||
if (! equals::equals_point_point(current, next, strategy))
|
||||
{
|
||||
previous = current;
|
||||
current = next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int Direction>
|
||||
inline void step_for_monotonicity(Point const& current, Point const& next)
|
||||
{
|
||||
if (geometry::get<Direction>(current) >= geometry::get<Direction>(next))
|
||||
{
|
||||
m_is_monotonic_increasing = false;
|
||||
}
|
||||
if (geometry::get<Direction>(current) <= geometry::get<Direction>(next))
|
||||
{
|
||||
m_is_monotonic_decreasing = false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
void check_monotonicity(It begin, It end)
|
||||
{
|
||||
m_is_monotonic_increasing = true;
|
||||
m_is_monotonic_decreasing = true;
|
||||
|
||||
if (begin == end || begin + 1 == end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
It it = begin;
|
||||
for (It previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
step_for_monotonicity<0>(*previous, *it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void calculate_radii(Point const& center, It begin, It end)
|
||||
{
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
|
||||
bool first = true;
|
||||
|
||||
// An offsetted point-buffer ring around a point is supposed to be closed,
|
||||
// therefore walking from start to end is fine.
|
||||
It it = begin;
|
||||
for (It previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
Point const& p0 = *previous;
|
||||
Point const& p1 = *it;
|
||||
segment_type const s(p0, p1);
|
||||
radius_type const d = geometry::comparable_distance(center, s);
|
||||
|
||||
if (first || d < m_min_comparable_radius)
|
||||
{
|
||||
m_min_comparable_radius = d;
|
||||
}
|
||||
if (first || d > m_max_comparable_radius)
|
||||
{
|
||||
m_max_comparable_radius = d;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PIECE_BORDER_HPP
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016, 2018.
|
||||
// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016-2023.
|
||||
// Modifications copyright (c) 2016-2023 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,
|
||||
@@ -15,8 +16,10 @@
|
||||
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
@@ -30,24 +33,40 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
template <typename Strategy>
|
||||
struct original_get_box
|
||||
{
|
||||
explicit original_get_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Original>
|
||||
static inline void apply(Box& total, Original const& original)
|
||||
inline void apply(Box& total, Original const& original) const
|
||||
{
|
||||
geometry::expand(total, original.m_box);
|
||||
assert_coordinate_type_equal(total, original.m_box);
|
||||
geometry::expand(total, original.m_box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct original_ovelaps_box
|
||||
template <typename Strategy>
|
||||
struct original_overlaps_box
|
||||
{
|
||||
explicit original_overlaps_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Original>
|
||||
static inline bool apply(Box const& box, Original const& original)
|
||||
inline bool apply(Box const& box, Original const& original) const
|
||||
{
|
||||
assert_coordinate_type_equal(box, original.m_box);
|
||||
return ! detail::disjoint::disjoint_box_box(box, original.m_box,
|
||||
DisjointBoxBoxStrategy());
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
struct include_turn_policy
|
||||
@@ -55,25 +74,31 @@ struct include_turn_policy
|
||||
template <typename Turn>
|
||||
static inline bool apply(Turn const& turn)
|
||||
{
|
||||
return turn.location == location_ok;
|
||||
return turn.is_turn_traversable;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct turn_in_original_ovelaps_box
|
||||
template <typename Strategy>
|
||||
struct turn_in_original_overlaps_box
|
||||
{
|
||||
explicit turn_in_original_overlaps_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
inline bool apply(Box const& box, Turn const& turn) const
|
||||
{
|
||||
if (turn.location != location_ok || turn.within_original)
|
||||
if (! turn.is_turn_traversable || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(
|
||||
turn.robust_point, box, DisjointPointBoxStrategy());
|
||||
turn.point, box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
//! Check if specified is in range of specified iterators
|
||||
@@ -150,16 +175,11 @@ inline bool point_in_section(Strategy& strategy, State& state,
|
||||
}
|
||||
|
||||
|
||||
template <typename Point, typename Original>
|
||||
inline int point_in_original(Point const& point, Original const& original)
|
||||
template <typename Point, typename Original, typename PointInGeometryStrategy>
|
||||
inline int point_in_original(Point const& point, Original const& original,
|
||||
PointInGeometryStrategy const& strategy)
|
||||
{
|
||||
// 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;
|
||||
typename PointInGeometryStrategy::state_type state;
|
||||
|
||||
if (boost::size(original.m_sections) == 0
|
||||
|| boost::size(original.m_ring) - boost::size(original.m_sections) < 16)
|
||||
@@ -172,20 +192,11 @@ inline int point_in_original(Point const& point, Original const& original)
|
||||
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);
|
||||
auto 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)
|
||||
for (auto const& section : original.m_sections)
|
||||
{
|
||||
section_type const& section = *it;
|
||||
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box)
|
||||
@@ -207,32 +218,38 @@ inline int point_in_original(Point const& point, Original const& original)
|
||||
}
|
||||
|
||||
|
||||
template <typename Turns>
|
||||
template <typename Turns, typename Strategy>
|
||||
class turn_in_original_visitor
|
||||
{
|
||||
public:
|
||||
turn_in_original_visitor(Turns& turns)
|
||||
turn_in_original_visitor(Turns& turns, Strategy const& strategy)
|
||||
: m_mutable_turns(turns)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Original>
|
||||
inline bool apply(Turn const& turn, Original const& original, bool first = true)
|
||||
inline bool apply(Turn const& turn, Original const& original)
|
||||
{
|
||||
boost::ignore_unused(first);
|
||||
if (boost::empty(original.m_ring))
|
||||
{
|
||||
// Skip empty rings
|
||||
return true;
|
||||
}
|
||||
|
||||
if (turn.location != location_ok || turn.within_original)
|
||||
if (! turn.is_turn_traversable || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return true;
|
||||
}
|
||||
|
||||
if (geometry::disjoint(turn.robust_point, original.m_box))
|
||||
if (geometry::disjoint(turn.point, original.m_box, m_strategy))
|
||||
{
|
||||
// Skip all disjoint
|
||||
return true;
|
||||
}
|
||||
|
||||
int const code = point_in_original(turn.robust_point, original);
|
||||
int const code = point_in_original(turn.point, original,
|
||||
m_strategy.relate(turn.point, original.m_ring));
|
||||
|
||||
if (code == -1)
|
||||
{
|
||||
@@ -244,7 +261,7 @@ public:
|
||||
if (code == 0)
|
||||
{
|
||||
// On border of original: always discard
|
||||
mutable_turn.location = location_discard;
|
||||
mutable_turn.is_turn_traversable = false;
|
||||
}
|
||||
|
||||
// Point is inside an original ring
|
||||
@@ -269,6 +286,7 @@ public:
|
||||
|
||||
private :
|
||||
Turns& m_mutable_turns;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,792 +1,54 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016, 2018.
|
||||
// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016-2022.
|
||||
// Modifications copyright (c) 2016-2022 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>
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR_HPP
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/config.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/dot_product.hpp>
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/comparable_distance.hpp>
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.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/dummy_geometries.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
struct piece_get_box
|
||||
{
|
||||
template <typename Box, typename Piece>
|
||||
static inline void apply(Box& total, Piece const& piece)
|
||||
{
|
||||
geometry::expand(total, piece.robust_envelope);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct piece_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Piece>
|
||||
static inline bool apply(Box const& box, Piece const& piece)
|
||||
{
|
||||
if (piece.type == strategy::buffer::buffered_flat_end
|
||||
|| piece.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// Turns cannot be inside a flat end (though they can be on border)
|
||||
// Neither we need to check if they are inside concave helper pieces
|
||||
|
||||
// Skip all pieces not used as soon as possible
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope,
|
||||
DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
struct turn_get_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline void apply(Box& total, Turn const& turn)
|
||||
{
|
||||
geometry::expand(total, turn.robust_point);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct turn_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
{
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum analyse_result
|
||||
{
|
||||
analyse_unknown,
|
||||
analyse_continue,
|
||||
analyse_disjoint,
|
||||
analyse_within,
|
||||
analyse_on_original_boundary,
|
||||
analyse_on_offsetted,
|
||||
analyse_near_offsetted
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
inline bool in_box(Point const& previous,
|
||||
Point const& current, Point const& point)
|
||||
{
|
||||
// Get its box (TODO: this can be prepared-on-demand later)
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, previous);
|
||||
geometry::expand(box, current);
|
||||
|
||||
return geometry::covered_by(point, box);
|
||||
}
|
||||
|
||||
// meta-programming-structure defining if to use side-of-intersection
|
||||
// (only for cartesian / only necessary with rescaling)
|
||||
template <typename Tag>
|
||||
struct use_side_of_intersection {};
|
||||
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
// With rescaling, let Cartesian use side-of-intersection
|
||||
template <>
|
||||
struct use_side_of_intersection<cartesian_tag> { static bool const value = true; };
|
||||
#else
|
||||
template <>
|
||||
struct use_side_of_intersection<cartesian_tag> { static bool const value = false; };
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct use_side_of_intersection<spherical_tag> { static bool const value = false; };
|
||||
|
||||
template <>
|
||||
struct use_side_of_intersection<geographic_tag> { static bool const value = false; };
|
||||
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
struct check_segment {};
|
||||
|
||||
// Implementation using side-of-intersection
|
||||
template <>
|
||||
struct check_segment<true>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (side == -1 && from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
if (side == 1 && from_monotonic)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_segment<false>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side = side_strategy::apply(previous, current, turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (side == -1)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
}
|
||||
};
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
class analyse_turn_wrt_point_piece {};
|
||||
|
||||
template <>
|
||||
class analyse_turn_wrt_point_piece<true>
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Piece::section_type section_type;
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef geometry::model::referring_segment<point_type const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
coordinate_type const point_x = geometry::get<0>(turn.robust_point);
|
||||
|
||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||
{
|
||||
section_type const& section = piece.sections[s];
|
||||
// If point within horizontal range of monotonic section:
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)
|
||||
{
|
||||
for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
|
||||
// First check if it is in range - if it is not, the
|
||||
// expensive side_of_intersection does not need to be
|
||||
// applied
|
||||
coordinate_type x1 = geometry::get<0>(previous);
|
||||
coordinate_type x2 = geometry::get<0>(current);
|
||||
|
||||
if (x1 > x2)
|
||||
{
|
||||
std::swap(x1, x2);
|
||||
}
|
||||
|
||||
if (point_x >= x1 - 1 && point_x <= x2 + 1)
|
||||
{
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
// Sections are monotonic in x-dimension
|
||||
if (side == 1)
|
||||
{
|
||||
// Left on segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
else if (side == 0)
|
||||
{
|
||||
// Collinear - TODO: check if really on segment
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It is nowhere outside, and not on segment, so it is within
|
||||
return analyse_within;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
class analyse_turn_wrt_point_piece<false>
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Piece::section_type section_type;
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
coordinate_type const point_x = geometry::get<0>(turn.robust_point);
|
||||
|
||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||
{
|
||||
section_type const& section = piece.sections[s];
|
||||
// If point within horizontal range of monotonic section:
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)
|
||||
{
|
||||
for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
analyse_result code = check_segment<false>::apply(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
// Get the state (to determine it is within), we don't have
|
||||
// to cover the on-segment case (covered above)
|
||||
strategy.apply(turn.robust_point, previous, current, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int const code = strategy.result(state);
|
||||
if (code == 1)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
else if (code == -1)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Should normally not occur - on-segment is covered
|
||||
return analyse_unknown;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
struct check_helper_segment {};
|
||||
|
||||
template <>
|
||||
struct check_helper_segment<true>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
boost::ignore_unused(is_original);
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(s1, s2);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 1)
|
||||
{
|
||||
// left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
else if (side == 0)
|
||||
{
|
||||
// If is collinear, either on segment or before/after
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, s1);
|
||||
geometry::expand(box, s2);
|
||||
|
||||
if (geometry::covered_by(turn.robust_point, box))
|
||||
{
|
||||
// Points on helper-segments (and not on its corners)
|
||||
// are considered as within
|
||||
return analyse_within;
|
||||
}
|
||||
|
||||
// It is collinear but not on the segment. Because these
|
||||
// segments are convex, it is outside
|
||||
// Unless the offsetted ring is collinear or concave w.r.t.
|
||||
// helper-segment but that scenario is not yet supported
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_helper_segment<false>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
|
||||
switch(side_strategy::apply(s1, s2, turn.robust_point))
|
||||
{
|
||||
case 1 :
|
||||
return analyse_disjoint; // left of segment
|
||||
case 0 :
|
||||
{
|
||||
// If is collinear, either on segment or before/after
|
||||
typedef geometry::model::box<Point> box_type;
|
||||
|
||||
box_type box;
|
||||
geometry::assign_inverse(box);
|
||||
geometry::expand(box, s1);
|
||||
geometry::expand(box, s2);
|
||||
|
||||
if (geometry::covered_by(turn.robust_point, box))
|
||||
{
|
||||
// It is on the segment
|
||||
if (! is_original
|
||||
&& geometry::comparable_distance(turn.robust_point, offsetted) <= 1)
|
||||
{
|
||||
// It is close to the offsetted-boundary, take
|
||||
// any rounding-issues into account
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
|
||||
// Points on helper-segments are considered as within
|
||||
// Points on original boundary are processed differently
|
||||
return is_original
|
||||
? analyse_on_original_boundary
|
||||
: analyse_within;
|
||||
}
|
||||
|
||||
// It is collinear but not on the segment. Because these
|
||||
// segments are convex, it is outside
|
||||
// Unless the offsetted ring is collinear or concave w.r.t.
|
||||
// helper-segment but that scenario is not yet supported
|
||||
return analyse_disjoint;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
}
|
||||
};
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
class analyse_turn_wrt_piece
|
||||
{
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
geometry::equal_to<point_type> comparator;
|
||||
|
||||
point_type points[4];
|
||||
|
||||
signed_size_type helper_count = static_cast<signed_size_type>(piece.robust_ring.size())
|
||||
- piece.offsetted_count;
|
||||
if (helper_count == 4)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
points[i] = piece.robust_ring[piece.offsetted_count + i];
|
||||
}
|
||||
|
||||
// 3--offsetted outline--0
|
||||
// | |
|
||||
// left | | right
|
||||
// | |
|
||||
// 2===>==original===>===1
|
||||
|
||||
}
|
||||
else if (helper_count == 3)
|
||||
{
|
||||
// Triangular piece, assign points but assign second twice
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int index = i < 2 ? i : i - 1;
|
||||
points[i] = piece.robust_ring[piece.offsetted_count + index];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some pieces (e.g. around points) do not have helper segments.
|
||||
// Others should have 3 (join) or 4 (side)
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
// First check point-equality
|
||||
point_type const& point = turn.robust_point;
|
||||
if (comparator(point, points[0]) || comparator(point, points[3]))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (comparator(point, points[1]))
|
||||
{
|
||||
// On original, right corner
|
||||
return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary;
|
||||
}
|
||||
if (comparator(point, points[2]))
|
||||
{
|
||||
// On original, left corner
|
||||
return piece.is_flat_start ? analyse_continue : analyse_on_original_boundary;
|
||||
}
|
||||
|
||||
// Right side of the piece
|
||||
analyse_result result
|
||||
= check_helper_segment<UseSideOfIntersection>::apply(points[0], points[1], turn,
|
||||
false, points[0]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Left side of the piece
|
||||
result = check_helper_segment<UseSideOfIntersection>::apply(points[2], points[3], turn,
|
||||
false, points[3]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (! comparator(points[1], points[2]))
|
||||
{
|
||||
// Side of the piece at side of original geometry
|
||||
result = check_helper_segment<UseSideOfIntersection>::apply(points[1], points[2], turn,
|
||||
true, point);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// We are within the \/ or |_| shaped piece, where the top is the
|
||||
// offsetted ring.
|
||||
if (! geometry::covered_by(point, piece.robust_offsetted_envelope))
|
||||
{
|
||||
// Not in offsetted-area. This makes a cheap check possible
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
switch(side_strategy::apply(points[3], points[0], point))
|
||||
{
|
||||
case 1 : return analyse_disjoint;
|
||||
case -1 : return analyse_within;
|
||||
case 0 : return analyse_disjoint;
|
||||
}
|
||||
}
|
||||
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
template <typename Turn, typename Piece, typename Compare>
|
||||
static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare)
|
||||
{
|
||||
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||
typedef typename ring_type::const_iterator it_type;
|
||||
it_type end = piece.robust_ring.begin() + piece.offsetted_count;
|
||||
it_type it = std::lower_bound(piece.robust_ring.begin(),
|
||||
end,
|
||||
turn.robust_point,
|
||||
compare);
|
||||
|
||||
if (it != end
|
||||
&& it != piece.robust_ring.begin())
|
||||
{
|
||||
// iterator points to point larger than point
|
||||
// w.r.t. specified direction, and prev points to a point smaller
|
||||
// We now know if it is inside/outside
|
||||
it_type prev = it - 1;
|
||||
return check_segment<UseSideOfIntersection>::apply(*prev, *it, turn, true);
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
analyse_result code = check_helper_segments(turn, piece);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
geometry::equal_to<point_type> comparator;
|
||||
|
||||
if (piece.offsetted_count > 8)
|
||||
{
|
||||
// If the offset contains some points and is monotonic, we try
|
||||
// to avoid walking all points linearly.
|
||||
// We try it only once.
|
||||
if (piece.is_monotonic_increasing[0])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::less<point_type, 0>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
else if (piece.is_monotonic_increasing[1])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::less<point_type, 1>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
else if (piece.is_monotonic_decreasing[0])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::greater<point_type, 0>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
else if (piece.is_monotonic_decreasing[1])
|
||||
{
|
||||
code = check_monotonic(turn, piece, geometry::greater<point_type, 1>());
|
||||
if (code != analyse_continue) return code;
|
||||
}
|
||||
}
|
||||
|
||||
// It is small or not monotonic, walk linearly through offset
|
||||
// TODO: this will be combined with winding strategy
|
||||
|
||||
for (signed_size_type i = 1; i < piece.offsetted_count; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
// The robust ring can contain duplicates
|
||||
// (on which any side or side-value would return 0)
|
||||
if (! comparator(previous, current))
|
||||
{
|
||||
code = check_segment<UseSideOfIntersection>::apply(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return analyse_unknown;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Helper Structure, of which the apply method returns a side value in {-1, 0, 1}
|
||||
template <bool UseSideOfIntersection>
|
||||
struct turn_in_piece {};
|
||||
|
||||
template <>
|
||||
struct turn_in_piece<true>
|
||||
{
|
||||
|
||||
private :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline int in_convex_piece(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||
typedef geometry::model::referring_segment<point_type const> segment;
|
||||
|
||||
segment const p(turn.rob_pi, turn.rob_pj);
|
||||
segment const q(turn.rob_qi, turn.rob_qj);
|
||||
|
||||
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
|
||||
iterator_type it = boost::begin(piece.robust_ring);
|
||||
iterator_type end = boost::end(piece.robust_ring);
|
||||
|
||||
// A robust ring is always closed, and always clockwise
|
||||
for (iterator_type previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
geometry::equal_to<point_type> comparator;
|
||||
if (comparator(*previous, *it))
|
||||
{
|
||||
// Points are the same
|
||||
continue;
|
||||
}
|
||||
|
||||
segment r(*previous, *it);
|
||||
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 1)
|
||||
{
|
||||
// IP is left of segment, so it is outside
|
||||
return -1; // outside
|
||||
}
|
||||
else if (side == 0)
|
||||
{
|
||||
// IP is collinear with segment. TODO: we should analyze this further
|
||||
// For now we use the fallback point
|
||||
if (in_box(*previous, *it, turn.robust_point))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; // outside
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1; // inside
|
||||
}
|
||||
|
||||
public :
|
||||
|
||||
template <typename Turn, typename Piece, typename Strategy>
|
||||
static inline int apply(Turn const& turn, Piece const& piece,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (piece.is_convex)
|
||||
{
|
||||
return in_convex_piece(turn, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
// side-of-intersection only supported for convex pieces
|
||||
// Call point_in_geometry, a performance-bottleneck
|
||||
// TODO: might be replaced by extending analysing piece
|
||||
return detail::within::point_in_geometry(turn.robust_point,
|
||||
piece.robust_ring, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_piece<false>
|
||||
{
|
||||
public :
|
||||
|
||||
template <typename Turn, typename Piece, typename Strategy>
|
||||
static inline int apply(Turn const& turn, Piece const& piece,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::within::point_in_geometry(turn.robust_point,
|
||||
piece.robust_ring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename CsTag,
|
||||
typename Turns,
|
||||
typename Pieces,
|
||||
typename PointInGeometryStrategy
|
||||
typename DistanceStrategy,
|
||||
typename UmbrellaStrategy
|
||||
|
||||
>
|
||||
class turn_in_piece_visitor
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
Pieces const& m_pieces; // to check for piece-type
|
||||
PointInGeometryStrategy const& m_point_in_geometry_strategy;
|
||||
DistanceStrategy const& m_distance_strategy; // to check if point is on original or one_sided
|
||||
UmbrellaStrategy const& m_umbrella_strategy;
|
||||
|
||||
template <typename Operation, typename Piece>
|
||||
inline bool skip(Operation const& op, Piece const& piece) const
|
||||
@@ -815,24 +77,40 @@ class turn_in_piece_visitor
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename NumericType>
|
||||
inline bool is_one_sided(NumericType const& left, NumericType const& right) const
|
||||
{
|
||||
static NumericType const zero = 0;
|
||||
return geometry::math::equals(left, zero)
|
||||
|| geometry::math::equals(right, zero);
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
inline bool has_zero_distance_at(Point const& point) const
|
||||
{
|
||||
return is_one_sided(m_distance_strategy.apply(point, point,
|
||||
strategy::buffer::buffer_side_left),
|
||||
m_distance_strategy.apply(point, point,
|
||||
strategy::buffer::buffer_side_right));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
|
||||
PointInGeometryStrategy const& strategy)
|
||||
DistanceStrategy const& distance_strategy,
|
||||
UmbrellaStrategy const& umbrella_strategy)
|
||||
: m_turns(turns)
|
||||
, m_pieces(pieces)
|
||||
, m_point_in_geometry_strategy(strategy)
|
||||
, m_distance_strategy(distance_strategy)
|
||||
, m_umbrella_strategy(umbrella_strategy)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
inline bool apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
inline bool apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
boost::ignore_unused(first);
|
||||
|
||||
if (turn.count_within > 0)
|
||||
if (! turn.is_turn_traversable)
|
||||
{
|
||||
// Already inside - no need to check again
|
||||
// Already handled
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -843,78 +121,63 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))
|
||||
{
|
||||
// Easy check: if the turn is not in the envelope, we can safely return
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: mutable_piece to make some on-demand preparations in analyse
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
return apply(turn, piece, piece.m_piece_border);
|
||||
}
|
||||
|
||||
template <typename Turn, typename Piece, typename Border>
|
||||
inline bool apply(Turn const& turn, Piece const& piece, Border const& border)
|
||||
{
|
||||
if (! geometry::covered_by(turn.point, border.m_envelope, m_umbrella_strategy))
|
||||
{
|
||||
// Easy check: if turn is not in the (expanded) envelope
|
||||
return true;
|
||||
}
|
||||
|
||||
if (piece.type == geometry::strategy::buffer::buffered_empty_side)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
// Optimization for a buffer around points: if distance from center
|
||||
// is not between min/max radius, it is either inside or outside,
|
||||
// and more expensive checks are not necessary.
|
||||
auto const d = geometry::comparable_distance(piece.m_center, turn.point,
|
||||
m_umbrella_strategy);
|
||||
|
||||
distance_type const cd
|
||||
= geometry::comparable_distance(piece.robust_center,
|
||||
turn.robust_point);
|
||||
|
||||
if (cd < piece.robust_min_comparable_radius)
|
||||
if (d < border.m_min_comparable_radius)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
mutable_turn.is_turn_traversable = false;
|
||||
return true;
|
||||
}
|
||||
if (cd > piece.robust_max_comparable_radius)
|
||||
if (d > border.m_max_comparable_radius)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const bool use_soi = use_side_of_intersection<CsTag>::value;
|
||||
boost::ignore_unused(use_soi);
|
||||
// Check if buffer is one-sided (at this point), because then a point
|
||||
// on the original border is not considered as within.
|
||||
bool const one_sided = has_zero_distance_at(turn.point);
|
||||
|
||||
analyse_result analyse_code =
|
||||
piece.type == geometry::strategy::buffer::buffered_point
|
||||
? analyse_turn_wrt_point_piece<use_soi>::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece<use_soi>::apply(turn, piece);
|
||||
|
||||
switch(analyse_code)
|
||||
typename Border::state_type state;
|
||||
if (! border.point_on_piece(turn.point, one_sided,
|
||||
turn.is_linear_end_point, state))
|
||||
{
|
||||
case analyse_disjoint :
|
||||
return true;
|
||||
case analyse_on_offsetted :
|
||||
mutable_turn.count_on_offsetted++; // value is not used anymore
|
||||
return true;
|
||||
case analyse_on_original_boundary :
|
||||
mutable_turn.count_on_original_boundary++;
|
||||
return true;
|
||||
case analyse_within :
|
||||
mutable_turn.count_within++;
|
||||
return true;
|
||||
case analyse_near_offsetted :
|
||||
mutable_turn.count_within_near_offsetted++;
|
||||
return true;
|
||||
default :
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
int const geometry_code = turn_in_piece<use_soi>::apply(turn, piece,
|
||||
m_point_in_geometry_strategy);
|
||||
|
||||
if (geometry_code == 1)
|
||||
if (state.is_inside() && ! state.is_on_boundary())
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
mutable_turn.is_turn_traversable = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -928,4 +191,4 @@ public:
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR_HPP
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2019-2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_POINT_ORDER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_POINT_ORDER_HPP
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/static_assert.hpp>
|
||||
#include <boost/geometry/strategies/geographic/point_order.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Iter, typename CalcT>
|
||||
struct clean_point
|
||||
{
|
||||
explicit clean_point(Iter const& iter)
|
||||
: m_iter(iter), m_azi(0), m_razi(0), m_azi_diff(0)
|
||||
, m_is_azi_valid(false), m_is_azi_diff_valid(false)
|
||||
{}
|
||||
|
||||
decltype(auto) ref() const
|
||||
{
|
||||
return *m_iter;
|
||||
}
|
||||
|
||||
CalcT const& azimuth() const
|
||||
{
|
||||
return m_azi;
|
||||
}
|
||||
|
||||
CalcT const& reverse_azimuth() const
|
||||
{
|
||||
return m_razi;
|
||||
}
|
||||
|
||||
CalcT const& azimuth_difference() const
|
||||
{
|
||||
return m_azi_diff;
|
||||
}
|
||||
|
||||
void set_azimuths(CalcT const& azi, CalcT const& razi)
|
||||
{
|
||||
m_azi = azi;
|
||||
m_razi = razi;
|
||||
m_is_azi_valid = true;
|
||||
}
|
||||
|
||||
void set_azimuth_invalid()
|
||||
{
|
||||
m_is_azi_valid = false;
|
||||
}
|
||||
|
||||
bool is_azimuth_valid() const
|
||||
{
|
||||
return m_is_azi_valid;
|
||||
}
|
||||
|
||||
void set_azimuth_difference(CalcT const& diff)
|
||||
{
|
||||
m_azi_diff = diff;
|
||||
m_is_azi_diff_valid = true;
|
||||
}
|
||||
|
||||
void set_azimuth_difference_invalid()
|
||||
{
|
||||
m_is_azi_diff_valid = false;
|
||||
}
|
||||
|
||||
bool is_azimuth_difference_valid() const
|
||||
{
|
||||
return m_is_azi_diff_valid;
|
||||
}
|
||||
|
||||
private:
|
||||
Iter m_iter;
|
||||
CalcT m_azi;
|
||||
CalcT m_razi;
|
||||
CalcT m_azi_diff;
|
||||
// NOTE: these flags could be removed and replaced with some magic number
|
||||
// assigned to the above variables, e.g. CalcT(1000).
|
||||
bool m_is_azi_valid;
|
||||
bool m_is_azi_diff_valid;
|
||||
};
|
||||
|
||||
struct calculate_point_order_by_azimuth
|
||||
{
|
||||
template <typename Ring, typename Strategy>
|
||||
static geometry::order_selector apply(Ring const& ring, Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator<Ring const>::type iter_t;
|
||||
typedef typename Strategy::template result_type<Ring>::type calc_t;
|
||||
typedef clean_point<iter_t, calc_t> clean_point_t;
|
||||
|
||||
calc_t const zero = 0;
|
||||
calc_t const pi = math::pi<calc_t>();
|
||||
|
||||
std::size_t const count = boost::size(ring);
|
||||
if (count < 3)
|
||||
{
|
||||
return geometry::order_undetermined;
|
||||
}
|
||||
|
||||
// non-duplicated, non-spike points
|
||||
std::vector<clean_point_t> cleaned;
|
||||
cleaned.reserve(count);
|
||||
|
||||
for (iter_t it = boost::begin(ring); it != boost::end(ring); ++it)
|
||||
{
|
||||
// Add point
|
||||
cleaned.push_back(clean_point_t(it));
|
||||
|
||||
while (cleaned.size() >= 3)
|
||||
{
|
||||
auto it0 = cleaned.end() - 3;
|
||||
auto it1 = cleaned.end() - 2;
|
||||
auto it2 = cleaned.end() - 1;
|
||||
|
||||
calc_t diff;
|
||||
if (get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
|
||||
&& ! math::equals(math::abs(diff), pi))
|
||||
{
|
||||
// neither duplicate nor a spike - difference already stored
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// spike detected
|
||||
// TODO: angles have to be invalidated only if spike is detected
|
||||
// for duplicates it'd be ok to leave them
|
||||
it0->set_azimuth_invalid();
|
||||
it0->set_azimuth_difference_invalid();
|
||||
it2->set_azimuth_difference_invalid();
|
||||
cleaned.erase(it1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// filter-out duplicates and spikes at the front and back of cleaned
|
||||
auto cleaned_b = cleaned.begin();
|
||||
auto cleaned_e = cleaned.end();
|
||||
std::size_t cleaned_count = cleaned.size();
|
||||
bool found = false;
|
||||
do
|
||||
{
|
||||
found = false;
|
||||
while(cleaned_count >= 3)
|
||||
{
|
||||
auto it0 = cleaned_e - 2;
|
||||
auto it1 = cleaned_e - 1;
|
||||
auto it2 = cleaned_b;
|
||||
auto it3 = cleaned_b + 1;
|
||||
|
||||
calc_t diff = 0;
|
||||
if (! get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
|
||||
|| math::equals(math::abs(diff), pi))
|
||||
{
|
||||
// spike at the back
|
||||
// TODO: angles have to be invalidated only if spike is detected
|
||||
// for duplicates it'd be ok to leave them
|
||||
it0->set_azimuth_invalid();
|
||||
it0->set_azimuth_difference_invalid();
|
||||
it2->set_azimuth_difference_invalid();
|
||||
--cleaned_e;
|
||||
--cleaned_count;
|
||||
found = true;
|
||||
}
|
||||
else if (! get_or_calculate_azimuths_difference(*it1, *it2, *it3, diff, strategy)
|
||||
|| math::equals(math::abs(diff), pi))
|
||||
{
|
||||
// spike at the front
|
||||
// TODO: angles have to be invalidated only if spike is detected
|
||||
// for duplicates it'd be ok to leave them
|
||||
it1->set_azimuth_invalid();
|
||||
it1->set_azimuth_difference_invalid();
|
||||
it3->set_azimuth_difference_invalid();
|
||||
++cleaned_b;
|
||||
--cleaned_count;
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (found);
|
||||
|
||||
if (cleaned_count < 3)
|
||||
{
|
||||
return geometry::order_undetermined;
|
||||
}
|
||||
|
||||
// calculate the sum of external angles
|
||||
calc_t angles_sum = zero;
|
||||
for (auto it = cleaned_b; it != cleaned_e; ++it)
|
||||
{
|
||||
auto it0 = (it == cleaned_b ? cleaned_e - 1 : it - 1);
|
||||
auto it2 = (it == cleaned_e - 1 ? cleaned_b : it + 1);
|
||||
|
||||
calc_t diff = 0;
|
||||
get_or_calculate_azimuths_difference(*it0, *it, *it2, diff, strategy);
|
||||
|
||||
angles_sum += diff;
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_POINT_ORDER
|
||||
std::cout << angles_sum << " for " << geometry::wkt(ring) << std::endl;
|
||||
#endif
|
||||
|
||||
return angles_sum == zero ? geometry::order_undetermined
|
||||
: angles_sum > zero ? geometry::clockwise
|
||||
: geometry::counterclockwise;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Iter, typename T, typename Strategy>
|
||||
static bool get_or_calculate_azimuths_difference(clean_point<Iter, T> & p0,
|
||||
clean_point<Iter, T> & p1,
|
||||
clean_point<Iter, T> const& p2,
|
||||
T & diff,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (p1.is_azimuth_difference_valid())
|
||||
{
|
||||
diff = p1.azimuth_difference();
|
||||
return true;
|
||||
}
|
||||
|
||||
T azi1, razi1, azi2, razi2;
|
||||
if (get_or_calculate_azimuths(p0, p1, azi1, razi1, strategy)
|
||||
&& get_or_calculate_azimuths(p1, p2, azi2, razi2, strategy))
|
||||
{
|
||||
diff = strategy.apply(p0.ref(), p1.ref(), p2.ref(), razi1, azi2);
|
||||
p1.set_azimuth_difference(diff);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iter, typename T, typename Strategy>
|
||||
static bool get_or_calculate_azimuths(clean_point<Iter, T> & p0,
|
||||
clean_point<Iter, T> const& p1,
|
||||
T & azi, T & razi,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (p0.is_azimuth_valid())
|
||||
{
|
||||
azi = p0.azimuth();
|
||||
razi = p0.reverse_azimuth();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strategy.apply(p0.ref(), p1.ref(), azi, razi))
|
||||
{
|
||||
p0.set_azimuths(azi, razi);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct calculate_point_order_by_area
|
||||
{
|
||||
template <typename Ring, typename Strategy>
|
||||
static geometry::order_selector apply(Ring const& ring, Strategy const& strategy)
|
||||
{
|
||||
auto const result = detail::area::ring_area::apply(
|
||||
ring,
|
||||
// TEMP - in the future (umbrella) strategy will be passed
|
||||
geometry::strategies::area::services::strategy_converter
|
||||
<
|
||||
decltype(strategy.get_area_strategy())
|
||||
>::get(strategy.get_area_strategy()));
|
||||
|
||||
decltype(result) const zero = 0;
|
||||
return result == zero ? geometry::order_undetermined
|
||||
: result > zero ? geometry::clockwise
|
||||
: geometry::counterclockwise;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
typename VersionTag = typename Strategy::version_tag
|
||||
>
|
||||
struct calculate_point_order
|
||||
{
|
||||
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
|
||||
"Not implemented for this VersionTag.",
|
||||
VersionTag);
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct calculate_point_order<Strategy, strategy::point_order::area_tag>
|
||||
: geometry::detail::calculate_point_order_by_area
|
||||
{};
|
||||
|
||||
template <typename Strategy>
|
||||
struct calculate_point_order<Strategy, strategy::point_order::azimuth_tag>
|
||||
: geometry::detail::calculate_point_order_by_azimuth
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Ring, typename Strategy>
|
||||
inline geometry::order_selector calculate_point_order(Ring const& ring, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Ring const>();
|
||||
|
||||
return dispatch::calculate_point_order<Strategy>::apply(ring, strategy);
|
||||
}
|
||||
|
||||
template <typename Ring>
|
||||
inline geometry::order_selector calculate_point_order(Ring const& ring)
|
||||
{
|
||||
typedef typename strategy::point_order::services::default_strategy
|
||||
<
|
||||
typename geometry::cs_tag<Ring>::type
|
||||
>::type strategy_type;
|
||||
|
||||
concepts::check<Ring const>();
|
||||
|
||||
return dispatch::calculate_point_order<strategy_type>::apply(ring, strategy_type());
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_POINT_ORDER_HPP
|
||||
@@ -8,9 +8,10 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2016-2020.
|
||||
// Modifications copyright (c) 2016-2020 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
|
||||
@@ -19,7 +20,8 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -35,8 +37,7 @@ class calculate_polygon_sum
|
||||
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)
|
||||
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
sum += Policy::apply(*it, strategy);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ 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)
|
||||
{
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// 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
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
typename RangeIterator,
|
||||
typename Strategy,
|
||||
typename Distance
|
||||
>
|
||||
>
|
||||
static inline RangeIterator apply(Geometry const& geometry,
|
||||
RangeIterator first,
|
||||
RangeIterator last,
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
typename Geometry,
|
||||
typename RangeIterator,
|
||||
typename Strategy
|
||||
>
|
||||
>
|
||||
static inline RangeIterator apply(Geometry const& geometry,
|
||||
RangeIterator first,
|
||||
RangeIterator last,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -12,7 +12,9 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
@@ -34,15 +36,14 @@ template
|
||||
<
|
||||
typename Point,
|
||||
typename Range,
|
||||
closure_selector Closure,
|
||||
typename Strategy
|
||||
closure_selector Closure
|
||||
>
|
||||
class point_to_point_range
|
||||
{
|
||||
protected:
|
||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
||||
|
||||
template <typename Distance>
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline void apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
@@ -71,8 +72,11 @@ protected:
|
||||
// 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))
|
||||
Distance const dist = strategy.apply(point, *prev, *it);
|
||||
|
||||
// Stop only if we find exactly zero distance
|
||||
// otherwise it may stop at some very small value and miss the min
|
||||
if (dist == zero)
|
||||
{
|
||||
dist_min = zero;
|
||||
it_min1 = prev;
|
||||
@@ -93,7 +97,7 @@ protected:
|
||||
public:
|
||||
typedef typename std::pair<iterator_type, iterator_type> return_type;
|
||||
|
||||
template <typename Distance>
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
@@ -106,6 +110,7 @@ public:
|
||||
return std::make_pair(it_min1, it_min2);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
@@ -121,7 +126,7 @@ public:
|
||||
return apply(point, first, last, strategy, dist_min);
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy,
|
||||
@@ -134,6 +139,7 @@ public:
|
||||
dist_min);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy)
|
||||
@@ -145,15 +151,15 @@ public:
|
||||
|
||||
|
||||
// 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>
|
||||
template <typename Point, typename Range>
|
||||
class point_to_point_range<Point, Range, open>
|
||||
: point_to_point_range<Point, Range, closed>
|
||||
{
|
||||
private:
|
||||
typedef point_to_point_range<Point, Range, closed, Strategy> base_type;
|
||||
typedef point_to_point_range<Point, Range, closed> base_type;
|
||||
typedef typename base_type::iterator_type iterator_type;
|
||||
|
||||
template <typename Distance>
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline void apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
@@ -183,12 +189,12 @@ private:
|
||||
it_min1 = it_back;
|
||||
it_min2 = first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename std::pair<iterator_type, iterator_type> return_type;
|
||||
|
||||
template <typename Distance>
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
@@ -202,6 +208,7 @@ public:
|
||||
return std::make_pair(it_min1, it_min2);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
@@ -219,7 +226,7 @@ public:
|
||||
return apply(point, first, last, strategy, dist_min);
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy,
|
||||
@@ -232,6 +239,7 @@ public:
|
||||
dist_min);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014, 2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -40,7 +41,7 @@ private:
|
||||
<
|
||||
typename RTreeRangeIterator,
|
||||
typename QueryRangeIterator,
|
||||
typename Strategy,
|
||||
typename Strategies,
|
||||
typename RTreeValueType,
|
||||
typename Distance
|
||||
>
|
||||
@@ -48,12 +49,16 @@ private:
|
||||
RTreeRangeIterator rtree_last,
|
||||
QueryRangeIterator queries_first,
|
||||
QueryRangeIterator queries_last,
|
||||
Strategy const& strategy,
|
||||
Strategies const& strategies,
|
||||
RTreeValueType& rtree_min,
|
||||
QueryRangeIterator& qit_min,
|
||||
Distance& dist_min)
|
||||
{
|
||||
typedef index::rtree<RTreeValueType, index::linear<8> > rtree_type;
|
||||
typedef index::parameters
|
||||
<
|
||||
index::linear<8>, Strategies
|
||||
> index_parameters_type;
|
||||
typedef index::rtree<RTreeValueType, index_parameters_type> rtree_type;
|
||||
|
||||
BOOST_GEOMETRY_ASSERT( rtree_first != rtree_last );
|
||||
BOOST_GEOMETRY_ASSERT( queries_first != queries_last );
|
||||
@@ -62,7 +67,8 @@ private:
|
||||
dist_min = zero;
|
||||
|
||||
// create -- packing algorithm
|
||||
rtree_type rt(rtree_first, rtree_last);
|
||||
rtree_type rt(rtree_first, rtree_last,
|
||||
index_parameters_type(index::linear<8>(), strategies));
|
||||
|
||||
RTreeValueType t_v;
|
||||
bool first = true;
|
||||
@@ -88,8 +94,8 @@ private:
|
||||
<
|
||||
QueryRangeIterator
|
||||
>::value_type,
|
||||
Strategy
|
||||
>::apply(t_v, *qit, strategy);
|
||||
Strategies
|
||||
>::apply(t_v, *qit, strategies);
|
||||
|
||||
if (first || dist < dist_min)
|
||||
{
|
||||
@@ -144,7 +150,7 @@ public:
|
||||
apply(rtree_first, rtree_last, queries_first, queries_last,
|
||||
strategy, rtree_min, qit_min, dist_min);
|
||||
|
||||
return std::make_pair(rtree_min, qit_min);
|
||||
return std::make_pair(rtree_min, qit_min);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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,325 @@
|
||||
// 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/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
|
||||
@@ -3,11 +3,13 @@
|
||||
// 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) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// 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.
|
||||
@@ -19,13 +21,18 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#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>
|
||||
#include <boost/geometry/strategies/distance/comparable.hpp>
|
||||
#include <boost/geometry/strategies/distance/services.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -35,47 +42,70 @@ namespace boost { namespace geometry
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
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)
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
return dispatch::distance
|
||||
<
|
||||
Strategy
|
||||
>::type comparable_strategy_type;
|
||||
Geometry1, Geometry2,
|
||||
strategies::distance::detail::comparable<Strategies>
|
||||
>::apply(geometry1,
|
||||
geometry2,
|
||||
strategies::distance::detail::comparable<Strategies>(strategies));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct comparable_distance<Strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using strategies::distance::services::strategy_converter;
|
||||
|
||||
using comparable_strategies_type = strategies::distance::detail::comparable
|
||||
<
|
||||
decltype(strategy_converter<Strategy>::get(strategy))
|
||||
>;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, comparable_strategy_type
|
||||
Geometry1, Geometry2,
|
||||
comparable_strategies_type
|
||||
>::apply(geometry1,
|
||||
geometry2,
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy));
|
||||
comparable_strategies_type(
|
||||
strategy_converter<Strategy>::get(strategy)));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct comparable_distance<default_strategy, false>
|
||||
{
|
||||
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)
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
using comparable_strategy_type = strategies::distance::detail::comparable
|
||||
<
|
||||
typename detail::distance::default_strategy
|
||||
typename strategies::distance::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type
|
||||
>::type comparable_strategy_type;
|
||||
>;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
@@ -87,211 +117,110 @@ struct comparable_distance
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
|
||||
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)
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type
|
||||
>
|
||||
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
|
||||
>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
typename comparable_distance_result
|
||||
return resolve_strategy::comparable_distance
|
||||
<
|
||||
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);
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
|
||||
struct comparable_distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline auto apply(DynamicGeometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using result_t = typename geometry::comparable_distance_result
|
||||
<
|
||||
DynamicGeometry1, Geometry2, Strategy
|
||||
>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
|
||||
{
|
||||
result = resolve_strategy::comparable_distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, geometry2, strategy);
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
|
||||
struct comparable_distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
DynamicGeometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using result_t = typename geometry::comparable_distance_result
|
||||
<
|
||||
Geometry1, DynamicGeometry2, Strategy
|
||||
>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::comparable_distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, g2, strategy);
|
||||
}, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename DynamicGeometry1, typename DynamicGeometry2>
|
||||
struct comparable_distance
|
||||
<
|
||||
DynamicGeometry1, DynamicGeometry2,
|
||||
dynamic_geometry_tag, dynamic_geometry_tag
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline auto apply(DynamicGeometry1 const& geometry1,
|
||||
DynamicGeometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using result_t = typename geometry::comparable_distance_result
|
||||
<
|
||||
DynamicGeometry1, DynamicGeometry2, Strategy
|
||||
>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::comparable_distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
|
||||
@@ -314,14 +243,14 @@ struct 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)
|
||||
inline auto comparable_distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return resolve_variant::comparable_distance
|
||||
return resolve_dynamic::comparable_distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
@@ -347,12 +276,9 @@ comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
\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)
|
||||
inline auto comparable_distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return geometry::comparable_distance(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,12 @@ namespace detail { namespace conversion
|
||||
{
|
||||
|
||||
|
||||
// TODO: Use assignment if possible.
|
||||
// WARNING: This utility is called in various places for a subset of dimensions.
|
||||
// In such cases only some of the coordinates should be copied. Alternatively
|
||||
// there should be a different utility for that called differently than
|
||||
// convert_xxx, e.g. set_coordinates.
|
||||
|
||||
template <typename Source, typename Destination, std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct point_to_point
|
||||
{
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2018.
|
||||
// Modifications copyright (c) 2014, 2018 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014-2023.
|
||||
// Modifications copyright (c) 2014-2023 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -14,64 +15,46 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/views/detail/range_type.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace convex_hull
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
namespace detail { namespace convex_hull
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename InputRange,
|
||||
typename RangeIterator,
|
||||
typename StrategyLess,
|
||||
typename StrategyGreater
|
||||
>
|
||||
struct get_extremes
|
||||
// TODO: All of the copies could be avoided if this function stored pointers to points.
|
||||
// But would it be possible considering that a range can return proxy reference?
|
||||
template <typename InputProxy, typename Point, typename Less>
|
||||
inline void get_extremes(InputProxy const& in_proxy,
|
||||
Point& left, Point& right,
|
||||
Less const& less)
|
||||
{
|
||||
typedef typename point_type<InputRange>::type point_type;
|
||||
|
||||
point_type left, right;
|
||||
|
||||
bool first;
|
||||
|
||||
StrategyLess less;
|
||||
StrategyGreater greater;
|
||||
|
||||
inline get_extremes()
|
||||
: first(true)
|
||||
{}
|
||||
|
||||
inline void apply(InputRange const& range)
|
||||
bool first = true;
|
||||
in_proxy.for_each_range([&](auto const& range)
|
||||
{
|
||||
if (boost::size(range) == 0)
|
||||
if (boost::empty(range))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -82,19 +65,18 @@ struct get_extremes
|
||||
// not persistent (in MSVC) this approach is not applicable
|
||||
// for more ranges together)
|
||||
|
||||
RangeIterator left_it = boost::begin(range);
|
||||
RangeIterator right_it = boost::begin(range);
|
||||
auto left_it = boost::begin(range);
|
||||
auto right_it = boost::begin(range);
|
||||
|
||||
for (RangeIterator it = boost::begin(range) + 1;
|
||||
it != boost::end(range);
|
||||
++it)
|
||||
auto it = boost::begin(range);
|
||||
for (++it; it != boost::end(range); ++it)
|
||||
{
|
||||
if (less(*it, *left_it))
|
||||
{
|
||||
left_it = it;
|
||||
}
|
||||
|
||||
if (greater(*it, *right_it))
|
||||
if (less(*right_it, *it))
|
||||
{
|
||||
right_it = it;
|
||||
}
|
||||
@@ -117,48 +99,29 @@ struct get_extremes
|
||||
left = *left_it;
|
||||
}
|
||||
|
||||
if (greater(*right_it, right))
|
||||
if (less(right, *right_it))
|
||||
{
|
||||
right = *right_it;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename InputRange,
|
||||
typename RangeIterator,
|
||||
typename Container,
|
||||
typename SideStrategy
|
||||
>
|
||||
struct assign_range
|
||||
template <typename InputProxy, typename Point, typename Container, typename SideStrategy>
|
||||
inline void assign_ranges(InputProxy const& in_proxy,
|
||||
Point const& most_left, Point const& most_right,
|
||||
Container& lower_points, Container& upper_points,
|
||||
SideStrategy const& side)
|
||||
{
|
||||
Container lower_points, upper_points;
|
||||
|
||||
typedef typename point_type<InputRange>::type point_type;
|
||||
|
||||
point_type const& most_left;
|
||||
point_type const& most_right;
|
||||
|
||||
inline assign_range(point_type const& left, point_type const& right)
|
||||
: most_left(left)
|
||||
, most_right(right)
|
||||
{}
|
||||
|
||||
inline void apply(InputRange const& range)
|
||||
in_proxy.for_each_range([&](auto const& range)
|
||||
{
|
||||
typedef SideStrategy side;
|
||||
|
||||
// Put points in one of the two output sequences
|
||||
for (RangeIterator it = boost::begin(range);
|
||||
it != boost::end(range);
|
||||
++it)
|
||||
for (auto it = boost::begin(range); it != boost::end(range); ++it)
|
||||
{
|
||||
// check if it is lying most_left or most_right from the line
|
||||
|
||||
int dir = side::apply(most_left, most_right, *it);
|
||||
int dir = side.apply(most_left, most_right, *it);
|
||||
switch(dir)
|
||||
{
|
||||
case 1 : // left side
|
||||
@@ -173,41 +136,18 @@ struct assign_range
|
||||
// -> all never part of hull
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Range>
|
||||
static inline void sort(Range& range)
|
||||
{
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
typedef geometry::less<point_type> comparator;
|
||||
|
||||
std::sort(boost::begin(range), boost::end(range), comparator());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
/*!
|
||||
\brief Graham scan strategy to calculate convex hull
|
||||
\ingroup strategies
|
||||
\brief Graham scan algorithm to calculate convex hull
|
||||
*/
|
||||
template <typename InputGeometry, typename OutputPoint>
|
||||
template <typename InputPoint>
|
||||
class graham_andrew
|
||||
{
|
||||
public :
|
||||
typedef OutputPoint point_type;
|
||||
typedef InputGeometry geometry_type;
|
||||
|
||||
private:
|
||||
|
||||
typedef typename cs_tag<point_type>::type cs_tag;
|
||||
|
||||
typedef InputPoint point_type;
|
||||
typedef typename std::vector<point_type> container_type;
|
||||
typedef typename std::vector<point_type>::const_iterator iterator;
|
||||
typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
|
||||
|
||||
|
||||
class partitions
|
||||
{
|
||||
@@ -218,12 +158,23 @@ private:
|
||||
container_type m_copied_input;
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
typedef partitions state_type;
|
||||
template <typename InputProxy, typename OutputRing, typename Strategy>
|
||||
static void apply(InputProxy const& in_proxy, OutputRing & out_ring, Strategy& strategy)
|
||||
{
|
||||
partitions state;
|
||||
|
||||
apply(in_proxy, state, strategy);
|
||||
|
||||
inline void apply(InputGeometry const& geometry, partitions& state) const
|
||||
result(state,
|
||||
range::back_inserter(out_ring),
|
||||
geometry::point_order<OutputRing>::value == clockwise,
|
||||
geometry::closure<OutputRing>::value != open);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename InputProxy, typename Strategy>
|
||||
static void apply(InputProxy const& in_proxy, partitions& state, Strategy& strategy)
|
||||
{
|
||||
// First pass.
|
||||
// Get min/max (in most cases left / right) points
|
||||
@@ -237,98 +188,64 @@ public:
|
||||
// For symmetry and to get often more balanced lower/upper halves
|
||||
// we keep it.
|
||||
|
||||
typedef typename geometry::detail::range_type<InputGeometry>::type range_type;
|
||||
point_type most_left, most_right;
|
||||
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
range_type const
|
||||
>::type range_iterator;
|
||||
geometry::less_exact<point_type, -1, Strategy> less;
|
||||
|
||||
detail::get_extremes
|
||||
<
|
||||
range_type,
|
||||
range_iterator,
|
||||
geometry::less<point_type>,
|
||||
geometry::greater<point_type>
|
||||
> extremes;
|
||||
geometry::detail::for_each_range(geometry, extremes);
|
||||
detail::convex_hull::get_extremes(in_proxy, most_left, most_right, less);
|
||||
|
||||
container_type lower_points, upper_points;
|
||||
|
||||
auto const side_strategy = strategy.side();
|
||||
|
||||
// Bounding left/right points
|
||||
// Second pass, now that extremes are found, assign all points
|
||||
// in either lower, either upper
|
||||
detail::assign_range
|
||||
<
|
||||
range_type,
|
||||
range_iterator,
|
||||
container_type,
|
||||
typename strategy::side::services::default_strategy<cs_tag>::type
|
||||
> assigner(extremes.left, extremes.right);
|
||||
|
||||
geometry::detail::for_each_range(geometry, assigner);
|
||||
|
||||
detail::convex_hull::assign_ranges(in_proxy, most_left, most_right,
|
||||
lower_points, upper_points,
|
||||
side_strategy);
|
||||
|
||||
// Sort both collections, first on x(, then on y)
|
||||
detail::sort(assigner.lower_points);
|
||||
detail::sort(assigner.upper_points);
|
||||
|
||||
//std::cout << boost::size(assigner.lower_points) << std::endl;
|
||||
//std::cout << boost::size(assigner.upper_points) << std::endl;
|
||||
std::sort(boost::begin(lower_points), boost::end(lower_points), less);
|
||||
std::sort(boost::begin(upper_points), boost::end(upper_points), less);
|
||||
|
||||
// And decide which point should be in the final hull
|
||||
build_half_hull<-1>(assigner.lower_points, state.m_lower_hull,
|
||||
extremes.left, extremes.right);
|
||||
build_half_hull<1>(assigner.upper_points, state.m_upper_hull,
|
||||
extremes.left, extremes.right);
|
||||
build_half_hull<-1>(lower_points, state.m_lower_hull,
|
||||
most_left, most_right,
|
||||
side_strategy);
|
||||
build_half_hull<1>(upper_points, state.m_upper_hull,
|
||||
most_left, most_right,
|
||||
side_strategy);
|
||||
}
|
||||
|
||||
|
||||
template <typename OutputIterator>
|
||||
inline void result(partitions const& state,
|
||||
OutputIterator out,
|
||||
bool clockwise,
|
||||
bool closed) const
|
||||
{
|
||||
if (clockwise)
|
||||
{
|
||||
output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
template <int Factor>
|
||||
template <int Factor, typename SideStrategy>
|
||||
static inline void build_half_hull(container_type const& input,
|
||||
container_type& output,
|
||||
point_type const& left, point_type const& right)
|
||||
point_type const& left, point_type const& right,
|
||||
SideStrategy const& side)
|
||||
{
|
||||
output.push_back(left);
|
||||
for(iterator it = input.begin(); it != input.end(); ++it)
|
||||
for (auto const& i : input)
|
||||
{
|
||||
add_to_hull<Factor>(*it, output);
|
||||
add_to_hull<Factor>(i, output, side);
|
||||
}
|
||||
add_to_hull<Factor>(right, output);
|
||||
add_to_hull<Factor>(right, output, side);
|
||||
}
|
||||
|
||||
|
||||
template <int Factor>
|
||||
static inline void add_to_hull(point_type const& p, container_type& output)
|
||||
template <int Factor, typename SideStrategy>
|
||||
static inline void add_to_hull(point_type const& p, container_type& output,
|
||||
SideStrategy const& side)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy<cs_tag>::type side;
|
||||
|
||||
output.push_back(p);
|
||||
std::size_t output_size = output.size();
|
||||
while (output_size >= 3)
|
||||
{
|
||||
rev_iterator rit = output.rbegin();
|
||||
auto rit = output.rbegin();
|
||||
point_type const last = *rit++;
|
||||
point_type const& last2 = *rit++;
|
||||
|
||||
if (Factor * side::apply(*rit, last, last2) <= 0)
|
||||
if (Factor * side.apply(*rit, last, last2) <= 0)
|
||||
{
|
||||
// Remove last two points from stack, and add last again
|
||||
// This is much faster then erasing the one but last.
|
||||
@@ -346,8 +263,23 @@ private:
|
||||
|
||||
|
||||
template <typename OutputIterator>
|
||||
static inline void output_ranges(container_type const& first, container_type const& second,
|
||||
OutputIterator out, bool closed)
|
||||
static void result(partitions const& state, OutputIterator out, bool clockwise, bool closed)
|
||||
{
|
||||
if (clockwise)
|
||||
{
|
||||
output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
static inline void output_ranges(container_type const& first,
|
||||
container_type const& second,
|
||||
OutputIterator out,
|
||||
bool closed)
|
||||
{
|
||||
std::copy(boost::begin(first), boost::end(first), out);
|
||||
|
||||
@@ -369,18 +301,10 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace strategy::convex_hull
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
template <typename InputGeometry, typename OutputPoint>
|
||||
struct strategy_convex_hull<InputGeometry, OutputPoint, cartesian_tag>
|
||||
{
|
||||
typedef strategy::convex_hull::graham_andrew<InputGeometry, OutputPoint> type;
|
||||
};
|
||||
#endif
|
||||
}} // namespace detail::convex_hull
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP
|
||||
@@ -0,0 +1,617 @@
|
||||
// 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) 2023 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 Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/visit.hpp>
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/geometry_types.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/visit.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/geometries/ring.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/geometry/util/sequence.hpp>
|
||||
#include <boost/geometry/util/type_traits.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// TODO: This file is named interface.hpp but the code below is not the interface.
|
||||
// It's the implementation of the algorithm.
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace convex_hull
|
||||
{
|
||||
|
||||
// Abstraction representing ranges/rings of a geometry
|
||||
template <typename Geometry>
|
||||
struct input_geometry_proxy
|
||||
{
|
||||
input_geometry_proxy(Geometry const& geometry)
|
||||
: m_geometry(geometry)
|
||||
{}
|
||||
|
||||
template <typename UnaryFunction>
|
||||
inline void for_each_range(UnaryFunction fun) const
|
||||
{
|
||||
geometry::detail::for_each_range(m_geometry, fun);
|
||||
}
|
||||
|
||||
Geometry const& m_geometry;
|
||||
};
|
||||
|
||||
// Abstraction representing ranges/rings of subgeometries of geometry collection
|
||||
// with boxes converted to rings
|
||||
template <typename Geometry, typename BoxRings>
|
||||
struct input_geometry_collection_proxy
|
||||
{
|
||||
input_geometry_collection_proxy(Geometry const& geometry, BoxRings const& box_rings)
|
||||
: m_geometry(geometry)
|
||||
, m_box_rings(box_rings)
|
||||
{}
|
||||
|
||||
template <typename UnaryFunction>
|
||||
inline void for_each_range(UnaryFunction fun) const
|
||||
{
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
input_geometry_collection_proxy::call_for_non_boxes(g, fun);
|
||||
return true;
|
||||
}, m_geometry);
|
||||
|
||||
for (auto const& r : m_box_rings)
|
||||
{
|
||||
geometry::detail::for_each_range(r, fun);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename G, typename F, std::enable_if_t<! util::is_box<G>::value, int> = 0>
|
||||
static inline void call_for_non_boxes(G const& g, F & f)
|
||||
{
|
||||
geometry::detail::for_each_range(g, f);
|
||||
}
|
||||
template <typename G, typename F, std::enable_if_t<util::is_box<G>::value, int> = 0>
|
||||
static inline void call_for_non_boxes(G const&, F &)
|
||||
{}
|
||||
|
||||
Geometry const& m_geometry;
|
||||
BoxRings const& m_box_rings;
|
||||
};
|
||||
|
||||
|
||||
// TODO: Or just implement point_type<> for GeometryCollection
|
||||
// and enforce the same point_type used in the whole sequence in check().
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct default_strategy
|
||||
{
|
||||
using type = typename strategies::convex_hull::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct default_strategy<Geometry, geometry_collection_tag>
|
||||
: default_strategy<typename detail::first_geometry_type<Geometry>::type>
|
||||
{};
|
||||
|
||||
|
||||
// Utilities for output GC and DG
|
||||
template <typename G1, typename G2>
|
||||
struct output_polygonal_less
|
||||
{
|
||||
template <typename G>
|
||||
using priority = std::integral_constant
|
||||
<
|
||||
int,
|
||||
(util::is_ring<G>::value ? 0 :
|
||||
util::is_polygon<G>::value ? 1 :
|
||||
util::is_multi_polygon<G>::value ? 2 : 3)
|
||||
>;
|
||||
|
||||
static const bool value = priority<G1>::value < priority<G2>::value;
|
||||
};
|
||||
|
||||
template <typename G1, typename G2>
|
||||
struct output_linear_less
|
||||
{
|
||||
template <typename G>
|
||||
using priority = std::integral_constant
|
||||
<
|
||||
int,
|
||||
(util::is_segment<G>::value ? 0 :
|
||||
util::is_linestring<G>::value ? 1 :
|
||||
util::is_multi_linestring<G>::value ? 2 : 3)
|
||||
>;
|
||||
|
||||
static const bool value = priority<G1>::value < priority<G2>::value;
|
||||
};
|
||||
|
||||
template <typename G1, typename G2>
|
||||
struct output_pointlike_less
|
||||
{
|
||||
template <typename G>
|
||||
using priority = std::integral_constant
|
||||
<
|
||||
int,
|
||||
(util::is_point<G>::value ? 0 :
|
||||
util::is_multi_point<G>::value ? 1 : 2)
|
||||
>;
|
||||
|
||||
static const bool value = priority<G1>::value < priority<G2>::value;
|
||||
};
|
||||
|
||||
|
||||
}} // 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
|
||||
{
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
detail::convex_hull::input_geometry_proxy<Geometry> in_proxy(geometry);
|
||||
detail::convex_hull::graham_andrew
|
||||
<
|
||||
typename point_type<Geometry>::type
|
||||
>::apply(in_proxy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// A hull for boxes is trivial. Any strategy is (currently) skipped.
|
||||
// TODO: This is not correct in spherical and geographic CS.
|
||||
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;
|
||||
|
||||
std::array<typename point_type<OutputGeometry>::type, 4> arr;
|
||||
// TODO: This assigns only 2d cooridnates!
|
||||
// And it is also used in box_view<>!
|
||||
geometry::detail::assign_box_corners_oriented<Reverse>(box, arr);
|
||||
|
||||
std::move(arr.begin(), arr.end(), range::back_inserter(out));
|
||||
if (BOOST_GEOMETRY_CONDITION(Close))
|
||||
{
|
||||
range::push_back(out, range::front(out));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename GeometryCollection>
|
||||
struct convex_hull<GeometryCollection, geometry_collection_tag>
|
||||
{
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(GeometryCollection const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// Assuming that single point_type is used by the GeometryCollection
|
||||
using subgeometry_type = typename detail::first_geometry_type<GeometryCollection>::type;
|
||||
using point_type = typename geometry::point_type<subgeometry_type>::type;
|
||||
using ring_type = model::ring<point_type, true, false>;
|
||||
|
||||
// Calculate box rings once
|
||||
std::vector<ring_type> box_rings;
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
convex_hull::add_ring_for_box(box_rings, g, strategy);
|
||||
return true;
|
||||
}, geometry);
|
||||
|
||||
detail::convex_hull::input_geometry_collection_proxy
|
||||
<
|
||||
GeometryCollection, std::vector<ring_type>
|
||||
> in_proxy(geometry, box_rings);
|
||||
|
||||
detail::convex_hull::graham_andrew
|
||||
<
|
||||
point_type
|
||||
>::apply(in_proxy, out, strategy);
|
||||
}
|
||||
|
||||
private:
|
||||
template
|
||||
<
|
||||
typename Ring, typename SubGeometry, typename Strategy,
|
||||
std::enable_if_t<util::is_box<SubGeometry>::value, int> = 0
|
||||
>
|
||||
static inline void add_ring_for_box(std::vector<Ring> & rings, SubGeometry const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
Ring ring;
|
||||
convex_hull<SubGeometry>::apply(box, ring, strategy);
|
||||
rings.push_back(std::move(ring));
|
||||
}
|
||||
template
|
||||
<
|
||||
typename Ring, typename SubGeometry, typename Strategy,
|
||||
std::enable_if_t<! util::is_box<SubGeometry>::value, int> = 0
|
||||
>
|
||||
static inline void add_ring_for_box(std::vector<Ring> & , SubGeometry const& ,
|
||||
Strategy const& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename OutputGeometry, typename Tag = typename tag<OutputGeometry>::type>
|
||||
struct convex_hull_out
|
||||
{
|
||||
BOOST_GEOMETRY_STATIC_ASSERT_FALSE("This OutputGeometry is not supported.", OutputGeometry, Tag);
|
||||
};
|
||||
|
||||
template <typename OutputGeometry>
|
||||
struct convex_hull_out<OutputGeometry, ring_tag>
|
||||
{
|
||||
template <typename Geometry, typename Strategies>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
dispatch::convex_hull<Geometry>::apply(geometry, out, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputGeometry>
|
||||
struct convex_hull_out<OutputGeometry, polygon_tag>
|
||||
{
|
||||
template <typename Geometry, typename Strategies>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
auto&& ring = exterior_ring(out);
|
||||
dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputGeometry>
|
||||
struct convex_hull_out<OutputGeometry, multi_polygon_tag>
|
||||
{
|
||||
template <typename Geometry, typename Strategies>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typename boost::range_value<OutputGeometry>::type polygon;
|
||||
auto&& ring = exterior_ring(polygon);
|
||||
dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
|
||||
// Empty input is checked so the output shouldn't be empty
|
||||
range::push_back(out, std::move(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputGeometry>
|
||||
struct convex_hull_out<OutputGeometry, geometry_collection_tag>
|
||||
{
|
||||
using polygonal_t = typename util::sequence_min_element
|
||||
<
|
||||
typename traits::geometry_types<OutputGeometry>::type,
|
||||
detail::convex_hull::output_polygonal_less
|
||||
>::type;
|
||||
using linear_t = typename util::sequence_min_element
|
||||
<
|
||||
typename traits::geometry_types<OutputGeometry>::type,
|
||||
detail::convex_hull::output_linear_less
|
||||
>::type;
|
||||
using pointlike_t = typename util::sequence_min_element
|
||||
<
|
||||
typename traits::geometry_types<OutputGeometry>::type,
|
||||
detail::convex_hull::output_pointlike_less
|
||||
>::type;
|
||||
|
||||
// select_element may define different kind of geometry than the one that is desired
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(util::is_polygonal<polygonal_t>::value,
|
||||
"It must be possible to store polygonal geometry in OutputGeometry.", polygonal_t);
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(util::is_linear<linear_t>::value,
|
||||
"It must be possible to store linear geometry in OutputGeometry.", linear_t);
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(util::is_pointlike<pointlike_t>::value,
|
||||
"It must be possible to store pointlike geometry in OutputGeometry.", pointlike_t);
|
||||
|
||||
template <typename Geometry, typename Strategies>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
polygonal_t polygonal;
|
||||
convex_hull_out<polygonal_t>::apply(geometry, polygonal, strategies);
|
||||
// Empty input is checked so the output shouldn't be empty
|
||||
auto&& out_ring = ring(polygonal);
|
||||
|
||||
if (boost::size(out_ring) == detail::minimum_ring_size<polygonal_t>::value)
|
||||
{
|
||||
using detail::equals::equals_point_point;
|
||||
if (equals_point_point(range::front(out_ring), range::at(out_ring, 1), strategies))
|
||||
{
|
||||
pointlike_t pointlike;
|
||||
move_to_pointlike(out_ring, pointlike);
|
||||
move_to_out(pointlike, out);
|
||||
return;
|
||||
}
|
||||
if (equals_point_point(range::front(out_ring), range::at(out_ring, 2), strategies))
|
||||
{
|
||||
linear_t linear;
|
||||
move_to_linear(out_ring, linear);
|
||||
move_to_out(linear, out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
move_to_out(polygonal, out);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Polygonal, util::enable_if_ring_t<Polygonal, int> = 0>
|
||||
static decltype(auto) ring(Polygonal const& polygonal)
|
||||
{
|
||||
return polygonal;
|
||||
}
|
||||
template <typename Polygonal, util::enable_if_polygon_t<Polygonal, int> = 0>
|
||||
static decltype(auto) ring(Polygonal const& polygonal)
|
||||
{
|
||||
return exterior_ring(polygonal);
|
||||
}
|
||||
template <typename Polygonal, util::enable_if_multi_polygon_t<Polygonal, int> = 0>
|
||||
static decltype(auto) ring(Polygonal const& polygonal)
|
||||
{
|
||||
return exterior_ring(range::front(polygonal));
|
||||
}
|
||||
|
||||
template <typename Range, typename Linear, util::enable_if_segment_t<Linear, int> = 0>
|
||||
static void move_to_linear(Range & out_range, Linear & seg)
|
||||
{
|
||||
detail::assign_point_to_index<0>(range::front(out_range), seg);
|
||||
detail::assign_point_to_index<1>(range::at(out_range, 1), seg);
|
||||
}
|
||||
template <typename Range, typename Linear, util::enable_if_linestring_t<Linear, int> = 0>
|
||||
static void move_to_linear(Range & out_range, Linear & ls)
|
||||
{
|
||||
std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
|
||||
}
|
||||
template <typename Range, typename Linear, util::enable_if_multi_linestring_t<Linear, int> = 0>
|
||||
static void move_to_linear(Range & out_range, Linear & mls)
|
||||
{
|
||||
typename boost::range_value<Linear>::type ls;
|
||||
std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
|
||||
range::push_back(mls, std::move(ls));
|
||||
}
|
||||
|
||||
template <typename Range, typename PointLike, util::enable_if_point_t<PointLike, int> = 0>
|
||||
static void move_to_pointlike(Range & out_range, PointLike & pt)
|
||||
{
|
||||
pt = range::front(out_range);
|
||||
}
|
||||
template <typename Range, typename PointLike, util::enable_if_multi_point_t<PointLike, int> = 0>
|
||||
static void move_to_pointlike(Range & out_range, PointLike & mpt)
|
||||
{
|
||||
range::push_back(mpt, std::move(range::front(out_range)));
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry, typename OutputGeometry_,
|
||||
util::enable_if_geometry_collection_t<OutputGeometry_, int> = 0
|
||||
>
|
||||
static void move_to_out(Geometry & g, OutputGeometry_ & out)
|
||||
{
|
||||
range::emplace_back(out, std::move(g));
|
||||
}
|
||||
template
|
||||
<
|
||||
typename Geometry, typename OutputGeometry_,
|
||||
util::enable_if_dynamic_geometry_t<OutputGeometry_, int> = 0
|
||||
>
|
||||
static void move_to_out(Geometry & g, OutputGeometry_ & out)
|
||||
{
|
||||
out = std::move(g);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputGeometry>
|
||||
struct convex_hull_out<OutputGeometry, dynamic_geometry_tag>
|
||||
: convex_hull_out<OutputGeometry, geometry_collection_tag>
|
||||
{};
|
||||
|
||||
|
||||
// For backward compatibility
|
||||
template <typename OutputGeometry>
|
||||
struct convex_hull_out<OutputGeometry, linestring_tag>
|
||||
: convex_hull_out<OutputGeometry, ring_tag>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
template <typename Strategies>
|
||||
struct convex_hull
|
||||
{
|
||||
template <typename Geometry, typename OutputGeometry>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convex_hull<default_strategy>
|
||||
{
|
||||
template <typename Geometry, typename OutputGeometry>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
default_strategy const&)
|
||||
{
|
||||
using strategy_type = typename detail::convex_hull::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type;
|
||||
|
||||
dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic {
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
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<Strategy>::apply(geometry, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct convex_hull<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename OutputGeometry, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
OutputGeometry& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
convex_hull<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{convex hull} \brief_strategy
|
||||
\ingroup convex_hull
|
||||
\details \details_calc{convex_hull,convex hull} \brief_strategy.
|
||||
\tparam Geometry the input geometry type
|
||||
\tparam OutputGeometry the output geometry type
|
||||
\tparam Strategy the strategy type
|
||||
\param geometry \param_geometry, input geometry
|
||||
\param out \param_geometry \param_set{convex hull}
|
||||
\param strategy \param_strategy{area}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{[include reference/algorithms/convex_hull.qbk]}
|
||||
*/
|
||||
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_dynamic::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());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
|
||||
@@ -5,10 +5,10 @@
|
||||
// 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.
|
||||
|
||||
// This file was modified by Oracle on 2014-2020.
|
||||
// Modifications copyright (c) 2014-2020, 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.
|
||||
@@ -22,15 +22,14 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.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
|
||||
{
|
||||
@@ -66,10 +65,8 @@ struct polygon_count
|
||||
{
|
||||
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)
|
||||
auto const& rings = interior_rings(poly);
|
||||
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
n += RangeCount::apply(*it);
|
||||
}
|
||||
@@ -83,13 +80,10 @@ template <typename SingleCount>
|
||||
struct multi_count
|
||||
{
|
||||
template <typename MultiGeometry>
|
||||
static inline std::size_t apply(MultiGeometry const& geometry)
|
||||
static inline std::size_t apply(MultiGeometry const& multi)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for (typename boost::range_iterator<MultiGeometry const>::type
|
||||
it = boost::begin(geometry);
|
||||
it != boost::end(geometry);
|
||||
++it)
|
||||
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
|
||||
{
|
||||
n += SingleCount::apply(*it);
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// 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
|
||||
@@ -4,9 +4,10 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2017, 2019.
|
||||
// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2022.
|
||||
// Modifications copyright (c) 2013-2022 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -23,6 +24,9 @@
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/implementation.hpp>
|
||||
#include <boost/geometry/strategies/relate/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/relate/geographic.hpp>
|
||||
#include <boost/geometry/strategies/relate/spherical.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -34,7 +38,8 @@ 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)
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::within::covered_by_point_geometry(geometry1, geometry2, strategy);
|
||||
}
|
||||
@@ -43,13 +48,32 @@ struct use_point_in_geometry
|
||||
struct use_relate
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename detail::de9im::static_mask_covered_by_type
|
||||
return detail::relate::relate_impl
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type covered_by_mask;
|
||||
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
|
||||
detail::de9im::static_mask_covered_by_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
struct geometry_covered_by_box
|
||||
{
|
||||
template <typename Geometry, typename Box, typename Strategy>
|
||||
static inline bool apply(Geometry const& geometry, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
using point_type = typename point_type<Geometry>::type;
|
||||
using mutable_point_type = typename helper_geometry<point_type>::type;
|
||||
using box_type = model::box<mutable_point_type>;
|
||||
|
||||
// TODO: this is not optimal since the process should be able to terminate if a point is found
|
||||
// outside of the box without computing the whole envelope
|
||||
box_type box_areal;
|
||||
geometry::envelope(geometry, box_areal, strategy);
|
||||
return strategy.covered_by(box_areal, box).apply(box_areal, box);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,30 +84,6 @@ struct use_relate
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Point, typename Box>
|
||||
struct covered_by<Point, Box, point_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
::boost::ignore_unused(strategy);
|
||||
return strategy.apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct covered_by<Box1, Box2, box_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
::boost::ignore_unused(strategy);
|
||||
return strategy.apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// P/P
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
@@ -271,6 +271,76 @@ struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// B/A
|
||||
|
||||
template <typename Box, typename Polygon>
|
||||
struct covered_by<Box, Polygon, box_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Box, typename Polygon>
|
||||
struct covered_by<Box, Polygon, box_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Box, typename Polygon>
|
||||
struct covered_by<Box, Polygon, box_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// Geometry/Box
|
||||
|
||||
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)
|
||||
{
|
||||
return strategy.covered_by(point, box).apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MultiPoint, typename Box>
|
||||
struct covered_by<MultiPoint, Box, multi_point_tag, box_tag>
|
||||
: public detail::covered_by::geometry_covered_by_box
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename Box>
|
||||
struct covered_by<Linestring, Box, linestring_tag, box_tag>
|
||||
: public detail::covered_by::geometry_covered_by_box
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Box>
|
||||
struct covered_by<MultiLinestring, Box, multi_linestring_tag, box_tag>
|
||||
: public detail::covered_by::geometry_covered_by_box
|
||||
{};
|
||||
|
||||
template <typename Ring, typename Box>
|
||||
struct covered_by<Ring, Box, ring_tag, box_tag>
|
||||
: public detail::covered_by::geometry_covered_by_box
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Box>
|
||||
struct covered_by<Polygon, Box, polygon_tag, box_tag>
|
||||
: public detail::covered_by::geometry_covered_by_box
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Box>
|
||||
struct covered_by<MultiPolygon, Box, multi_polygon_tag, box_tag>
|
||||
: public detail::covered_by::geometry_covered_by_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>();
|
||||
return strategy.covered_by(box1, box2).apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2022 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_COVERED_BY_IMPLEMENTATION_GC_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct covered_by<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
|
||||
: detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1>
|
||||
struct covered_by<Geometry1, Geometry2, Tag1, geometry_collection_tag>
|
||||
: detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag2>
|
||||
struct covered_by<Geometry1, Geometry2, geometry_collection_tag, Tag2>
|
||||
: detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
|
||||
@@ -4,9 +4,8 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021 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
|
||||
@@ -20,16 +19,12 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/within/interface.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/relate/services.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -56,9 +51,14 @@ struct covered_by
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
@@ -68,32 +68,63 @@ struct covered_by
|
||||
concepts::check<Geometry2 const>();
|
||||
assert_dimension_equal<Geometry1, Geometry2>();
|
||||
|
||||
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
|
||||
geometry2,
|
||||
strategy);
|
||||
return dispatch::covered_by
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct covered_by<Strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using strategies::relate::services::strategy_converter;
|
||||
|
||||
return covered_by
|
||||
<
|
||||
decltype(strategy_converter<Strategy>::get(strategy))
|
||||
>::apply(geometry1, geometry2,
|
||||
strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct covered_by<default_strategy, false>
|
||||
{
|
||||
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
|
||||
typedef typename strategies::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return covered_by::apply(geometry1, geometry2, strategy_type());
|
||||
return covered_by
|
||||
<
|
||||
strategy_type
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_dynamic {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type
|
||||
>
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Strategy>
|
||||
@@ -102,106 +133,73 @@ struct covered_by
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::covered_by
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
<
|
||||
Strategy
|
||||
>::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 Geometry1, typename Geometry2, typename Tag2>
|
||||
struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
bool result = false;
|
||||
traits::visit<Geometry1>::apply([&](auto const& g1)
|
||||
{
|
||||
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);
|
||||
result = resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, geometry2, strategy);
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1>
|
||||
struct covered_by<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
bool result = false;
|
||||
traits::visit<Geometry2>::apply([&](auto const& g2)
|
||||
{
|
||||
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);
|
||||
result = resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, g2, strategy);
|
||||
}, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
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 Geometry1, typename Geometry2>
|
||||
struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
bool result = false;
|
||||
traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
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);
|
||||
result = resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -217,13 +215,19 @@ struct covered_by<
|
||||
\note The default strategy is used for covered_by detection
|
||||
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Examples]
|
||||
[covered_by]
|
||||
[covered_by_output]
|
||||
}
|
||||
*/
|
||||
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());
|
||||
return resolve_dynamic::covered_by
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -246,8 +250,10 @@ 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);
|
||||
return resolve_dynamic::covered_by
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2015-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2017.
|
||||
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2020.
|
||||
// Modifications copyright (c) 2015-2020 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
|
||||
@@ -12,17 +12,20 @@
|
||||
// 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
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/static_assert.hpp>
|
||||
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
|
||||
#include <boost/geometry/algorithms/detail/make/make.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -32,108 +35,111 @@ namespace boost { namespace geometry
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
// TODO: remove
|
||||
template <std::size_t Index, typename Point1, typename Point2>
|
||||
inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return
|
||||
math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))
|
||||
?
|
||||
0
|
||||
:
|
||||
(geometry::get<Index>(point1) > geometry::get<Index>(point2) ? 1 : -1);
|
||||
}
|
||||
|
||||
|
||||
template <typename Point, typename CSTag = typename cs_tag<Point>::type>
|
||||
template <typename CSTag>
|
||||
struct direction_code_impl
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag));
|
||||
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
|
||||
"Not implemented for this coordinate system.",
|
||||
CSTag);
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, cartesian_tag>
|
||||
template <>
|
||||
struct direction_code_impl<cartesian_tag>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
|
||||
Point2 const& p)
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
|
||||
Point2 const& point)
|
||||
{
|
||||
typedef typename geometry::select_coordinate_type
|
||||
using calc_t = typename geometry::select_coordinate_type
|
||||
<
|
||||
Point1, Point2
|
||||
>::type calc_t;
|
||||
PointSegmentA, PointSegmentB, Point2
|
||||
>::type;
|
||||
|
||||
if ( (math::equals(geometry::get<0>(segment_b), geometry::get<0>(segment_a))
|
||||
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(segment_a)))
|
||||
|| (math::equals(geometry::get<0>(segment_b), geometry::get<0>(p))
|
||||
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(p))) )
|
||||
using line_type = model::infinite_line<calc_t>;
|
||||
|
||||
// Situation and construction of perpendicular line
|
||||
//
|
||||
// P1 a--------------->b P2
|
||||
// |
|
||||
// |
|
||||
// v
|
||||
//
|
||||
// P1 is located right of the (directional) perpendicular line
|
||||
// and therefore gets a negative side_value, and returns -1.
|
||||
// P2 is to the left of the perpendicular line and returns 1.
|
||||
// If the specified point is located on top of b, it returns 0.
|
||||
|
||||
line_type const line
|
||||
= detail::make::make_perpendicular_line<calc_t>(segment_a,
|
||||
segment_b, segment_b);
|
||||
|
||||
if (arithmetic::is_degenerate(line))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
calc_t x1 = geometry::get<0>(segment_b) - geometry::get<0>(segment_a);
|
||||
calc_t y1 = geometry::get<1>(segment_b) - geometry::get<1>(segment_a);
|
||||
calc_t x2 = geometry::get<0>(segment_b) - geometry::get<0>(p);
|
||||
calc_t y2 = geometry::get<1>(segment_b) - geometry::get<1>(p);
|
||||
|
||||
calc_t ax = (std::min)(math::abs(x1), math::abs(x2));
|
||||
calc_t ay = (std::min)(math::abs(y1), math::abs(y2));
|
||||
|
||||
int s1 = 0, s2 = 0;
|
||||
if (ax >= ay)
|
||||
{
|
||||
s1 = x1 > 0 ? 1 : -1;
|
||||
s2 = x2 > 0 ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = y1 > 0 ? 1 : -1;
|
||||
s2 = y2 > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return s1 == s2 ? -1 : 1;
|
||||
calc_t const sv = arithmetic::side_value(line, point);
|
||||
static calc_t const zero = 0;
|
||||
return sv == zero ? 0 : sv > zero ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, spherical_equatorial_tag>
|
||||
template <>
|
||||
struct direction_code_impl<spherical_equatorial_tag>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
|
||||
Point2 const& p)
|
||||
{
|
||||
typedef typename coordinate_type<Point1>::type coord1_t;
|
||||
typedef typename coordinate_type<Point2>::type coord2_t;
|
||||
typedef typename coordinate_system<Point1>::type::units units_t;
|
||||
typedef typename coordinate_system<Point2>::type::units units2_t;
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<units_t, units2_t>::value),
|
||||
NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS,
|
||||
(units_t, units2_t));
|
||||
{
|
||||
using units_sa_t = typename cs_angular_units<PointSegmentA>::type;
|
||||
using units_sb_t = typename cs_angular_units<PointSegmentB>::type;
|
||||
using units_p_t = typename cs_angular_units<Point2>::type;
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(
|
||||
(std::is_same<units_sa_t, units_sb_t>::value),
|
||||
"Not implemented for different units.",
|
||||
units_sa_t, units_sb_t);
|
||||
BOOST_GEOMETRY_STATIC_ASSERT(
|
||||
(std::is_same<units_sa_t, units_p_t>::value),
|
||||
"Not implemented for different units.",
|
||||
units_sa_t, units_p_t);
|
||||
}
|
||||
|
||||
typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
|
||||
typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
|
||||
typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
|
||||
static coord1_t const pi_half1 = constants1::max_latitude();
|
||||
static coord2_t const pi_half2 = constants2::max_latitude();
|
||||
using coor_sa_t = typename coordinate_type<PointSegmentA>::type;
|
||||
using coor_sb_t = typename coordinate_type<PointSegmentB>::type;
|
||||
using coor_p_t = typename coordinate_type<Point2>::type;
|
||||
|
||||
// Declare unit type (equal for all types) and calc type (coerced to most precise)
|
||||
using units_t = typename cs_angular_units<Point2>::type;
|
||||
using calc_t = typename geometry::select_coordinate_type
|
||||
<
|
||||
PointSegmentA, PointSegmentB, Point2
|
||||
>::type;
|
||||
using constants_sa_t = math::detail::constants_on_spheroid<coor_sa_t, units_t>;
|
||||
using constants_sb_t = math::detail::constants_on_spheroid<coor_sb_t, units_t>;
|
||||
using constants_p_t = math::detail::constants_on_spheroid<coor_p_t, units_t>;
|
||||
|
||||
static coor_sa_t const pi_half_sa = constants_sa_t::max_latitude();
|
||||
static coor_sb_t const pi_half_sb = constants_sb_t::max_latitude();
|
||||
static coor_p_t const pi_half_p = constants_p_t::max_latitude();
|
||||
static calc_t const c0 = 0;
|
||||
|
||||
coord1_t const a0 = geometry::get<0>(segment_a);
|
||||
coord1_t const a1 = geometry::get<1>(segment_a);
|
||||
coord1_t const b0 = geometry::get<0>(segment_b);
|
||||
coord1_t const b1 = geometry::get<1>(segment_b);
|
||||
coord2_t const p0 = geometry::get<0>(p);
|
||||
coord2_t const p1 = geometry::get<1>(p);
|
||||
|
||||
coor_sa_t const a0 = geometry::get<0>(segment_a);
|
||||
coor_sa_t const a1 = geometry::get<1>(segment_a);
|
||||
coor_sb_t const b0 = geometry::get<0>(segment_b);
|
||||
coor_sb_t const b1 = geometry::get<1>(segment_b);
|
||||
coor_p_t const p0 = geometry::get<0>(p);
|
||||
coor_p_t const p1 = geometry::get<1>(p);
|
||||
|
||||
if ( (math::equals(b0, a0) && math::equals(b1, a1))
|
||||
|| (math::equals(b0, p0) && math::equals(b1, p1)) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
|
||||
bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
|
||||
bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
|
||||
bool const is_a_pole = math::equals(pi_half_sa, math::abs(a1));
|
||||
bool const is_b_pole = math::equals(pi_half_sb, math::abs(b1));
|
||||
bool const is_p_pole = math::equals(pi_half_p, math::abs(p1));
|
||||
|
||||
if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
|
||||
|| (is_p_pole && math::sign(b1) == math::sign(p1))) )
|
||||
@@ -151,12 +157,12 @@ struct direction_code_impl<Point, spherical_equatorial_tag>
|
||||
calc_t const dlat1 = latitude_distance_signed<units_t, calc_t>(b1, a1, dlon1, is_antilon1);
|
||||
calc_t const dlat2 = latitude_distance_signed<units_t, calc_t>(b1, p1, dlon2, is_antilon2);
|
||||
|
||||
calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
|
||||
c0 :
|
||||
(std::min)(is_antilon1 ? c0 : math::abs(dlon1),
|
||||
is_antilon2 ? c0 : math::abs(dlon2));
|
||||
calc_t my = (std::min)(math::abs(dlat1),
|
||||
math::abs(dlat2));
|
||||
calc_t const mx = is_a_pole || is_b_pole || is_p_pole
|
||||
? c0
|
||||
: (std::min)(is_antilon1 ? c0 : math::abs(dlon1),
|
||||
is_antilon2 ? c0 : math::abs(dlon2));
|
||||
calc_t const my = (std::min)(math::abs(dlat1),
|
||||
math::abs(dlat2));
|
||||
|
||||
int s1 = 0, s2 = 0;
|
||||
if (mx >= my)
|
||||
@@ -176,7 +182,7 @@ struct direction_code_impl<Point, spherical_equatorial_tag>
|
||||
template <typename Units, typename T>
|
||||
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid<T, Units> constants;
|
||||
using constants = math::detail::constants_on_spheroid<T, Units>;
|
||||
static T const pi = constants::half_period();
|
||||
static T const c0 = 0;
|
||||
|
||||
@@ -196,41 +202,66 @@ struct direction_code_impl<Point, spherical_equatorial_tag>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, spherical_polar_tag>
|
||||
template <>
|
||||
struct direction_code_impl<spherical_polar_tag>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline int apply(Point1 segment_a, Point1 segment_b,
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
|
||||
Point2 p)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
using constants_sa_t = math::detail::constants_on_spheroid
|
||||
<
|
||||
typename coordinate_type<Point1>::type,
|
||||
typename coordinate_system<Point1>::type::units
|
||||
> constants1;
|
||||
typedef math::detail::constants_on_spheroid
|
||||
typename coordinate_type<PointSegmentA>::type,
|
||||
typename cs_angular_units<PointSegmentA>::type
|
||||
>;
|
||||
using constants_p_t = math::detail::constants_on_spheroid
|
||||
<
|
||||
typename coordinate_type<Point2>::type,
|
||||
typename coordinate_system<Point2>::type::units
|
||||
> constants2;
|
||||
typename cs_angular_units<Point2>::type
|
||||
>;
|
||||
|
||||
geometry::set<1>(segment_a,
|
||||
constants1::max_latitude() - geometry::get<1>(segment_a));
|
||||
constants_sa_t::max_latitude() - geometry::get<1>(segment_a));
|
||||
geometry::set<1>(segment_b,
|
||||
constants1::max_latitude() - geometry::get<1>(segment_b));
|
||||
constants_sa_t::max_latitude() - geometry::get<1>(segment_b));
|
||||
geometry::set<1>(p,
|
||||
constants2::max_latitude() - geometry::get<1>(p));
|
||||
constants_p_t::max_latitude() - geometry::get<1>(p));
|
||||
|
||||
return direction_code_impl
|
||||
<
|
||||
Point, spherical_equatorial_tag
|
||||
spherical_equatorial_tag
|
||||
>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, geographic_tag>
|
||||
: direction_code_impl<Point, spherical_equatorial_tag>
|
||||
// if spherical_tag is passed then pick cs_tag based on PointSegmentA type
|
||||
// with spherical_equatorial_tag as the default
|
||||
template <>
|
||||
struct direction_code_impl<spherical_tag>
|
||||
{
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
|
||||
Point2 p)
|
||||
{
|
||||
return direction_code_impl
|
||||
<
|
||||
std::conditional_t
|
||||
<
|
||||
std::is_same
|
||||
<
|
||||
typename geometry::cs_tag<PointSegmentA>::type,
|
||||
spherical_polar_tag
|
||||
>::value,
|
||||
spherical_polar_tag,
|
||||
spherical_equatorial_tag
|
||||
>
|
||||
>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct direction_code_impl<geographic_tag>
|
||||
: direction_code_impl<spherical_equatorial_tag>
|
||||
{};
|
||||
|
||||
// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
|
||||
@@ -238,11 +269,13 @@ struct direction_code_impl<Point, geographic_tag>
|
||||
// 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,
|
||||
// In some cases the "segment" consists of different source points, and therefore
|
||||
// their types might differ.
|
||||
template <typename CSTag, typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
inline int direction_code(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
|
||||
Point2 const& p)
|
||||
{
|
||||
return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
|
||||
return direction_code_impl<CSTag>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
|
||||
|
||||
@@ -252,4 +285,4 @@ inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2019.
|
||||
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2022.
|
||||
// Modifications copyright (c) 2013-2022, 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
|
||||
@@ -23,14 +23,16 @@
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
|
||||
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/for_each.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -46,51 +48,25 @@ inline bool point_on_border_covered_by(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename geometry::point_type<Geometry1>::type pt;
|
||||
using point_type = typename geometry::point_type<Geometry1>::type;
|
||||
typename helper_geometry<point_type>::type pt;
|
||||
return geometry::point_on_border(pt, geometry1)
|
||||
&& geometry::covered_by(pt, geometry2, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template<typename Geometry, typename Strategy>
|
||||
struct check_each_ring_for_within
|
||||
{
|
||||
bool not_disjoint;
|
||||
Geometry const& m_geometry;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
inline check_each_ring_for_within(Geometry const& g,
|
||||
Strategy const& strategy)
|
||||
: not_disjoint(false)
|
||||
, m_geometry(g)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Range>
|
||||
inline void apply(Range const& range)
|
||||
{
|
||||
not_disjoint = not_disjoint
|
||||
|| point_on_border_covered_by(range, m_geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
|
||||
inline bool rings_containing(FirstGeometry const& geometry1,
|
||||
SecondGeometry const& geometry2,
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool rings_containing(Geometry1 const& geometry1,
|
||||
Geometry2 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;
|
||||
return geometry::detail::any_range_of(geometry2, [&](auto const& range)
|
||||
{
|
||||
return point_on_border_covered_by(range, geometry1, strategy);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -117,10 +93,8 @@ struct areal_areal
|
||||
// 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>()) )
|
||||
if ( rings_containing(geometry1, geometry2, strategy)
|
||||
|| rings_containing(geometry2, geometry1, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -141,10 +115,10 @@ struct areal_box
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( ! for_each_segment(geometry::segments_begin(areal),
|
||||
geometry::segments_end(areal),
|
||||
box,
|
||||
strategy.get_disjoint_segment_box_strategy()) )
|
||||
if (! geometry::all_segments_of(areal, [&](auto const& s)
|
||||
{
|
||||
return disjoint_segment_box::apply(s, box, strategy);
|
||||
}) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -152,31 +126,13 @@ struct areal_box
|
||||
// If there is no intersection of any segment and box,
|
||||
// the box might be located inside areal geometry
|
||||
|
||||
if ( point_on_border_covered_by(box, areal,
|
||||
strategy.template get_point_in_geometry_strategy<Box, Areal>()) )
|
||||
if ( point_on_border_covered_by(box, areal, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename SegIter, typename Strategy>
|
||||
static inline bool for_each_segment(SegIter first,
|
||||
SegIter last,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
for ( ; first != last ; ++first)
|
||||
{
|
||||
if (! disjoint_segment_box::apply(*first, box, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021, 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
|
||||
|
||||
@@ -25,9 +24,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -43,8 +40,23 @@ namespace detail { namespace disjoint
|
||||
\note Is used from other algorithms, declared separately
|
||||
to avoid circular references
|
||||
*/
|
||||
template <typename Box1, typename Box2, typename Strategy>
|
||||
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2, typename Strategy,
|
||||
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
|
||||
>
|
||||
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
typedef decltype(strategy.disjoint(box1, box2)) strategy_type;
|
||||
return strategy_type::apply(box1, box2);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2, typename Strategy,
|
||||
std::enable_if_t<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
|
||||
>
|
||||
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const& )
|
||||
{
|
||||
return Strategy::apply(box1, box2);
|
||||
}
|
||||
@@ -63,9 +75,10 @@ template <typename Box1, typename Box2, std::size_t DimensionCount>
|
||||
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
return Strategy::apply(box1, box2);
|
||||
typedef decltype(strategy.disjoint(box1, box2)) strategy_type;
|
||||
return strategy_type::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021, 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
|
||||
@@ -33,5 +33,9 @@
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/relate/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/relate/geographic.hpp>
|
||||
#include <boost/geometry/strategies/relate/spherical.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021, 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
|
||||
@@ -23,16 +23,16 @@
|
||||
|
||||
#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/detail/visit.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/relate/services.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -41,9 +41,14 @@ namespace boost { namespace geometry
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct disjoint
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
@@ -53,13 +58,35 @@ struct disjoint
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct disjoint<Strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using strategies::relate::services::strategy_converter;
|
||||
|
||||
return dispatch::disjoint
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2,
|
||||
strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct disjoint<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
typedef typename strategies::relate::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
@@ -74,13 +101,21 @@ struct disjoint
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_dynamic {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
bool IsDynamic = util::is_dynamic_geometry<Geometry1>::value
|
||||
|| util::is_dynamic_geometry<Geometry2>::value,
|
||||
bool IsCollection = util::is_geometry_collection<Geometry1>::value
|
||||
|| util::is_geometry_collection<Geometry2>::value
|
||||
>
|
||||
struct disjoint
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions
|
||||
<
|
||||
@@ -88,108 +123,60 @@ struct disjoint
|
||||
Geometry2 const
|
||||
>();
|
||||
|
||||
return resolve_strategy::disjoint::apply(geometry1, geometry2, strategy);
|
||||
return resolve_strategy::disjoint
|
||||
<
|
||||
Strategy
|
||||
>::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 Geometry1, typename Geometry2>
|
||||
struct disjoint<Geometry1, Geometry2, true, false>
|
||||
{
|
||||
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,
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
bool result = true;
|
||||
detail::visit([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
result = disjoint
|
||||
<
|
||||
util::remove_cref_t<decltype(g1)>, util::remove_cref_t<decltype(g2)>
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct disjoint<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
// TODO: The complexity is quadratic for two GCs
|
||||
// Decrease e.g. with spatial index
|
||||
template <typename Geometry1, typename Geometry2, bool IsDynamic>
|
||||
struct disjoint<Geometry1, Geometry2, IsDynamic, true>
|
||||
{
|
||||
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,
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
bool result = true;
|
||||
detail::visit_breadth_first([&](auto const& g1)
|
||||
{
|
||||
detail::visit_breadth_first([&](auto const& g2)
|
||||
{
|
||||
result = disjoint
|
||||
<
|
||||
util::remove_cref_t<decltype(g1)>, util::remove_cref_t<decltype(g2)>
|
||||
>::apply(g1, g2, strategy);
|
||||
// If any of the combination intersects then the final result is not disjoint
|
||||
return result;
|
||||
}, geometry2);
|
||||
return result;
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -211,7 +198,7 @@ inline bool disjoint(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::disjoint
|
||||
return resolve_dynamic::disjoint
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
@@ -228,12 +215,17 @@ inline bool disjoint(Geometry1 const& geometry1,
|
||||
\return \return_check2{are disjoint}
|
||||
|
||||
\qbk{[include reference/algorithms/disjoint.qbk]}
|
||||
\qbk{
|
||||
[heading Examples]
|
||||
[disjoint]
|
||||
[disjoint_output]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool disjoint(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::disjoint
|
||||
return resolve_dynamic::disjoint
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2022.
|
||||
// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -23,7 +24,9 @@
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
@@ -34,11 +37,10 @@
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
@@ -49,6 +51,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -68,11 +71,11 @@ struct disjoint_no_intersections_policy
|
||||
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;
|
||||
using point_type = typename point_type<Geometry1>::type;
|
||||
typename helper_geometry<point_type>::type p;
|
||||
geometry::point_on_border(p, g1);
|
||||
|
||||
return !geometry::covered_by(p, g2, strategy);
|
||||
return ! geometry::covered_by(p, g2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,12 +89,11 @@ struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
|
||||
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 )
|
||||
for (auto 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) )
|
||||
if (! disjoint_no_intersections_policy<value_type const, Geometry2>
|
||||
::apply(*it, g2, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -118,9 +120,7 @@ struct disjoint_linear_areal
|
||||
return false;
|
||||
}
|
||||
|
||||
return NoIntersectionsPolicy
|
||||
::apply(g1, g2,
|
||||
strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>());
|
||||
return NoIntersectionsPolicy::apply(g1, g2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,31 +141,25 @@ struct disjoint_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;
|
||||
using ring_type = typename boost::range_value<InteriorRings>::type;
|
||||
|
||||
typedef unary_disjoint_geometry_to_query_geometry
|
||||
using unary_predicate_type = 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));
|
||||
disjoint_range_segment_or_box<ring_type, Segment>
|
||||
>;
|
||||
|
||||
return std::all_of(boost::begin(interior_rings),
|
||||
boost::end(interior_rings),
|
||||
unary_predicate_type(segment, strategy));
|
||||
}
|
||||
|
||||
|
||||
@@ -175,17 +169,16 @@ public:
|
||||
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) )
|
||||
if (! disjoint_range_segment_or_box
|
||||
<
|
||||
typename geometry::ring_type<Polygon>::type,
|
||||
Segment
|
||||
>::apply(geometry::exterior_ring(polygon), segment, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !check_interior_rings(geometry::interior_rings(polygon), segment, strategy) )
|
||||
if (! check_interior_rings(geometry::interior_rings(polygon), segment, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -193,8 +186,7 @@ public:
|
||||
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>());
|
||||
return ! geometry::covered_by(p, polygon, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -222,10 +214,7 @@ struct disjoint_segment_areal<Segment, Ring, ring_tag>
|
||||
Ring const& ring,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
if ( !disjoint_range_segment_or_box
|
||||
<
|
||||
Ring, closure<Ring>::value, Segment
|
||||
>::apply(ring, segment, strategy) )
|
||||
if (! disjoint_range_segment_or_box<Ring, Segment>::apply(ring, segment, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -233,8 +222,7 @@ struct disjoint_segment_areal<Segment, Ring, ring_tag>
|
||||
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>());
|
||||
return ! geometry::covered_by(p, ring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2013-2020.
|
||||
// Modifications copyright (c) 2013-2020, 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
|
||||
@@ -24,9 +24,6 @@
|
||||
#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>
|
||||
@@ -34,10 +31,12 @@
|
||||
#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/algorithms/detail/overlay/segment_as_subrange.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.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>
|
||||
|
||||
@@ -59,28 +58,17 @@ struct disjoint_segment
|
||||
{
|
||||
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 segment_intersection_points<point_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);
|
||||
detail::segment_as_subrange<Segment1> sub_range1(segment1);
|
||||
detail::segment_as_subrange<Segment2> sub_range2(segment2);
|
||||
intersection_return_type is = strategy.relate().apply(sub_range1, sub_range2,
|
||||
intersection_policy());
|
||||
|
||||
return is.count == 0;
|
||||
}
|
||||
@@ -93,6 +81,7 @@ struct assign_disjoint_policy
|
||||
static bool const include_no_turn = true;
|
||||
static bool const include_degenerate = true;
|
||||
static bool const include_opposite = true;
|
||||
static bool const include_start_turn = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -104,21 +93,21 @@ struct disjoint_linear
|
||||
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
|
||||
using point_type = typename geometry::point_type<Geometry1>::type;
|
||||
using mutable_point_type = typename helper_geometry<point_type>::type;
|
||||
using ratio_type = geometry::segment_ratio
|
||||
<
|
||||
point_type, rescale_policy_type
|
||||
>::type segment_ratio_type;
|
||||
typedef overlay::turn_info
|
||||
typename coordinate_type<point_type>::type
|
||||
> ;
|
||||
using turn_info_type = overlay::turn_info
|
||||
<
|
||||
point_type,
|
||||
segment_ratio_type,
|
||||
mutable_point_type,
|
||||
ratio_type,
|
||||
typename detail::get_turns::turn_operation_type
|
||||
<
|
||||
Geometry1, Geometry2, segment_ratio_type
|
||||
Geometry1, Geometry2, mutable_point_type, ratio_type
|
||||
>::type
|
||||
> turn_info_type;
|
||||
>;
|
||||
|
||||
std::deque<turn_info_type> turns;
|
||||
|
||||
@@ -139,7 +128,7 @@ struct disjoint_linear
|
||||
Geometry1, Geometry2, assign_disjoint_policy
|
||||
>
|
||||
>::apply(0, geometry1, 1, geometry2,
|
||||
strategy, rescale_policy_type(), turns, interrupt_policy);
|
||||
strategy, detail::no_rescale_policy(), turns, interrupt_policy);
|
||||
|
||||
return !interrupt_policy.has_intersections;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021, 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
|
||||
@@ -21,19 +21,14 @@
|
||||
#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>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -47,10 +42,41 @@ namespace detail { namespace disjoint
|
||||
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
closure_selector Closure,
|
||||
typename SegmentOrBox
|
||||
typename SegmentOrBox,
|
||||
typename Tag = typename tag<SegmentOrBox>::type
|
||||
>
|
||||
struct disjoint_point_segment_or_box
|
||||
: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct disjoint_point_segment_or_box<Segment, segment_tag>
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline bool apply(Point const& point, Segment const& segment, Strategy const& strategy)
|
||||
{
|
||||
return dispatch::disjoint
|
||||
<
|
||||
Point, Segment
|
||||
>::apply(point, segment, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct disjoint_point_segment_or_box<Box, box_tag>
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
return dispatch::disjoint
|
||||
<
|
||||
Point, Box
|
||||
>::apply(point, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Range, typename SegmentOrBox>
|
||||
struct disjoint_range_segment_or_box
|
||||
{
|
||||
template <typename Strategy>
|
||||
@@ -58,24 +84,12 @@ struct disjoint_range_segment_or_box
|
||||
SegmentOrBox const& segment_or_box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename closeable_view<Range const, Closure>::type view_type;
|
||||
using point_type = typename point_type<Range>::type;
|
||||
using range_segment = typename geometry::model::referring_segment<point_type const>;
|
||||
|
||||
typedef typename ::boost::range_value<view_type>::type point_type;
|
||||
typedef typename ::boost::range_iterator
|
||||
<
|
||||
view_type const
|
||||
>::type const_iterator;
|
||||
detail::closed_view<Range const> const view(range);
|
||||
|
||||
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);
|
||||
auto const count = ::boost::size(view);
|
||||
|
||||
if ( count == 0 )
|
||||
{
|
||||
@@ -83,22 +97,22 @@ struct disjoint_range_segment_or_box
|
||||
}
|
||||
else if ( count == 1 )
|
||||
{
|
||||
return dispatch::disjoint
|
||||
return disjoint_point_segment_or_box
|
||||
<
|
||||
point_type, SegmentOrBox
|
||||
>::apply(geometry::range::front<view_type const>(view),
|
||||
segment_or_box,
|
||||
strategy.template get_point_in_geometry_strategy<Range, SegmentOrBox>());
|
||||
SegmentOrBox
|
||||
>::apply(range::front(view), segment_or_box, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
const_iterator it0 = ::boost::begin(view);
|
||||
const_iterator it1 = ::boost::begin(view) + 1;
|
||||
const_iterator last = ::boost::end(view);
|
||||
auto it0 = ::boost::begin(view);
|
||||
auto it1 = ::boost::begin(view) + 1;
|
||||
auto const last = ::boost::end(view);
|
||||
|
||||
for ( ; it1 != last ; ++it0, ++it1 )
|
||||
{
|
||||
range_segment rng_segment(*it0, *it1);
|
||||
point_type const& p0 = *it0;
|
||||
point_type const& p1 = *it1;
|
||||
range_segment rng_segment(p0, p1);
|
||||
if ( !dispatch::disjoint
|
||||
<
|
||||
range_segment, SegmentOrBox
|
||||
@@ -128,7 +142,7 @@ struct disjoint_linear_segment_or_box
|
||||
|
||||
template <typename Linestring, typename SegmentOrBox>
|
||||
struct disjoint_linear_segment_or_box<Linestring, SegmentOrBox, linestring_tag>
|
||||
: disjoint_range_segment_or_box<Linestring, closed, SegmentOrBox>
|
||||
: disjoint_range_segment_or_box<Linestring, SegmentOrBox>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2023, 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
|
||||
|
||||
@@ -15,8 +17,10 @@
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/mpl/assert.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/core/assert.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
@@ -29,7 +33,6 @@
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
@@ -42,6 +45,12 @@
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
|
||||
// TEMP
|
||||
#include <boost/geometry/strategies/envelope/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/envelope/geographic.hpp>
|
||||
#include <boost/geometry/strategies/envelope/spherical.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -51,29 +60,28 @@ namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2>
|
||||
class multipoint_multipoint
|
||||
{
|
||||
private:
|
||||
template <typename Iterator>
|
||||
class unary_disjoint_predicate
|
||||
: geometry::less<>
|
||||
template <typename Iterator, typename Strategy>
|
||||
class unary_not_disjoint_predicate
|
||||
: geometry::less<void, -1, Strategy>
|
||||
{
|
||||
private:
|
||||
typedef geometry::less<> base_type;
|
||||
using less_type = geometry::less<void, -1, Strategy>;
|
||||
|
||||
public:
|
||||
unary_disjoint_predicate(Iterator first, Iterator last)
|
||||
: base_type(), m_first(first), m_last(last)
|
||||
unary_not_disjoint_predicate(Iterator first, Iterator last)
|
||||
: less_type(), m_first(first), m_last(last)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
inline bool apply(Point const& point) const
|
||||
inline bool operator()(Point const& point) const
|
||||
{
|
||||
return !std::binary_search(m_first,
|
||||
m_last,
|
||||
point,
|
||||
static_cast<base_type const&>(*this));
|
||||
return std::binary_search(m_first,
|
||||
m_last,
|
||||
point,
|
||||
static_cast<less_type const&>(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -81,29 +89,30 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
static inline bool apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2)
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const&)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
|
||||
|
||||
typedef typename boost::range_value<MultiPoint1>::type point1_type;
|
||||
using less_type = geometry::less<void, -1, Strategy>;
|
||||
using point1_type = typename boost::range_value<MultiPoint1>::type;
|
||||
|
||||
std::vector<point1_type> points1(boost::begin(multipoint1),
|
||||
boost::end(multipoint1));
|
||||
|
||||
std::sort(points1.begin(), points1.end(), geometry::less<>());
|
||||
std::sort(points1.begin(), points1.end(), less_type());
|
||||
|
||||
typedef unary_disjoint_predicate
|
||||
using predicate_type = unary_not_disjoint_predicate
|
||||
<
|
||||
typename std::vector<point1_type>::const_iterator
|
||||
> predicate_type;
|
||||
typename std::vector<point1_type>::const_iterator,
|
||||
Strategy
|
||||
>;
|
||||
|
||||
return check_iterator_range
|
||||
<
|
||||
predicate_type
|
||||
>::apply(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
predicate_type(points1.begin(), points1.end()));
|
||||
return none_of(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
predicate_type(points1.begin(), points1.end()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,65 +121,78 @@ template <typename MultiPoint, typename Linear>
|
||||
class multipoint_linear
|
||||
{
|
||||
private:
|
||||
template <typename Strategy>
|
||||
struct expand_box_point
|
||||
{
|
||||
explicit expand_box_point(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Point>
|
||||
static inline void apply(Box& total, Point const& point)
|
||||
void apply(Box& total, Point const& point) const
|
||||
{
|
||||
geometry::expand(total, point);
|
||||
geometry::expand(total, point, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename EnvelopeStrategy>
|
||||
template <typename Strategy>
|
||||
struct expand_box_segment
|
||||
{
|
||||
explicit expand_box_segment(EnvelopeStrategy const& strategy)
|
||||
explicit expand_box_segment(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
inline void apply(Box& total, Segment const& segment) const
|
||||
void apply(Box& total, Segment const& segment) const
|
||||
{
|
||||
geometry::expand(total,
|
||||
geometry::return_envelope<Box>(segment, m_strategy));
|
||||
geometry::return_envelope<Box>(segment, m_strategy),
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
EnvelopeStrategy const& m_strategy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_point
|
||||
{
|
||||
explicit overlaps_box_point(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Point>
|
||||
static inline bool apply(Box const& box, Point const& point)
|
||||
bool apply(Box const& box, Point const& point) const
|
||||
{
|
||||
// The default strategy is enough in this case
|
||||
return ! detail::disjoint::disjoint_point_box(point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename DisjointStrategy>
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_segment
|
||||
{
|
||||
explicit overlaps_box_segment(DisjointStrategy const& strategy)
|
||||
explicit overlaps_box_segment(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
inline bool apply(Box const& box, Segment const& segment) const
|
||||
bool apply(Box const& box, Segment const& segment) const
|
||||
{
|
||||
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
|
||||
}
|
||||
|
||||
DisjointStrategy const& m_strategy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename PtSegStrategy>
|
||||
template <typename Strategy>
|
||||
class item_visitor_type
|
||||
{
|
||||
public:
|
||||
item_visitor_type(PtSegStrategy const& strategy)
|
||||
item_visitor_type(Strategy const& strategy)
|
||||
: m_intersection_found(false)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
@@ -191,7 +213,7 @@ private:
|
||||
|
||||
private:
|
||||
bool m_intersection_found;
|
||||
PtSegStrategy const& m_strategy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
// structs for partition -- end
|
||||
|
||||
@@ -225,10 +247,6 @@ public:
|
||||
{
|
||||
item_visitor_type<Strategy> visitor(strategy);
|
||||
|
||||
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
|
||||
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
|
||||
typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type;
|
||||
|
||||
// TODO: disjoint Segment/Box may be called in partition multiple times
|
||||
// possibly for non-cartesian segments which could be slow. We should consider
|
||||
// passing a range of bounding boxes of segments after calculating them once.
|
||||
@@ -238,16 +256,17 @@ public:
|
||||
<
|
||||
geometry::model::box<typename point_type<MultiPoint>::type>
|
||||
>::apply(multipoint, segment_range(linear), visitor,
|
||||
expand_box_point(),
|
||||
overlaps_box_point<disjoint_pb_strategy_type>(),
|
||||
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
|
||||
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
|
||||
expand_box_point<Strategy>(strategy),
|
||||
overlaps_box_point<Strategy>(strategy),
|
||||
expand_box_segment<Strategy>(strategy),
|
||||
overlaps_box_segment<Strategy>(strategy));
|
||||
|
||||
return ! visitor.intersection_found();
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy)
|
||||
static inline bool apply(Linear const& linear, MultiPoint const& multipoint,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(multipoint, linear, strategy);
|
||||
}
|
||||
@@ -263,21 +282,18 @@ public:
|
||||
SingleGeometry const& single_geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type;
|
||||
|
||||
typedef typename point_type<MultiPoint>::type point1_type;
|
||||
typedef typename point_type<SingleGeometry>::type point2_type;
|
||||
typedef model::box<point2_type> box2_type;
|
||||
|
||||
|
||||
box2_type box2;
|
||||
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
|
||||
geometry::envelope(single_geometry, box2, strategy);
|
||||
geometry::detail::expand_by_epsilon(box2);
|
||||
|
||||
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
|
||||
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
|
||||
for (auto it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it)
|
||||
{
|
||||
// The default strategy is enough for Point/Box
|
||||
if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())
|
||||
if (! detail::disjoint::disjoint_point_box(*it, box2, strategy)
|
||||
&& ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
|
||||
{
|
||||
return false;
|
||||
@@ -288,7 +304,8 @@ public:
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy)
|
||||
static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(multi_point, single_geometry, strategy);
|
||||
}
|
||||
@@ -299,54 +316,77 @@ template <typename MultiPoint, typename MultiGeometry>
|
||||
class multi_point_multi_geometry
|
||||
{
|
||||
private:
|
||||
template <typename Strategy>
|
||||
struct expand_box_point
|
||||
{
|
||||
explicit expand_box_point(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Point>
|
||||
static inline void apply(Box& total, Point const& point)
|
||||
void apply(Box& total, Point const& point) const
|
||||
{
|
||||
geometry::expand(total, point);
|
||||
geometry::expand(total, point, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct expand_box_box_pair
|
||||
{
|
||||
explicit expand_box_box_pair(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename BoxPair>
|
||||
inline void apply(Box& total, BoxPair const& box_pair) const
|
||||
void apply(Box& total, BoxPair const& box_pair) const
|
||||
{
|
||||
geometry::expand(total, box_pair.first);
|
||||
geometry::expand(total, box_pair.first, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_point
|
||||
{
|
||||
explicit overlaps_box_point(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Point>
|
||||
static inline bool apply(Box const& box, Point const& point)
|
||||
bool apply(Box const& box, Point const& point) const
|
||||
{
|
||||
// The default strategy is enough for Point/Box
|
||||
return ! detail::disjoint::disjoint_point_box(point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
return ! detail::disjoint::disjoint_point_box(point, box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_box_pair
|
||||
{
|
||||
explicit overlaps_box_box_pair(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename BoxPair>
|
||||
inline bool apply(Box const& box, BoxPair const& box_pair) const
|
||||
bool apply(Box const& box, BoxPair const& box_pair) const
|
||||
{
|
||||
// The default strategy is enough for Box/Box
|
||||
return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
|
||||
DisjointBoxBoxStrategy());
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename PtSegStrategy>
|
||||
template <typename Strategy>
|
||||
class item_visitor_type
|
||||
{
|
||||
public:
|
||||
item_visitor_type(MultiGeometry const& multi_geometry,
|
||||
PtSegStrategy const& strategy)
|
||||
Strategy const& strategy)
|
||||
: m_intersection_found(false)
|
||||
, m_multi_geometry(multi_geometry)
|
||||
, m_strategy(strategy)
|
||||
@@ -355,14 +395,15 @@ private:
|
||||
template <typename Point, typename BoxPair>
|
||||
inline bool apply(Point const& point, BoxPair const& box_pair)
|
||||
{
|
||||
typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type;
|
||||
|
||||
typedef typename boost::range_value<MultiGeometry>::type single_type;
|
||||
|
||||
// The default strategy is enough for Point/Box
|
||||
if (! m_intersection_found
|
||||
&& ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type())
|
||||
&& ! dispatch::disjoint<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
|
||||
&& ! detail::disjoint::disjoint_point_box(point, box_pair.first, m_strategy)
|
||||
&& ! dispatch::disjoint
|
||||
<
|
||||
Point, single_type
|
||||
>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
|
||||
{
|
||||
m_intersection_found = true;
|
||||
return false;
|
||||
@@ -375,7 +416,7 @@ private:
|
||||
private:
|
||||
bool m_intersection_found;
|
||||
MultiGeometry const& m_multi_geometry;
|
||||
PtSegStrategy const& m_strategy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
// structs for partition -- end
|
||||
|
||||
@@ -389,37 +430,25 @@ public:
|
||||
typedef model::box<point2_type> box2_type;
|
||||
typedef std::pair<box2_type, std::size_t> box_pair_type;
|
||||
|
||||
typename Strategy::envelope_strategy_type const
|
||||
envelope_strategy = strategy.get_envelope_strategy();
|
||||
|
||||
std::size_t count2 = boost::size(multi_geometry);
|
||||
std::vector<box_pair_type> boxes(count2);
|
||||
for (std::size_t i = 0 ; i < count2 ; ++i)
|
||||
{
|
||||
geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
|
||||
geometry::envelope(range::at(multi_geometry, i), boxes[i].first, strategy);
|
||||
geometry::detail::expand_by_epsilon(boxes[i].first);
|
||||
boxes[i].second = i;
|
||||
}
|
||||
|
||||
item_visitor_type<Strategy> visitor(multi_geometry, strategy);
|
||||
|
||||
typedef overlaps_box_point
|
||||
<
|
||||
typename Strategy::disjoint_point_box_strategy_type
|
||||
> overlaps_box_point_type;
|
||||
typedef overlaps_box_box_pair
|
||||
<
|
||||
typename Strategy::disjoint_box_box_strategy_type
|
||||
> overlaps_box_box_pair_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
box1_type
|
||||
>::apply(multi_point, boxes, visitor,
|
||||
expand_box_point(),
|
||||
overlaps_box_point_type(),
|
||||
expand_box_box_pair(),
|
||||
overlaps_box_box_pair_type());
|
||||
expand_box_point<Strategy>(strategy),
|
||||
overlaps_box_point<Strategy>(strategy),
|
||||
expand_box_box_pair<Strategy>(strategy),
|
||||
overlaps_box_box_pair<Strategy>(strategy));
|
||||
|
||||
return ! visitor.intersection_found();
|
||||
}
|
||||
@@ -493,20 +522,16 @@ struct disjoint
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const& )
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( boost::size(multipoint2) < boost::size(multipoint1) )
|
||||
{
|
||||
return detail::disjoint::multipoint_multipoint
|
||||
<
|
||||
MultiPoint2, MultiPoint1
|
||||
>::apply(multipoint2, multipoint1);
|
||||
}
|
||||
::apply(multipoint2, multipoint1, strategy);
|
||||
}
|
||||
|
||||
return detail::disjoint::multipoint_multipoint
|
||||
<
|
||||
MultiPoint1, MultiPoint2
|
||||
>::apply(multipoint1, multipoint2);
|
||||
::apply(multipoint1, multipoint2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2023, 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
|
||||
|
||||
@@ -11,9 +12,12 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
@@ -31,13 +35,13 @@ class unary_disjoint_geometry_to_query_geometry
|
||||
{
|
||||
public:
|
||||
unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
Strategy const& strategy)
|
||||
: m_geometry(geometry)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename QueryGeometry>
|
||||
inline bool apply(QueryGeometry const& query_geometry) const
|
||||
inline bool operator()(QueryGeometry const& query_geometry) const
|
||||
{
|
||||
return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
|
||||
}
|
||||
@@ -56,7 +60,7 @@ struct multirange_constant_size_geometry
|
||||
ConstantSizeGeometry const& constant_size_geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef unary_disjoint_geometry_to_query_geometry
|
||||
using disjoint = unary_disjoint_geometry_to_query_geometry
|
||||
<
|
||||
ConstantSizeGeometry,
|
||||
Strategy,
|
||||
@@ -65,13 +69,11 @@ struct multirange_constant_size_geometry
|
||||
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));
|
||||
return std::all_of(boost::begin(multirange),
|
||||
boost::end(multirange),
|
||||
disjoint(constant_size_geometry, strategy));
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021, 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
|
||||
|
||||
@@ -23,12 +22,13 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#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>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -41,8 +41,26 @@ namespace detail { namespace disjoint
|
||||
/*!
|
||||
\brief Internal utility function to detect if point/box are disjoint
|
||||
*/
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& )
|
||||
template
|
||||
<
|
||||
typename Point, typename Box, typename Strategy,
|
||||
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
|
||||
>
|
||||
inline bool disjoint_point_box(Point const& point, Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef decltype(strategy.covered_by(point, box)) strategy_type;
|
||||
// ! covered_by(point, box)
|
||||
return ! strategy_type::apply(point, box);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point, typename Box, typename Strategy,
|
||||
std::enable_if_t<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
|
||||
>
|
||||
inline bool disjoint_point_box(Point const& point, Box const& box,
|
||||
Strategy const& )
|
||||
{
|
||||
// ! covered_by(point, box)
|
||||
return ! Strategy::apply(point, box);
|
||||
@@ -62,10 +80,12 @@ 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& )
|
||||
static inline bool apply(Point const& point, Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef decltype(strategy.covered_by(point, box)) strategy_type;
|
||||
// ! covered_by(point, box)
|
||||
return ! Strategy::apply(point, box);
|
||||
return ! strategy_type::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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.
|
||||
// This file was modified by Oracle on 2013-2022.
|
||||
// Modifications copyright (c) 2013-2022, 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
|
||||
@@ -21,7 +21,7 @@
|
||||
#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/covered_by/implementation.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2020.
|
||||
// Modifications copyright (c) 2013-2020, 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
|
||||
@@ -22,11 +22,14 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
@@ -46,10 +49,28 @@ namespace detail { namespace disjoint
|
||||
\brief Internal utility function to detect of points are disjoint
|
||||
\note To avoid circular references
|
||||
*/
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2, typename Strategy,
|
||||
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
|
||||
>
|
||||
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef decltype(strategy.relate(point1, point2)) strategy_type;
|
||||
// ! within(point1, point2)
|
||||
return ! strategy_type::apply(point1, point2);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2, typename Strategy,
|
||||
std::enable_if_t<! strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
|
||||
>
|
||||
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2,
|
||||
Strategy const& )
|
||||
{
|
||||
// ! within(point1, point2)
|
||||
return ! Strategy::apply(point1, point2);
|
||||
}
|
||||
|
||||
@@ -68,9 +89,11 @@ struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2,
|
||||
Strategy const& )
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return ! Strategy::apply(point1, point2);
|
||||
typedef decltype(strategy.relate(point1, point2)) strategy_type;
|
||||
// ! within(point1, point2)
|
||||
return ! strategy_type::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2019.
|
||||
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021, 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
|
||||
@@ -33,14 +33,13 @@
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/vertex_longitude.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
// Temporary, for envelope_segment_impl
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -181,12 +180,31 @@ struct disjoint_segment_box_sphere_or_spheroid
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
|
||||
|
||||
bool b0 = formula::azimuth_side_value(alp1, a_b0) > 0;
|
||||
bool b1 = formula::azimuth_side_value(alp1, a_b1) > 0;
|
||||
bool b2 = formula::azimuth_side_value(alp1, a_b2) > 0;
|
||||
bool b3 = formula::azimuth_side_value(alp1, a_b3) > 0;
|
||||
int s0 = formula::azimuth_side_value(alp1, a_b0);
|
||||
int s1 = formula::azimuth_side_value(alp1, a_b1);
|
||||
int s2 = formula::azimuth_side_value(alp1, a_b2);
|
||||
int s3 = formula::azimuth_side_value(alp1, a_b3);
|
||||
|
||||
if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3))
|
||||
if (s0 == 0 || s1 == 0 || s2 == 0 || s3 == 0)
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
|
||||
bool s0_positive = s0 > 0;
|
||||
bool s1_positive = s1 > 0;
|
||||
bool s2_positive = s2 > 0;
|
||||
bool s3_positive = s3 > 0;
|
||||
|
||||
bool all_positive = s0_positive && s1_positive && s2_positive && s3_positive;
|
||||
bool all_non_positive = !(s0_positive || s1_positive || s2_positive || s3_positive);
|
||||
bool vertex_north = lat1 + lat2 > 0;
|
||||
|
||||
if ((all_positive && vertex_north) || (all_non_positive && !vertex_north))
|
||||
{
|
||||
return disjoint_info::disjoint_no_vertex;
|
||||
}
|
||||
|
||||
if (!all_positive && !all_non_positive)
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
@@ -196,14 +214,13 @@ struct disjoint_segment_box_sphere_or_spheroid
|
||||
// hemisphere. Then we have to compute the vertex of the segment
|
||||
|
||||
CT vertex_lat;
|
||||
CT lat_sum = lat1 + lat2;
|
||||
|
||||
if ((lat1 < b_lat_min && lat_sum > CT(0))
|
||||
|| (lat1 > b_lat_max && lat_sum < CT(0)))
|
||||
if ((lat1 < b_lat_min && vertex_north)
|
||||
|| (lat1 > b_lat_max && !vertex_north))
|
||||
{
|
||||
CT b_lat_below; //latitude of box closest to equator
|
||||
|
||||
if (lat_sum > CT(0))
|
||||
if (vertex_north)
|
||||
{
|
||||
vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
|
||||
b_lat_below = b_lat_min;
|
||||
@@ -247,7 +264,7 @@ struct disjoint_segment_box
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return strategy.apply(segment, box);
|
||||
return strategy.disjoint(segment, box).apply(segment, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
// 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
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -29,23 +30,17 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, typename Strategy>
|
||||
template <typename Box1, typename Box2, typename Strategies>
|
||||
struct distance
|
||||
<
|
||||
Box1, Box2, Strategy, box_tag, box_tag,
|
||||
Box1, Box2, Strategies, 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)
|
||||
static inline auto apply(Box1 const& box1, Box2 const& box2, Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(box1, box2);
|
||||
boost::ignore_unused(strategies);
|
||||
return strategies.distance(box1, box2).apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/reverse_dispatch.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Helper metafunction for default strategy retrieval
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2 = Geometry1,
|
||||
typename Tag1 = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry1>::type, pointlike_tag
|
||||
>::type,
|
||||
typename Tag2 = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry2>::type, pointlike_tag
|
||||
>::type,
|
||||
bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
|
||||
>
|
||||
struct default_strategy
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, segment_tag,
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1,
|
||||
typename Tag2
|
||||
>
|
||||
struct default_strategy<Geometry1, Geometry2, Tag1, Tag2, true>
|
||||
: default_strategy<Geometry2, Geometry1, Tag2, Tag1, false>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Pointlike1, typename Pointlike2>
|
||||
struct default_strategy
|
||||
<
|
||||
Pointlike1, Pointlike2,
|
||||
pointlike_tag, pointlike_tag, false
|
||||
> : strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, point_tag,
|
||||
typename point_type<Pointlike1>::type,
|
||||
typename point_type<Pointlike2>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Pointlike, typename Box>
|
||||
struct default_strategy<Pointlike, Box, pointlike_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, box_tag,
|
||||
typename point_type<Pointlike>::type,
|
||||
typename point_type<Box>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct default_strategy<Box1, Box2, box_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
box_tag, box_tag,
|
||||
typename point_type<Box1>::type,
|
||||
typename point_type<Box2>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Linear, typename Box>
|
||||
struct default_strategy<Linear, Box, segment_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
segment_tag, box_tag,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Box>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Linear, typename Box>
|
||||
struct default_strategy<Linear, Box, linear_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
segment_tag, box_tag,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Box>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
// Helper metafunction for default point-segment strategy retrieval
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
struct default_ps_strategy
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
point_tag, segment_tag,
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type,
|
||||
typename cs_tag<typename point_type<Geometry1>::type>::type,
|
||||
typename cs_tag<typename point_type<Geometry2>::type>::type,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_DEFAULT_STRATEGIES_HPP
|
||||
@@ -0,0 +1,237 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/algorithms/detail/visit.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/index/rtree.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/distance_result.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, typename GeometryCollection, typename Strategies>
|
||||
inline auto geometry_to_collection(Geometry const& geometry,
|
||||
GeometryCollection const& collection,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
using result_t = typename geometry::distance_result<Geometry, GeometryCollection, Strategies>::type;
|
||||
result_t result = 0;
|
||||
bool is_first = true;
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
result_t r = dispatch::distance
|
||||
<
|
||||
Geometry, util::remove_cref_t<decltype(g)>, Strategies
|
||||
>::apply(geometry, g, strategies);
|
||||
if (is_first)
|
||||
{
|
||||
result = r;
|
||||
is_first = false;
|
||||
}
|
||||
else if (r < result)
|
||||
{
|
||||
result = r;
|
||||
}
|
||||
return result > result_t(0);
|
||||
}, collection);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename GeometryCollection1, typename GeometryCollection2, typename Strategies>
|
||||
inline auto collection_to_collection(GeometryCollection1 const& collection1,
|
||||
GeometryCollection2 const& collection2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
using result_t = typename geometry::distance_result<GeometryCollection1, GeometryCollection2, Strategies>::type;
|
||||
|
||||
using point1_t = typename geometry::point_type<GeometryCollection1>::type;
|
||||
using box1_t = model::box<point1_t>;
|
||||
using point2_t = typename geometry::point_type<GeometryCollection2>::type;
|
||||
using box2_t = model::box<point2_t>;
|
||||
|
||||
using rtree_value_t = std::pair<box1_t, typename boost::range_iterator<GeometryCollection1 const>::type>;
|
||||
using rtree_params_t = index::parameters<index::rstar<4>, Strategies>;
|
||||
using rtree_t = index::rtree<rtree_value_t, rtree_params_t>;
|
||||
|
||||
rtree_params_t rtree_params(index::rstar<4>(), strategies);
|
||||
rtree_t rtree(rtree_params);
|
||||
|
||||
// Build rtree of boxes and iterators of elements of GC1
|
||||
// TODO: replace this with visit_breadth_first_iterator to avoid creating an unnecessary container?
|
||||
{
|
||||
std::vector<rtree_value_t> values;
|
||||
visit_breadth_first_impl<true>::apply([&](auto & g1, auto it)
|
||||
{
|
||||
box1_t b1 = geometry::return_envelope<box1_t>(g1, strategies);
|
||||
geometry::detail::expand_by_epsilon(b1);
|
||||
values.emplace_back(b1, it);
|
||||
return true;
|
||||
}, collection1);
|
||||
rtree_t rt(values.begin(), values.end(), rtree_params);
|
||||
rtree = std::move(rt);
|
||||
}
|
||||
|
||||
result_t const zero = 0;
|
||||
auto const rtree_qend = rtree.qend();
|
||||
|
||||
result_t result = 0;
|
||||
bool is_first = true;
|
||||
visit_breadth_first([&](auto const& g2)
|
||||
{
|
||||
box2_t b2 = geometry::return_envelope<box2_t>(g2, strategies);
|
||||
geometry::detail::expand_by_epsilon(b2);
|
||||
|
||||
for (auto it = rtree.qbegin(index::nearest(b2, rtree.size())) ; it != rtree_qend ; ++it)
|
||||
{
|
||||
// If the distance between boxes is greater than or equal to previously found
|
||||
// distance between geometries then stop processing the current b2 because no
|
||||
// closer b1 will be found
|
||||
if (! is_first)
|
||||
{
|
||||
result_t const bd = dispatch::distance
|
||||
<
|
||||
box1_t, box2_t, Strategies
|
||||
>::apply(it->first, b2, strategies);
|
||||
if (bd >= result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Boxes are closer than the previously found distance (or it's the first time),
|
||||
// calculate the new distance between geometries and check if it's closer (or assign it).
|
||||
traits::iter_visit<GeometryCollection1>::apply([&](auto const& g1)
|
||||
{
|
||||
result_t const d = dispatch::distance
|
||||
<
|
||||
util::remove_cref_t<decltype(g1)>, util::remove_cref_t<decltype(g2)>,
|
||||
Strategies
|
||||
>::apply(g1, g2, strategies);
|
||||
if (is_first)
|
||||
{
|
||||
result = d;
|
||||
is_first = false;
|
||||
}
|
||||
else if (d < result)
|
||||
{
|
||||
result = d;
|
||||
}
|
||||
}, it->second);
|
||||
|
||||
// The smallest possible distance found, end searching.
|
||||
if (! is_first && result <= zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Just in case
|
||||
return is_first || result > zero;
|
||||
}, collection2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry, typename GeometryCollection, typename Strategies, typename Tag1
|
||||
>
|
||||
struct distance
|
||||
<
|
||||
Geometry, GeometryCollection, Strategies,
|
||||
Tag1, geometry_collection_tag, void, false
|
||||
>
|
||||
{
|
||||
static inline auto apply(Geometry const& geometry,
|
||||
GeometryCollection const& collection,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
assert_dimension_equal<Geometry, GeometryCollection>();
|
||||
|
||||
return detail::distance::geometry_to_collection(geometry, collection, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryCollection, typename Geometry, typename Strategies, typename Tag2
|
||||
>
|
||||
struct distance
|
||||
<
|
||||
GeometryCollection, Geometry, Strategies,
|
||||
geometry_collection_tag, Tag2, void, false
|
||||
>
|
||||
{
|
||||
static inline auto apply(GeometryCollection const& collection,
|
||||
Geometry const& geometry,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
assert_dimension_equal<Geometry, GeometryCollection>();
|
||||
|
||||
return detail::distance::geometry_to_collection(geometry, collection, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryCollection1, typename GeometryCollection2, typename Strategies
|
||||
>
|
||||
struct distance
|
||||
<
|
||||
GeometryCollection1, GeometryCollection2, Strategies,
|
||||
geometry_collection_tag, geometry_collection_tag, void, false
|
||||
>
|
||||
{
|
||||
static inline auto apply(GeometryCollection1 const& collection1,
|
||||
GeometryCollection2 const& collection2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
assert_dimension_equal<GeometryCollection1, GeometryCollection2>();
|
||||
|
||||
// Build the rtree for the smaller GC (ignoring recursive GCs)
|
||||
return boost::size(collection1) <= boost::size(collection2)
|
||||
? detail::distance::collection_to_collection(collection1, collection2, strategies)
|
||||
: detail::distance::collection_to_collection(collection2, collection1, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -12,28 +13,27 @@
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.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/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/num_points.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/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
@@ -54,7 +54,7 @@ template
|
||||
>
|
||||
struct segment_or_box_point_range_closure
|
||||
: not_implemented<SegmentOrBox>
|
||||
{};
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct segment_or_box_point_range_closure<Segment, segment_tag>
|
||||
@@ -74,7 +74,7 @@ template
|
||||
<
|
||||
typename Geometry,
|
||||
typename SegmentOrBox,
|
||||
typename Strategy,
|
||||
typename Strategies,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
class geometry_to_segment_or_box
|
||||
@@ -82,28 +82,18 @@ 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 distance::strategy_t<Geometry, SegmentOrBox, Strategies> strategy_type;
|
||||
|
||||
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
|
||||
segment_or_box_point_range_closure<SegmentOrBox>::value
|
||||
> 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;
|
||||
|
||||
typedef distance::creturn_t<Geometry, SegmentOrBox, Strategies> comparable_return_type;
|
||||
|
||||
// assign the new minimum value for an iterator of the point range
|
||||
// of a segment or a box
|
||||
@@ -165,45 +155,34 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Geometry>::type,
|
||||
segment_or_box_point
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Geometry, SegmentOrBox, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Geometry const& geometry,
|
||||
SegmentOrBox const& segment_or_box,
|
||||
Strategy const& strategy,
|
||||
Strategies const& strategies,
|
||||
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))
|
||||
&& geometry::intersects(geometry, segment_or_box, strategies))
|
||||
{
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
comparable_strategy cstrategy =
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy);
|
||||
strategy_type const strategy = strategies.distance(geometry, segment_or_box);
|
||||
|
||||
auto const cstrategy = strategy::distance::services::get_comparable
|
||||
<
|
||||
strategy_type
|
||||
>::apply(strategy);
|
||||
|
||||
// get all points of the segment or the box
|
||||
std::vector<segment_or_box_point>
|
||||
@@ -211,32 +190,27 @@ public:
|
||||
|
||||
assign_segment_or_box_points
|
||||
<
|
||||
SegmentOrBox,
|
||||
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;
|
||||
auto pit_min = points_begin(geometry);
|
||||
auto it_min1 = boost::const_begin(seg_or_box_points);
|
||||
auto it_min2 = it_min1 + 1;
|
||||
bool first = true;
|
||||
|
||||
for (point_iterator_type pit = points_begin(geometry);
|
||||
for (auto pit = pit_min;
|
||||
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);
|
||||
auto 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)
|
||||
{
|
||||
@@ -251,10 +225,10 @@ public:
|
||||
// segments of the geometry
|
||||
comparable_return_type cd_min2(0);
|
||||
segment_iterator_type sit_min;
|
||||
seg_or_box_const_iterator it_min;
|
||||
auto it_min = boost::const_begin(seg_or_box_points);
|
||||
|
||||
first = true;
|
||||
for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points);
|
||||
for (auto it = boost::const_begin(seg_or_box_points);
|
||||
it != boost::const_end(seg_or_box_points); ++it, first = false)
|
||||
{
|
||||
comparable_return_type cd;
|
||||
@@ -273,7 +247,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<strategy_type>::value))
|
||||
{
|
||||
return (std::min)(cd_min1, cd_min2);
|
||||
}
|
||||
@@ -291,71 +265,53 @@ public:
|
||||
<
|
||||
segment_iterator_type
|
||||
>::value_type,
|
||||
Strategy
|
||||
>::apply(*it_min, *sit_min, strategy);
|
||||
Strategies
|
||||
>::apply(*it_min, *sit_min, strategies);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline return_type
|
||||
apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
|
||||
Strategy const& strategy, bool check_intersection = true)
|
||||
static inline return_type apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
|
||||
Strategies const& strategies, bool check_intersection = true)
|
||||
{
|
||||
return apply(geometry, segment_or_box, strategy, check_intersection);
|
||||
return apply(geometry, segment_or_box, strategies, check_intersection);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename MultiPoint, typename SegmentOrBox, typename Strategy>
|
||||
template <typename MultiPoint, typename SegmentOrBox, typename Strategies>
|
||||
class geometry_to_segment_or_box
|
||||
<
|
||||
MultiPoint, SegmentOrBox, Strategy, multi_point_tag
|
||||
MultiPoint, SegmentOrBox, Strategies, 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;
|
||||
typedef distance::strategy_t<MultiPoint, SegmentOrBox, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<SegmentOrBox>::type,
|
||||
typename point_type<MultiPoint>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<MultiPoint, SegmentOrBox, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint const& multipoint,
|
||||
SegmentOrBox const& segment_or_box,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
namespace sds = strategy::distance::services;
|
||||
distance::creturn_t<MultiPoint, SegmentOrBox, Strategies> cd_min;
|
||||
|
||||
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
|
||||
auto const it_min
|
||||
= geometry_to_range::apply(segment_or_box,
|
||||
boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
sds::get_comparable
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy),
|
||||
strategy_type
|
||||
>::apply(strategies.distance(multipoint, segment_or_box)),
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<Strategy>::value
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
@@ -363,8 +319,8 @@ public:
|
||||
<
|
||||
typename point_type<MultiPoint>::type,
|
||||
SegmentOrBox,
|
||||
Strategy
|
||||
>::apply(*it_min, segment_or_box, strategy);
|
||||
Strategies
|
||||
>::apply(*it_min, segment_or_box, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2018.
|
||||
// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021, 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.
|
||||
@@ -27,11 +27,15 @@
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/geometry_collection.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>
|
||||
#include <boost/geometry/strategies/distance/backward_compatibility.hpp>
|
||||
#include <boost/geometry/strategies/distance/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/distance/geographic.hpp>
|
||||
#include <boost/geometry/strategies/distance/spherical.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2018.
|
||||
// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// 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
|
||||
|
||||
@@ -24,23 +23,22 @@
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
#include <boost/mpl/always.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/visit.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/distance.hpp>
|
||||
// TODO: move these to algorithms
|
||||
#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>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/distance/services.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -66,17 +64,8 @@ struct distance
|
||||
>
|
||||
: 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)
|
||||
static inline auto apply(Geometry1 const& g1, Geometry2 const& g2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return distance
|
||||
<
|
||||
@@ -95,14 +84,17 @@ struct distance
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Strategy>
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct distance
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
@@ -111,17 +103,69 @@ struct distance
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct is_strategy_converter_specialized
|
||||
{
|
||||
typedef strategies::distance::services::strategy_converter<Strategy> converter;
|
||||
static const bool value = ! std::is_same
|
||||
<
|
||||
decltype(converter::get(std::declval<Strategy>())),
|
||||
strategies::detail::not_implemented
|
||||
>::value;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct distance<Strategy, false>
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2, typename S,
|
||||
std::enable_if_t<is_strategy_converter_specialized<S>::value, int> = 0
|
||||
>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
S const& strategy)
|
||||
{
|
||||
typedef strategies::distance::services::strategy_converter<Strategy> converter;
|
||||
typedef decltype(converter::get(strategy)) strategy_type;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, strategy_type
|
||||
>::apply(geometry1, geometry2, converter::get(strategy));
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2, typename S,
|
||||
std::enable_if_t<! is_strategy_converter_specialized<S>::value, int> = 0
|
||||
>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
S const& strategy)
|
||||
{
|
||||
typedef strategies::distance::services::custom_strategy_converter
|
||||
<
|
||||
Geometry1, Geometry2, Strategy
|
||||
> converter;
|
||||
typedef decltype(converter::get(strategy)) strategy_type;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, strategy_type
|
||||
>::apply(geometry1, geometry2, converter::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct distance<default_strategy>
|
||||
struct distance<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline
|
||||
typename distance_result<Geometry1, Geometry2, default_strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename detail::distance::default_strategy
|
||||
typedef typename strategies::distance::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
@@ -136,18 +180,22 @@ struct distance<default_strategy>
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type
|
||||
>
|
||||
struct distance
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::distance
|
||||
<
|
||||
@@ -157,174 +205,72 @@ struct distance
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
|
||||
struct distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor
|
||||
<
|
||||
typename distance_result
|
||||
<
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
|
||||
Geometry2,
|
||||
Strategy
|
||||
>::type
|
||||
>
|
||||
static inline auto apply(DynamicGeometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
using result_t = typename geometry::distance_result<DynamicGeometry1, Geometry2, Strategy>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
|
||||
{
|
||||
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);
|
||||
result = resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, geometry2, strategy);
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
|
||||
struct distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor
|
||||
<
|
||||
typename distance_result
|
||||
<
|
||||
Geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
|
||||
Strategy
|
||||
>::type
|
||||
>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
DynamicGeometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
using result_t = typename geometry::distance_result<Geometry1, DynamicGeometry2, Strategy>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
|
||||
{
|
||||
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);
|
||||
result = resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, g2, strategy);
|
||||
}, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 DynamicGeometry1, typename DynamicGeometry2>
|
||||
struct distance<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
|
||||
{
|
||||
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
|
||||
>
|
||||
static inline auto apply(DynamicGeometry1 const& geometry1,
|
||||
DynamicGeometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
using result_t = typename geometry::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
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);
|
||||
result = resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
@@ -364,10 +310,9 @@ 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)
|
||||
inline auto distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
@@ -375,7 +320,7 @@ distance(Geometry1 const& geometry1,
|
||||
detail::throw_on_empty_input(geometry1);
|
||||
detail::throw_on_empty_input(geometry2);
|
||||
|
||||
return resolve_variant::distance
|
||||
return resolve_dynamic::distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
@@ -397,13 +342,9 @@ distance(Geometry1 const& geometry1,
|
||||
\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)
|
||||
inline auto distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return geometry::distance(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2020, 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
|
||||
@@ -10,7 +11,8 @@
|
||||
#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 <type_traits>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
@@ -26,7 +28,7 @@ namespace detail { namespace distance
|
||||
// metafunction to determine is a strategy is comparable or not
|
||||
template <typename Strategy>
|
||||
struct is_comparable
|
||||
: boost::is_same
|
||||
: std::is_same
|
||||
<
|
||||
Strategy,
|
||||
typename strategy::distance::services::comparable_type
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -10,13 +11,14 @@
|
||||
#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/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.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
|
||||
{
|
||||
@@ -26,63 +28,53 @@ namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Areal, typename Strategy>
|
||||
template <typename Linear, typename Areal, typename Strategies>
|
||||
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;
|
||||
typedef distance::return_t<Linear, Areal, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
Areal const& areal,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( geometry::intersects(linear, areal) )
|
||||
if ( geometry::intersects(linear, areal, strategies) )
|
||||
{
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return linear_to_linear
|
||||
<
|
||||
Linear, Areal, Strategy
|
||||
>::apply(linear, areal, strategy, false);
|
||||
Linear, Areal, Strategies
|
||||
>::apply(linear, areal, strategies, false);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type apply(Areal const& areal,
|
||||
Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(linear, areal, strategy);
|
||||
return apply(linear, areal, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Strategy>
|
||||
template <typename Areal1, typename Areal2, typename Strategies>
|
||||
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;
|
||||
typedef distance::return_t<Areal1, Areal2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Areal1 const& areal1,
|
||||
Areal2 const& areal2,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( geometry::intersects(areal1, areal2) )
|
||||
if ( geometry::intersects(areal1, areal2, strategies) )
|
||||
{
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return linear_to_linear
|
||||
<
|
||||
Areal1, Areal2, Strategy
|
||||
>::apply(areal1, areal2, strategy, false);
|
||||
Areal1, Areal2, Strategies
|
||||
>::apply(areal1, areal2, strategies, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,7 +91,7 @@ template <typename Linear, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Areal, Strategy,
|
||||
linear_tag, areal_tag,
|
||||
linear_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::linear_to_areal
|
||||
@@ -112,7 +104,7 @@ template <typename Areal, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Linear, Strategy,
|
||||
areal_tag, linear_tag,
|
||||
areal_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::linear_to_areal
|
||||
@@ -126,7 +118,7 @@ template <typename Areal1, typename Areal2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal1, Areal2, Strategy,
|
||||
areal_tag, areal_tag,
|
||||
areal_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::areal_to_areal
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2018-2021, 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -10,9 +11,16 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -21,21 +29,16 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
template <typename Linear, typename Box, typename Strategy>
|
||||
template <typename Linear, typename Box, typename Strategies>
|
||||
struct linear_to_box
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Linear, Box, Strategies> return_type;
|
||||
|
||||
template <typename Iterator>
|
||||
static inline return_type apply(Box const& box,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
bool first = true;
|
||||
return_type d_min(0);
|
||||
@@ -44,8 +47,8 @@ struct linear_to_box
|
||||
typedef typename std::iterator_traits<Iterator>::value_type
|
||||
Segment;
|
||||
|
||||
return_type d = dispatch::distance<Segment, Box, Strategy>
|
||||
::apply(*it, box, strategy);
|
||||
return_type d = dispatch::distance<Segment, Box, Strategies>
|
||||
::apply(*it, box, strategies);
|
||||
|
||||
if ( first || d < d_min )
|
||||
{
|
||||
@@ -57,25 +60,25 @@ struct linear_to_box
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( geometry::intersects(linear, box) )
|
||||
{
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return apply(box,
|
||||
geometry::segments_begin(linear),
|
||||
geometry::segments_end(linear),
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type apply(Box const& box,
|
||||
Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(linear, box, strategy);
|
||||
return apply(linear, box, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -10,19 +11,18 @@
|
||||
#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/algorithms/detail/distance/range_to_geometry_rtree.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/algorithms/num_points.hpp>
|
||||
#include <boost/geometry/algorithms/num_segments.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/core/point_type.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>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -33,19 +33,14 @@ namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear1, typename Linear2, typename Strategy>
|
||||
template <typename Linear1, typename Linear2, typename Strategies>
|
||||
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;
|
||||
typedef distance::return_t<Linear1, Linear2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Linear1 const& linear1,
|
||||
Linear2 const& linear2,
|
||||
Strategy const& strategy,
|
||||
Strategies const& strategies,
|
||||
bool = false)
|
||||
{
|
||||
if (geometry::num_points(linear1) == 1)
|
||||
@@ -54,8 +49,8 @@ struct linear_to_linear
|
||||
<
|
||||
typename point_type<Linear1>::type,
|
||||
Linear2,
|
||||
Strategy
|
||||
>::apply(*points_begin(linear1), linear2, strategy);
|
||||
Strategies
|
||||
>::apply(*points_begin(linear1), linear2, strategies);
|
||||
}
|
||||
|
||||
if (geometry::num_points(linear2) == 1)
|
||||
@@ -64,8 +59,8 @@ struct linear_to_linear
|
||||
<
|
||||
typename point_type<Linear2>::type,
|
||||
Linear1,
|
||||
Strategy
|
||||
>::apply(*points_begin(linear2), linear1, strategy);
|
||||
Strategies
|
||||
>::apply(*points_begin(linear2), linear1, strategies);
|
||||
}
|
||||
|
||||
if (geometry::num_segments(linear2) < geometry::num_segments(linear1))
|
||||
@@ -74,11 +69,11 @@ struct linear_to_linear
|
||||
<
|
||||
geometry::segment_iterator<Linear2 const>,
|
||||
Linear1,
|
||||
Strategy
|
||||
Strategies
|
||||
>::apply(geometry::segments_begin(linear2),
|
||||
geometry::segments_end(linear2),
|
||||
linear1,
|
||||
strategy);
|
||||
strategies);
|
||||
|
||||
}
|
||||
|
||||
@@ -86,11 +81,11 @@ struct linear_to_linear
|
||||
<
|
||||
geometry::segment_iterator<Linear1 const>,
|
||||
Linear2,
|
||||
Strategy
|
||||
Strategies
|
||||
>::apply(geometry::segments_begin(linear1),
|
||||
geometry::segments_end(linear1),
|
||||
linear2,
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,12 +98,12 @@ struct linear_to_linear
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Linear1, typename Linear2, typename Strategy>
|
||||
template <typename Linear1, typename Linear2, typename Strategy, typename StrategyTag>
|
||||
struct distance
|
||||
<
|
||||
Linear1, Linear2, Strategy,
|
||||
linear_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
linear_tag, linear_tag,
|
||||
StrategyTag, false
|
||||
> : detail::distance::linear_to_linear
|
||||
<
|
||||
Linear1, Linear2, Strategy
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -10,7 +12,14 @@
|
||||
#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/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
@@ -18,13 +27,6 @@
|
||||
#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
|
||||
{
|
||||
@@ -34,139 +36,118 @@ namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategies>
|
||||
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;
|
||||
typedef distance::return_t<MultiPoint1, MultiPoint2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (boost::size(multipoint2) < boost::size(multipoint1))
|
||||
|
||||
{
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint2 const>::type,
|
||||
MultiPoint1,
|
||||
Strategy
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
multipoint1,
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint1 const>::type,
|
||||
MultiPoint2,
|
||||
Strategy
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint1),
|
||||
boost::end(multipoint1),
|
||||
multipoint2,
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, typename Strategy>
|
||||
template <typename MultiPoint, typename Linear, typename Strategies>
|
||||
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)
|
||||
static inline auto apply(MultiPoint const& multipoint,
|
||||
Linear const& linear,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return detail::distance::point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint const>::type,
|
||||
Linear,
|
||||
Strategy
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
linear,
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
MultiPoint const& multipoint,
|
||||
Strategy const& strategy)
|
||||
static inline auto apply(Linear const& linear,
|
||||
MultiPoint const& multipoint,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(multipoint, linear, strategy);
|
||||
return apply(multipoint, linear, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Strategy>
|
||||
template <typename MultiPoint, typename Areal, typename Strategies>
|
||||
class multipoint_to_areal
|
||||
{
|
||||
private:
|
||||
struct not_covered_by_areal
|
||||
struct covered_by_areal
|
||||
{
|
||||
not_covered_by_areal(Areal const& areal)
|
||||
: m_areal(areal)
|
||||
covered_by_areal(Areal const& areal, Strategies const& strategy)
|
||||
: m_areal(areal), m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
inline bool apply(Point const& point) const
|
||||
inline bool operator()(Point const& point) const
|
||||
{
|
||||
return !geometry::covered_by(point, m_areal);
|
||||
return geometry::covered_by(point, m_areal, m_strategy);
|
||||
}
|
||||
|
||||
Areal const& m_areal;
|
||||
Strategies const& m_strategy;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<MultiPoint>::type,
|
||||
typename point_type<Areal>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<MultiPoint, Areal, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint const& multipoint,
|
||||
Areal const& areal,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
not_covered_by_areal predicate(areal);
|
||||
covered_by_areal predicate(areal, strategies);
|
||||
|
||||
if (check_iterator_range
|
||||
<
|
||||
not_covered_by_areal, false
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
predicate))
|
||||
if (! boost::empty(multipoint) &&
|
||||
std::none_of(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
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
areal,
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
static inline return_type apply(Areal const& areal,
|
||||
MultiPoint const& multipoint,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(multipoint, areal, strategy);
|
||||
return apply(multipoint, areal, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2019.
|
||||
// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
|
||||
// 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
|
||||
@@ -22,10 +22,22 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/is_same.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>
|
||||
@@ -34,20 +46,11 @@
|
||||
#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/relate/services.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -58,12 +61,28 @@ namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename P1, typename P2, typename Strategy>
|
||||
template
|
||||
<
|
||||
typename P1, typename P2, typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
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)
|
||||
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);
|
||||
@@ -71,52 +90,101 @@ struct point_to_point
|
||||
};
|
||||
|
||||
|
||||
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 Strategy
|
||||
typename Strategies
|
||||
>
|
||||
class point_to_range
|
||||
{
|
||||
private:
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type comparable_strategy;
|
||||
typedef distance::strategy_t<Point, Range, Strategies> strategy_type;
|
||||
|
||||
typedef detail::closest_feature::point_to_point_range
|
||||
<
|
||||
Point, Range, Closure, comparable_strategy
|
||||
Point, Range, Closure
|
||||
> point_to_point_range;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename boost::range_value<Range>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Point, Range, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point, Range const& range,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return_type const zero = return_type(0);
|
||||
|
||||
if (boost::size(range) == 0)
|
||||
{
|
||||
return zero;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
namespace sds = strategy::distance::services;
|
||||
|
||||
typename sds::return_type
|
||||
<
|
||||
comparable_strategy,
|
||||
Point,
|
||||
typename point_type<Range>::type
|
||||
>::type cd_min;
|
||||
distance::creturn_t<Point, Range, Strategies> cd_min;
|
||||
|
||||
std::pair
|
||||
<
|
||||
@@ -126,18 +194,18 @@ public:
|
||||
= point_to_point_range::apply(point,
|
||||
boost::begin(range),
|
||||
boost::end(range),
|
||||
sds::get_comparable
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy),
|
||||
strategy_type
|
||||
>::apply(strategies.distance(point, range)),
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<Strategy>::value
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
strategy.apply(point, *it_pair.first, *it_pair.second);
|
||||
strategies.distance(point, range).apply(point, *it_pair.first, *it_pair.second);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -147,29 +215,25 @@ template
|
||||
typename Point,
|
||||
typename Ring,
|
||||
closure_selector Closure,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
struct point_to_ring
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, Point, typename point_type<Ring>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Point, Ring, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
Ring const& ring,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// TODO: pass strategy
|
||||
if (within::within_point_geometry(point, ring))
|
||||
if (within::within_point_geometry(point, ring, strategies))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return point_to_range
|
||||
<
|
||||
Point, Ring, closure<Ring>::value, Strategy
|
||||
>::apply(point, ring, strategy);
|
||||
Point, Ring, closure<Ring>::value, Strategies
|
||||
>::apply(point, ring, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -179,20 +243,17 @@ template
|
||||
typename Point,
|
||||
typename Polygon,
|
||||
closure_selector Closure,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
class point_to_polygon
|
||||
{
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, Point, typename point_type<Polygon>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Point, Polygon, Strategies> return_type;
|
||||
|
||||
private:
|
||||
typedef point_to_range
|
||||
<
|
||||
Point, typename ring_type<Polygon>::type, Closure, Strategy
|
||||
Point, typename ring_type<Polygon>::type, Closure, Strategies
|
||||
> per_ring;
|
||||
|
||||
struct distance_to_interior_rings
|
||||
@@ -201,31 +262,29 @@ private:
|
||||
static inline return_type apply(Point const& point,
|
||||
InteriorRingIterator first,
|
||||
InteriorRingIterator last,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
for (InteriorRingIterator it = first; it != last; ++it)
|
||||
{
|
||||
// TODO: pass strategy
|
||||
if (within::within_point_geometry(point, *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, strategy);
|
||||
return per_ring::apply(point, *it, strategies);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
template <typename InteriorRings>
|
||||
static inline return_type apply(Point const& point,
|
||||
InteriorRings const& interior_rings,
|
||||
Strategy const& strategy)
|
||||
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),
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -233,20 +292,20 @@ private:
|
||||
public:
|
||||
static inline return_type apply(Point const& point,
|
||||
Polygon const& polygon,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// TODO: pass strategy
|
||||
if (! within::covered_by_point_geometry(point, exterior_ring(polygon)))
|
||||
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), strategy);
|
||||
return per_ring::apply(point, exterior_ring(polygon), strategies);
|
||||
}
|
||||
|
||||
// Check interior rings
|
||||
return distance_to_interior_rings::apply(point,
|
||||
interior_rings(polygon),
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -255,8 +314,8 @@ template
|
||||
<
|
||||
typename Point,
|
||||
typename MultiGeometry,
|
||||
typename Strategy,
|
||||
bool CheckCoveredBy = boost::is_same
|
||||
typename Strategies,
|
||||
bool CheckCoveredBy = std::is_same
|
||||
<
|
||||
typename tag<MultiGeometry>::type, multi_polygon_tag
|
||||
>::value
|
||||
@@ -266,41 +325,35 @@ 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 typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename point_type<MultiGeometry>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Point, MultiGeometry, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
MultiGeometry const& multigeometry,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
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;
|
||||
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),
|
||||
sds::get_comparable
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy),
|
||||
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>::value
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd
|
||||
:
|
||||
@@ -311,38 +364,32 @@ public:
|
||||
<
|
||||
typename selector_type::iterator_type
|
||||
>::value_type,
|
||||
Strategy
|
||||
>::apply(point, *it_min, strategy);
|
||||
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 Strategy>
|
||||
struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
|
||||
template <typename Point, typename MultiPolygon, typename Strategies>
|
||||
struct point_to_multigeometry<Point, MultiPolygon, Strategies, true>
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename point_type<MultiPolygon>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Point, MultiPolygon, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
MultiPolygon const& multipolygon,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// TODO: pass strategy
|
||||
if (within::covered_by_point_geometry(point, multipolygon))
|
||||
if (within::covered_by_point_geometry(point, multipolygon, strategies))
|
||||
{
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return point_to_multigeometry
|
||||
<
|
||||
Point, MultiPolygon, Strategy, false
|
||||
>::apply(point, multipolygon, strategy);
|
||||
Point, MultiPolygon, Strategies, false
|
||||
>::apply(point, multipolygon, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -358,7 +405,6 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// Point-point
|
||||
template <typename P1, typename P2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
@@ -368,7 +414,6 @@ struct distance
|
||||
{};
|
||||
|
||||
|
||||
// Point-line version 2, where point-segment strategy is specified
|
||||
template <typename Point, typename Linestring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
@@ -378,7 +423,6 @@ struct distance
|
||||
{};
|
||||
|
||||
|
||||
// Point-ring , where point-segment strategy is specified
|
||||
template <typename Point, typename Ring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
@@ -391,7 +435,6 @@ struct distance
|
||||
{};
|
||||
|
||||
|
||||
// Point-polygon , where point-segment strategy is specified
|
||||
template <typename Point, typename Polygon, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
@@ -404,29 +447,13 @@ struct distance
|
||||
{};
|
||||
|
||||
|
||||
// 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]);
|
||||
}
|
||||
};
|
||||
> : detail::distance::point_to_segment<Point, Segment, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
@@ -434,18 +461,8 @@ 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);
|
||||
}
|
||||
};
|
||||
> : detail::distance::point_to_box<Point, Box, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename MultiPoint, typename Strategy>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Boost.Geometry
|
||||
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -13,18 +13,18 @@
|
||||
#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>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.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
|
||||
@@ -40,7 +40,7 @@ template
|
||||
<
|
||||
typename PointOrSegmentIterator,
|
||||
typename Geometry,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
class point_or_segment_range_to_geometry_rtree
|
||||
{
|
||||
@@ -54,37 +54,27 @@ private:
|
||||
|
||||
typedef detail::closest_feature::range_to_range_rtree range_to_range;
|
||||
|
||||
typedef distance::strategy_t<point_or_segment_type, Geometry, Strategies> strategy_type;
|
||||
|
||||
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;
|
||||
typedef distance::return_t<point_or_segment_type, Geometry, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(PointOrSegmentIterator first,
|
||||
PointOrSegmentIterator last,
|
||||
Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
namespace sds = strategy::distance::services;
|
||||
|
||||
BOOST_GEOMETRY_ASSERT( first != last );
|
||||
|
||||
if ( geometry::has_one_element(first, last) )
|
||||
if ( detail::has_one_element(first, last) )
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
point_or_segment_type, Geometry, Strategy
|
||||
>::apply(*first, geometry, strategy);
|
||||
point_or_segment_type, Geometry, Strategies
|
||||
>::apply(*first, geometry, strategies);
|
||||
}
|
||||
|
||||
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;
|
||||
distance::creturn_t<point_or_segment_type, Geometry, Strategies> cd_min;
|
||||
|
||||
std::pair
|
||||
<
|
||||
@@ -95,28 +85,25 @@ public:
|
||||
last,
|
||||
selector_type::begin(geometry),
|
||||
selector_type::end(geometry),
|
||||
sds::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy),
|
||||
strategies,
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<Strategy>::value
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
dispatch::distance
|
||||
<
|
||||
point_or_segment_type,
|
||||
point_or_segment_type,
|
||||
typename std::iterator_traits
|
||||
<
|
||||
typename selector_type::iterator_type
|
||||
>::value_type,
|
||||
Strategy
|
||||
Strategies
|
||||
>::apply(closest_features.first,
|
||||
*closest_features.second,
|
||||
strategy);
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2019 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2023 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
|
||||
@@ -13,14 +13,23 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#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/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
@@ -29,16 +38,6 @@
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/util/calculation_type.hpp>
|
||||
@@ -50,7 +49,6 @@
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -60,26 +58,24 @@ namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
// TODO: Take strategy
|
||||
template <typename Segment, typename Box>
|
||||
inline bool intersects_segment_box(Segment const& segment, Box const& box)
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
inline bool intersects_segment_box(Segment const& segment, Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Segment, Box
|
||||
>::type strategy_type;
|
||||
|
||||
return ! detail::disjoint::disjoint_segment_box::apply(segment, box,
|
||||
strategy_type());
|
||||
return ! detail::disjoint::disjoint_segment_box::apply(segment, box, strategy);
|
||||
}
|
||||
|
||||
// TODO: segment_to_box_2D_generic is not used anymore. Remove?
|
||||
|
||||
// TODO: Furthermore this utility can potentially use different strategy than
|
||||
// the one that was passed into bg::distance() but it seems this is by design.
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename Strategy,
|
||||
bool UsePointBoxStrategy = false
|
||||
typename Strategies,
|
||||
bool UsePointBoxStrategy = false // use only PointSegment strategy
|
||||
>
|
||||
class segment_to_box_2D_generic
|
||||
{
|
||||
@@ -87,46 +83,29 @@ private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename Strategy::distance_ps_strategy::type
|
||||
>::type comparable_strategy;
|
||||
typedef distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
|
||||
|
||||
typedef detail::closest_feature::point_to_point_range
|
||||
<
|
||||
segment_point,
|
||||
std::vector<box_point>,
|
||||
open,
|
||||
comparable_strategy
|
||||
open
|
||||
> 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;
|
||||
// TODO: Or should the return type be defined by sb_strategy_type?
|
||||
typedef distance::return_t<box_point, Segment, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy,
|
||||
Strategies const& strategies,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && intersects_segment_box(segment, box))
|
||||
if (check_intersection && intersects_segment_box(segment, box, strategies))
|
||||
{
|
||||
return 0;
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
comparable_strategy cstrategy =
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
typename Strategy::distance_ps_strategy::type
|
||||
>::apply(strategy.get_distance_ps_strategy());
|
||||
|
||||
// get segment points
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
@@ -135,8 +114,15 @@ public:
|
||||
// get box points
|
||||
std::vector<box_point> box_points(4);
|
||||
detail::assign_box_corners_oriented<true>(box, box_points);
|
||||
|
||||
comparable_return_type cd[6];
|
||||
|
||||
ps_strategy_type const strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
|
||||
auto const cstrategy = strategy::distance::services::get_comparable
|
||||
<
|
||||
ps_strategy_type
|
||||
>::apply(strategy);
|
||||
|
||||
distance::creturn_t<box_point, Segment, Strategies> cd[6];
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
|
||||
@@ -168,19 +154,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<ps_strategy_type>::value))
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
return strategy.get_distance_ps_strategy().apply(box_points[imin], p[0], p[1]);
|
||||
return strategy.apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int bimin = imin - 4;
|
||||
return strategy.get_distance_ps_strategy().apply(p[bimin],
|
||||
return strategy.apply(p[bimin],
|
||||
*bit_min[bimin].first,
|
||||
*bit_min[bimin].second);
|
||||
}
|
||||
@@ -192,57 +178,31 @@ template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename Strategy
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box_2D_generic<Segment, Box, Strategy, true>
|
||||
class segment_to_box_2D_generic<Segment, Box, Strategies, true> // Use both PointSegment and PointBox strategies
|
||||
{
|
||||
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;
|
||||
typedef distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
|
||||
typedef distance::strategy_t<segment_point, Box, Strategies> pb_strategy_type;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy, segment_point, box_point
|
||||
>::type return_type;
|
||||
// TODO: Or should the return type be defined by sb_strategy_type?
|
||||
typedef distance::return_t<box_point, Segment, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy,
|
||||
Strategies const& strategies,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && intersects_segment_box(segment, box))
|
||||
if (check_intersection && intersects_segment_box(segment, box, strategies))
|
||||
{
|
||||
return 0;
|
||||
return return_type(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]);
|
||||
@@ -251,15 +211,28 @@ public:
|
||||
// get box points
|
||||
std::vector<box_point> box_points(4);
|
||||
detail::assign_box_corners_oriented<true>(box, box_points);
|
||||
|
||||
comparable_return_type cd[6];
|
||||
|
||||
distance::creturn_t<box_point, Segment, Strategies> cd[6];
|
||||
|
||||
ps_strategy_type ps_strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
auto const ps_cstrategy = strategy::distance::services::get_comparable
|
||||
<
|
||||
ps_strategy_type
|
||||
>::apply(ps_strategy);
|
||||
boost::ignore_unused(ps_strategy, ps_cstrategy);
|
||||
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
|
||||
cd[i] = ps_cstrategy.apply(box_points[i], p[0], p[1]);
|
||||
}
|
||||
|
||||
point_box_comparable_strategy pb_cstrategy;
|
||||
boost::ignore_unused(pb_cstrategy);
|
||||
pb_strategy_type const pb_strategy = strategies.distance(dummy_point(), dummy_box());
|
||||
auto const pb_cstrategy = strategy::distance::services::get_comparable
|
||||
<
|
||||
pb_strategy_type
|
||||
>::apply(pb_strategy);
|
||||
boost::ignore_unused(pb_strategy, pb_cstrategy);
|
||||
|
||||
cd[4] = pb_cstrategy.apply(p[0], box);
|
||||
cd[5] = pb_cstrategy.apply(p[1], box);
|
||||
|
||||
@@ -272,18 +245,23 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (is_comparable<Strategy>::value)
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
strategy.apply(box_points[imin], p[0], p[1]);
|
||||
if (is_comparable<ps_strategy_type>::value)
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
return ps_strategy.apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return point_box_strategy().apply(p[imin - 4], box);
|
||||
if (is_comparable<pb_strategy_type>::value)
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
return pb_strategy.apply(p[imin - 4], box);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -296,7 +274,7 @@ template
|
||||
typename ReturnType,
|
||||
typename SegmentPoint,
|
||||
typename BoxPoint,
|
||||
typename SBStrategy
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box_2D
|
||||
{
|
||||
@@ -355,10 +333,8 @@ private:
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& bottom_right,
|
||||
BoxPoint const& top_right,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(sb_strategy);
|
||||
|
||||
// the implementation below is written for non-negative slope
|
||||
// segments
|
||||
//
|
||||
@@ -369,8 +345,7 @@ private:
|
||||
|
||||
LessEqual less_equal;
|
||||
|
||||
typename SBStrategy::distance_ps_strategy::type ps_strategy =
|
||||
sb_strategy.get_distance_ps_strategy();
|
||||
auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
|
||||
if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
|
||||
{
|
||||
@@ -412,19 +387,19 @@ private:
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(sb_strategy);
|
||||
return apply(p0, p1, p0, top_left, sb_strategy);
|
||||
return apply(p0, p1, p0, top_left, strategies);
|
||||
}
|
||||
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
SegmentPoint const& p_max,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(sb_strategy);
|
||||
auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
LessEqual less_equal;
|
||||
|
||||
@@ -432,22 +407,21 @@ private:
|
||||
// then compute the vertical (i.e. meridian for spherical) distance
|
||||
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
|
||||
{
|
||||
ReturnType diff =
|
||||
sb_strategy.get_distance_ps_strategy().vertical_or_meridian(
|
||||
ReturnType diff = ps_strategy.vertical_or_meridian(
|
||||
geometry::get_as_radian<1>(p_max),
|
||||
geometry::get_as_radian<1>(top_left));
|
||||
|
||||
return strategy::distance::services::result_from_distance
|
||||
<
|
||||
SBStrategy, SegmentPoint, BoxPoint
|
||||
>::apply(sb_strategy, math::abs(diff));
|
||||
std::remove_const_t<decltype(ps_strategy)>,
|
||||
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(sb_strategy.get_distance_ps_strategy().
|
||||
apply(top_left, p0, p1));
|
||||
return cast::apply(ps_strategy.apply(top_left, p0, p1));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -460,7 +434,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
SBStrategy const& sb_strategy,
|
||||
Strategies const& strategies,
|
||||
ReturnType& result)
|
||||
{
|
||||
// p0 lies to the right of the box
|
||||
@@ -470,7 +444,7 @@ private:
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, bottom_right, top_right,
|
||||
sb_strategy);
|
||||
strategies);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -481,7 +455,7 @@ private:
|
||||
<
|
||||
typename other_compare<LessEqual>::type
|
||||
>::apply(p1, p0, top_left, bottom_left,
|
||||
sb_strategy);
|
||||
strategies);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -498,7 +472,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
SBStrategy const& sb_strategy,
|
||||
Strategies const& strategies,
|
||||
ReturnType& result)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> GreaterEqual;
|
||||
@@ -506,13 +480,20 @@ private:
|
||||
// the segment lies below the box
|
||||
if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
|
||||
{
|
||||
auto const sb_strategy = strategies.distance(dummy_segment(), dummy_box());
|
||||
|
||||
// TODO: this strategy calls this algorithm's again, specifically:
|
||||
// geometry::detail::distance::segment_to_box_2D<>::call_above_of_box
|
||||
// If possible rewrite them to avoid this.
|
||||
// For now just pass umbrella strategy.
|
||||
result = sb_strategy.template segment_below_of_box
|
||||
<
|
||||
LessEqual,
|
||||
ReturnType
|
||||
>(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right);
|
||||
bottom_left, bottom_right,
|
||||
strategies);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -522,11 +503,11 @@ private:
|
||||
result = (std::min)(above_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, top_left, sb_strategy),
|
||||
>::apply(p0, p1, top_left, strategies),
|
||||
above_of_box
|
||||
<
|
||||
GreaterEqual
|
||||
>::apply(p1, p0, top_right, sb_strategy));
|
||||
>::apply(p1, p0, top_right, strategies));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -539,28 +520,23 @@ private:
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& corner1,
|
||||
BoxPoint const& corner2,
|
||||
SBStrategy const& sb_strategy,
|
||||
Strategies const& strategies,
|
||||
ReturnType& result)
|
||||
{
|
||||
typedef typename geometry::strategy::side::services::default_strategy
|
||||
<
|
||||
typename geometry::cs_tag<SegmentPoint>::type
|
||||
>::type side;
|
||||
auto const side_strategy = strategies.side();
|
||||
auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
ReturnType diff1 = cast::apply(geometry::get<1>(p1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
|
||||
typename SBStrategy::distance_ps_strategy::type ps_strategy =
|
||||
sb_strategy.get_distance_ps_strategy();
|
||||
|
||||
int sign = diff1 < 0 ? -1 : 1;
|
||||
if (side::apply(p0, p1, corner1) * sign < 0)
|
||||
if (side_strategy.apply(p0, p1, corner1) * sign < 0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
|
||||
return true;
|
||||
}
|
||||
if (side::apply(p0, p1, corner2) * sign > 0)
|
||||
if (side_strategy.apply(p0, p1, corner2) * sign > 0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner2, p0, p1));
|
||||
return true;
|
||||
@@ -576,7 +552,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, true> less_equal;
|
||||
|
||||
@@ -596,7 +572,7 @@ private:
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
sb_strategy, result))
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -606,14 +582,14 @@ private:
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
sb_strategy, result))
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
top_left, bottom_right,
|
||||
sb_strategy, result))
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -630,7 +606,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> greater_equal;
|
||||
|
||||
@@ -647,7 +623,7 @@ private:
|
||||
greater_equal
|
||||
>::apply(p0, p1,
|
||||
bottom_left, bottom_right, top_left, top_right,
|
||||
sb_strategy, result))
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -657,14 +633,14 @@ private:
|
||||
greater_equal
|
||||
>::apply(p1, p0,
|
||||
top_right, top_left, bottom_right, bottom_left,
|
||||
sb_strategy, result))
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
bottom_left, top_right,
|
||||
sb_strategy, result))
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -680,9 +656,9 @@ public:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1)
|
||||
BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, Strategies>()(p0, p1))
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1) );
|
||||
|
||||
@@ -692,13 +668,13 @@ public:
|
||||
return negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
sb_strategy);
|
||||
strategies);
|
||||
}
|
||||
|
||||
return non_negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
sb_strategy);
|
||||
strategies);
|
||||
}
|
||||
|
||||
template <typename LessEqual>
|
||||
@@ -706,18 +682,18 @@ public:
|
||||
SegmentPoint const& p1,
|
||||
SegmentPoint const& p_max,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, sb_strategy);
|
||||
return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, strategies);
|
||||
}
|
||||
|
||||
template <typename LessEqual>
|
||||
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return above_of_box<LessEqual>::apply(p0, p1, top_left, sb_strategy);
|
||||
return above_of_box<LessEqual>::apply(p0, p1, top_left, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -728,7 +704,7 @@ template
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename std::size_t Dimension,
|
||||
typename SBStrategy
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box
|
||||
: not_implemented<Segment, Box>
|
||||
@@ -739,87 +715,56 @@ template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename SBStrategy
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box<Segment, Box, 2, SBStrategy>
|
||||
class segment_to_box<Segment, Box, 2, Strategies>
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
typedef distance::strategy_t<Segment, Box, Strategies> strategy_type;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
SBStrategy
|
||||
>::type ps_comparable_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
ps_comparable_strategy, segment_point, box_point
|
||||
>::type comparable_return_type;
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
SBStrategy, segment_point, box_point
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Segment, Box, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
SBStrategy const& sb_strategy)
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
if (detail::equals::equals_point_point(p[0], p[1],
|
||||
sb_strategy.get_equals_point_point_strategy()))
|
||||
if (detail::equals::equals_point_point(p[0], p[1], strategies))
|
||||
{
|
||||
typedef typename boost::mpl::if_
|
||||
<
|
||||
boost::is_same
|
||||
<
|
||||
ps_comparable_strategy,
|
||||
SBStrategy
|
||||
>,
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
segment_point, Box
|
||||
>::type
|
||||
>::type,
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
segment_point, Box
|
||||
>::type
|
||||
>::type point_box_strategy_type;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
segment_point,
|
||||
Box,
|
||||
point_box_strategy_type
|
||||
>::apply(p[0], box, point_box_strategy_type());
|
||||
Strategies
|
||||
>::apply(p[0], box, strategies);
|
||||
}
|
||||
|
||||
box_point top_left, top_right, bottom_left, bottom_right;
|
||||
detail::assign_box_corners(box, bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
|
||||
SBStrategy::mirror(p[0], p[1],
|
||||
bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
strategy_type::mirror(p[0], p[1],
|
||||
bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
|
||||
if (geometry::less<segment_point>()(p[0], p[1]))
|
||||
typedef geometry::less<segment_point, -1, Strategies> less_type;
|
||||
if (less_type()(p[0], p[1]))
|
||||
{
|
||||
return segment_to_box_2D
|
||||
<
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
SBStrategy
|
||||
Strategies
|
||||
>::apply(p[0], p[1],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
sb_strategy);
|
||||
strategies);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -828,10 +773,10 @@ public:
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
SBStrategy
|
||||
Strategies
|
||||
>::apply(p[1], p[0],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
sb_strategy);
|
||||
strategies);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -846,24 +791,15 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
template <typename Segment, typename Box, typename Strategies>
|
||||
struct distance
|
||||
<
|
||||
Segment, Box, Strategy, segment_tag, box_tag,
|
||||
Segment, Box, Strategies, segment_tag, box_tag,
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Segment>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type return_type;
|
||||
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
static inline auto apply(Segment const& segment, Box const& box,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
assert_dimension_equal<Segment, Box>();
|
||||
|
||||
@@ -872,8 +808,8 @@ struct distance
|
||||
Segment,
|
||||
Box,
|
||||
dimension<Segment>::value,
|
||||
Strategy
|
||||
>::apply(segment, box, strategy);
|
||||
Strategies
|
||||
>::apply(segment, box, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -15,20 +16,19 @@
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.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/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>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -42,35 +42,18 @@ namespace detail { namespace distance
|
||||
|
||||
|
||||
// compute segment-segment distance
|
||||
template<typename Segment1, typename Segment2, typename Strategy>
|
||||
template<typename Segment1, typename Segment2, typename Strategies>
|
||||
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;
|
||||
typedef distance::strategy_t<Segment1, Segment2, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Segment1>::type,
|
||||
typename point_type<Segment2>::type
|
||||
>::type return_type;
|
||||
typedef distance::return_t<Segment1, Segment2, Strategies> return_type;
|
||||
|
||||
static inline return_type
|
||||
apply(Segment1 const& segment1, Segment2 const& segment2,
|
||||
Strategy const& strategy)
|
||||
static inline return_type apply(Segment1 const& segment1, Segment2 const& segment2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (geometry::intersects(segment1, segment2))
|
||||
if (geometry::intersects(segment1, segment2, strategies))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -83,13 +66,14 @@ public:
|
||||
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);
|
||||
strategy_type const strategy = strategies.distance(segment1, segment2);
|
||||
|
||||
comparable_return_type d[4];
|
||||
auto const cstrategy = strategy::distance::services::get_comparable
|
||||
<
|
||||
strategy_type
|
||||
>::apply(strategy);
|
||||
|
||||
distance::creturn_t<Segment1, Segment2, Strategies> 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]);
|
||||
@@ -98,7 +82,7 @@ public:
|
||||
std::size_t imin = std::distance(boost::addressof(d[0]),
|
||||
std::min_element(d, d + 4));
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<strategy_type>::value))
|
||||
{
|
||||
return d[imin];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_STRATEGY_UTILS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_STRATEGY_UTILS_HPP
|
||||
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Strategies>
|
||||
using strategy_t = decltype(
|
||||
std::declval<Strategies>().distance(std::declval<Geometry1>(), std::declval<Geometry2>()));
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Strategies>
|
||||
using return_t = typename strategy::distance::services::return_type
|
||||
<
|
||||
strategy_t<Geometry1, Geometry2, Strategies>,
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type
|
||||
>::type;
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Strategies>
|
||||
using cstrategy_t = typename strategy::distance::services::comparable_type
|
||||
<
|
||||
strategy_t<Geometry1, Geometry2, Strategies>
|
||||
>::type;
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Strategies>
|
||||
using creturn_t = typename strategy::distance::services::return_type
|
||||
<
|
||||
cstrategy_t<Geometry1, Geometry2, Strategies>,
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type
|
||||
>::type;
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_STRATEGY_UTILS_HPP
|
||||
@@ -0,0 +1,56 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DUMMY_GEOMETRIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DUMMY_GEOMETRIES_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct dummy_point {};
|
||||
struct dummy_segment {};
|
||||
struct dummy_box {};
|
||||
struct dummy_linestring {};
|
||||
struct dummy_ring {};
|
||||
struct dummy_polygon {};
|
||||
struct dummy_multi_point {};
|
||||
struct dummy_multi_linestring {};
|
||||
struct dummy_multi_polygon {};
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <> struct tag<geometry::detail::dummy_point> { typedef point_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_segment> { typedef segment_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_box> { typedef box_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_linestring> { typedef linestring_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_ring> { typedef ring_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_polygon> { typedef polygon_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_multi_point> { typedef multi_point_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_multi_linestring> { typedef multi_linestring_tag type; };
|
||||
template <> struct tag<geometry::detail::dummy_multi_polygon> { typedef multi_polygon_tag type; };
|
||||
|
||||
} // namespace traits
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DUMMY_GEOMETRIES_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2018 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2018-2021 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
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -29,6 +31,24 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct envelope_hole
|
||||
{
|
||||
template <typename Range, typename Box, typename Strategies>
|
||||
static inline void apply(Range const& range, Box& mbr, Strategies const& strategies)
|
||||
{
|
||||
// Reverse holes to avoid calculating the envelope for the outside
|
||||
// in spherical and geographic coordinate systems
|
||||
detail::clockwise_view
|
||||
<
|
||||
Range const,
|
||||
geometry::point_order<Range>::value == counterclockwise
|
||||
? clockwise : counterclockwise
|
||||
> view(range);
|
||||
strategies.envelope(range, mbr).apply(view, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
struct envelope_polygon
|
||||
{
|
||||
template <typename Polygon, typename Box, typename Strategy>
|
||||
@@ -39,11 +59,14 @@ struct envelope_polygon
|
||||
|
||||
if (geometry::is_empty(ext_ring))
|
||||
{
|
||||
// use dummy multi polygon to get the strategy because there is no multi ring concept
|
||||
using strategy_t = decltype(strategy.envelope(detail::dummy_multi_polygon(),
|
||||
detail::dummy_box()));
|
||||
// if the exterior ring is empty, consider the interior rings
|
||||
envelope_multi_range
|
||||
<
|
||||
envelope_range
|
||||
>::apply(interior_rings(polygon), mbr, strategy);
|
||||
envelope_hole
|
||||
>::template apply<strategy_t>(interior_rings(polygon), mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021, 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
|
||||
@@ -19,11 +19,9 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_box.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -39,9 +37,10 @@ template <typename Box>
|
||||
struct envelope<Box, box_tag>
|
||||
{
|
||||
template<typename BoxIn, typename BoxOut, typename Strategy>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr, Strategy const& )
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr, Strategy const& strategy)
|
||||
{
|
||||
Strategy::apply(box_in, mbr);
|
||||
using strategy_t = decltype(strategy.envelope(box_in, mbr));
|
||||
strategy_t::apply(box_in, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, 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_ENVELOPE_GEOMETRY_COLLECTION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/visit.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Collection>
|
||||
struct envelope<Collection, geometry_collection_tag>
|
||||
{
|
||||
template <typename Geometry, typename Box, typename Strategies>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& mbr,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
using strategy_t = decltype(strategies.envelope(geometry, mbr));
|
||||
|
||||
typename strategy_t::template state<Box> state;
|
||||
detail::visit_breadth_first([&](auto const& g)
|
||||
{
|
||||
if (! geometry::is_empty(g))
|
||||
{
|
||||
Box b;
|
||||
envelope<util::remove_cref_t<decltype(g)>>::apply(g, b, strategies);
|
||||
strategy_t::apply(state, b);
|
||||
}
|
||||
return true;
|
||||
}, geometry);
|
||||
strategy_t::result(state, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
|
||||
@@ -4,11 +4,11 @@
|
||||
// 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.
|
||||
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021, 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.
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/geometry_collection.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>
|
||||
@@ -36,4 +37,8 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/envelope/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/envelope/geographic.hpp>
|
||||
#include <boost/geometry/strategies/envelope/spherical.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021, 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
|
||||
@@ -22,22 +22,22 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/visit.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/envelope.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/envelope/services.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -46,31 +46,49 @@ namespace boost { namespace geometry
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct envelope
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
template <typename Geometry, typename Box>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
dispatch::envelope<Geometry>::apply(geometry, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
template <typename Strategy>
|
||||
struct envelope<Strategy, false>
|
||||
{
|
||||
template <typename Geometry, typename Box>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using strategies::envelope::services::strategy_converter;
|
||||
return dispatch::envelope
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, box, strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct envelope<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry, typename Box>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::envelope::services::default_strategy
|
||||
typedef typename strategies::envelope::services::default_strategy
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
typename cs_tag<Geometry>::type,
|
||||
typename select_most_precise
|
||||
<
|
||||
typename coordinate_type<Geometry>::type,
|
||||
typename coordinate_type<Box>::type
|
||||
>::type
|
||||
Geometry, Box
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
|
||||
@@ -79,10 +97,10 @@ struct envelope
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
namespace resolve_variant
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct envelope
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
@@ -93,43 +111,28 @@ struct envelope
|
||||
concepts::check<Geometry const>();
|
||||
concepts::check<Box>();
|
||||
|
||||
resolve_strategy::envelope<Geometry>::apply(geometry, box, strategy);
|
||||
resolve_strategy::envelope<Strategy>::apply(geometry, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
struct envelope<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
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);
|
||||
envelope<util::remove_cref_t<decltype(g)>>::apply(g, box, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope (with strategy)}
|
||||
@@ -152,7 +155,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
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);
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -173,7 +176,7 @@ inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strateg
|
||||
template<typename Geometry, typename Box>
|
||||
inline void envelope(Geometry const& geometry, Box& mbr)
|
||||
{
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +202,7 @@ 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);
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
return mbr;
|
||||
}
|
||||
|
||||
@@ -222,7 +225,7 @@ template<typename Box, typename Geometry>
|
||||
inline Box return_envelope(Geometry const& geometry)
|
||||
{
|
||||
Box mbr;
|
||||
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
return mbr;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace detail { namespace envelope
|
||||
@@ -38,7 +38,7 @@ struct intersects_antimeridian
|
||||
<
|
||||
CoordinateType, Units
|
||||
> constants;
|
||||
|
||||
|
||||
return
|
||||
math::equals(math::abs(lat1), constants::max_latitude())
|
||||
||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2020.
|
||||
// Modifications copyright (c) 2015-2020, 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
|
||||
@@ -25,11 +25,6 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2020, 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
|
||||
@@ -17,10 +17,6 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_multipoint.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_multipoint.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -34,9 +30,11 @@ template <typename MultiPoint>
|
||||
struct envelope<MultiPoint, multi_point_tag>
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& )
|
||||
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
Strategy::apply(multipoint, mbr);
|
||||
// strategy.envelope(multipoint, mbr).apply(multipoint, mbr);
|
||||
using strategy_t = decltype(strategy.envelope(multipoint, mbr));
|
||||
strategy_t::apply(multipoint, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2020.
|
||||
// Modifications copyright (c) 2015-2020, 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
|
||||
@@ -22,11 +22,6 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -38,9 +33,11 @@ namespace detail { namespace envelope
|
||||
struct envelope_point
|
||||
{
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const& )
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
Strategy::apply(point, mbr);
|
||||
// strategy.envelope(point, mbr).apply(point, mbr);
|
||||
using strategy_t = decltype(strategy.envelope(point, mbr));
|
||||
strategy_t::apply(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user