mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-05 23:17:52 +00:00
Added thirdparty: boost library
This commit is contained in:
+285
@@ -0,0 +1,285 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014-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.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
|
||||
|
||||
|
||||
#include <boost/range/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/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/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace append
|
||||
{
|
||||
|
||||
struct append_no_action
|
||||
{
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry& , Point const& ,
|
||||
signed_size_type = -1, signed_size_type = 0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct to_range_point
|
||||
{
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry& geometry, Point const& point,
|
||||
signed_size_type = -1, signed_size_type = 0)
|
||||
{
|
||||
typename geometry::point_type<Geometry>::type copy;
|
||||
geometry::detail::conversion::convert_point_to_point(point, copy);
|
||||
traits::push_back<Geometry>::apply(geometry, copy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct to_range_range
|
||||
{
|
||||
template <typename Geometry, typename Range>
|
||||
static inline void apply(Geometry& geometry, Range const& range,
|
||||
signed_size_type = -1, signed_size_type = 0)
|
||||
{
|
||||
using point_type = typename boost::range_value<Range>::type;
|
||||
|
||||
auto const end = boost::end(range);
|
||||
for (auto it = boost::begin(range); it != end; ++it)
|
||||
{
|
||||
to_range_point::apply<Geometry, point_type>(geometry, *it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct to_polygon_point
|
||||
{
|
||||
template <typename Polygon, typename Point>
|
||||
static inline void apply(Polygon& polygon, Point const& point,
|
||||
signed_size_type ring_index, signed_size_type = 0)
|
||||
{
|
||||
using ring_type = typename ring_type<Polygon>::type;
|
||||
|
||||
if (ring_index == -1)
|
||||
{
|
||||
auto&& ext_ring = exterior_ring(polygon);
|
||||
to_range_point::apply<ring_type, Point>(ext_ring, point);
|
||||
}
|
||||
else if (ring_index < signed_size_type(num_interior_rings(polygon)))
|
||||
{
|
||||
auto&& int_rings = interior_rings(polygon);
|
||||
to_range_point::apply<ring_type, Point>(range::at(int_rings, ring_index), point);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct to_polygon_range
|
||||
{
|
||||
template <typename Polygon, typename Range>
|
||||
static inline void apply(Polygon& polygon, Range const& range,
|
||||
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);
|
||||
to_range_range::apply<ring_type, Range>(ext_ring, range);
|
||||
}
|
||||
else if (ring_index < signed_size_type(num_interior_rings(polygon)))
|
||||
{
|
||||
interior_ring_range_type int_rings = interior_rings(polygon);
|
||||
to_range_range::apply<ring_type, Range>(range::at(int_rings, ring_index), range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Policy>
|
||||
struct to_multigeometry
|
||||
{
|
||||
template <typename MultiGeometry, typename RangeOrPoint>
|
||||
static inline void apply(MultiGeometry& multigeometry,
|
||||
RangeOrPoint const& range_or_point,
|
||||
signed_size_type ring_index, signed_size_type multi_index)
|
||||
{
|
||||
Policy::template apply
|
||||
<
|
||||
typename boost::range_value<MultiGeometry>::type,
|
||||
RangeOrPoint
|
||||
>(range::at(multigeometry, multi_index), range_or_point, ring_index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::append
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace 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<Geometry, Point, linestring_tag, point_tag>
|
||||
: detail::append::to_range_point
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Point>
|
||||
struct append<Geometry, Point, ring_tag, point_tag>
|
||||
: detail::append::to_range_point
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Point>
|
||||
struct append<Polygon, Point, polygon_tag, point_tag>
|
||||
: detail::append::to_polygon_point
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range, typename RangeTag>
|
||||
struct append<Geometry, Range, linestring_tag, RangeTag>
|
||||
: detail::append::to_range_range
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename Range, typename RangeTag>
|
||||
struct append<Geometry, Range, ring_tag, RangeTag>
|
||||
: detail::append::to_range_range
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Range, typename RangeTag>
|
||||
struct append<Polygon, Range, polygon_tag, RangeTag>
|
||||
: detail::append::to_polygon_range
|
||||
{};
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
/*!
|
||||
\brief Appends one or more points to a linestring, ring, polygon, multi-geometry
|
||||
\ingroup append
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam RangeOrPoint Either a range or a point, fullfilling Boost.Range concept or Boost.Geometry Point Concept
|
||||
\param geometry \param_geometry
|
||||
\param range_or_point The point or range to add
|
||||
\param ring_index The index of the ring in case of a polygon:
|
||||
exterior ring (-1, the default) or interior ring index
|
||||
\param multi_index The index of the geometry to which the points are appended
|
||||
|
||||
\qbk{[include reference/algorithms/append.qbk]}
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename RangeOrPoint>
|
||||
inline void append(Geometry& geometry, RangeOrPoint const& range_or_point,
|
||||
signed_size_type ring_index = -1, signed_size_type multi_index = 0)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::append
|
||||
<
|
||||
Geometry, RangeOrPoint
|
||||
>::apply(geometry, range_or_point, ring_index, multi_index);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
|
||||
+371
@@ -0,0 +1,371 @@
|
||||
// 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-2022 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
|
||||
#include <boost/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/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/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/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/views/detail/closed_clockwise_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace area
|
||||
{
|
||||
|
||||
struct box_area
|
||||
{
|
||||
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 strategies.area(box).apply(box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ring_area
|
||||
{
|
||||
template <typename Ring, typename Strategies>
|
||||
static inline typename area_result<Ring, Strategies>::type
|
||||
apply(Ring const& ring, Strategies const& strategies)
|
||||
{
|
||||
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(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) < detail::minimum_ring_size<Ring>::value)
|
||||
{
|
||||
return typename area_result<Ring, Strategies>::type();
|
||||
}
|
||||
|
||||
detail::closed_clockwise_view<Ring const> const view(ring);
|
||||
auto it = boost::begin(view);
|
||||
auto const end = boost::end(view);
|
||||
|
||||
strategy_type const strategy = strategies.area(ring);
|
||||
typename strategy_type::template state<Ring> state;
|
||||
|
||||
for (auto previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
strategy.apply(*previous, *it, state);
|
||||
}
|
||||
|
||||
return strategy.result(state);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::area
|
||||
|
||||
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
struct area : detail::calculate_null
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return calculate_null::apply
|
||||
<
|
||||
typename area_result<Geometry, Strategy>::type
|
||||
>(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct area<Geometry, box_tag> : detail::area::box_area
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct area<Ring, ring_tag>
|
||||
: detail::area::ring_area
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon>
|
||||
struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
|
||||
{
|
||||
template <typename Strategy>
|
||||
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
|
||||
>(polygon, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiGeometry>
|
||||
struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename area_result<MultiGeometry, Strategy>::type
|
||||
apply(MultiGeometry const& multi, Strategy const& strategy)
|
||||
{
|
||||
return multi_sum::apply
|
||||
<
|
||||
typename area_result<MultiGeometry, Strategy>::type,
|
||||
area<typename boost::range_value<MultiGeometry>::type>
|
||||
>(multi, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct area
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
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, false>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline typename area_result<Geometry>::type
|
||||
apply(Geometry const& geometry, default_strategy)
|
||||
{
|
||||
typedef typename strategies::area::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
|
||||
struct area
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::area<Strategy>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct area<Geometry, dynamic_geometry_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;
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
result = area<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
|
||||
}, geometry);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{area}
|
||||
\ingroup area
|
||||
\details \details_calc{area}. \details_default_strategy
|
||||
|
||||
The area algorithm calculates the surface area of all geometries having a surface, namely
|
||||
box, polygon, ring, multipolygon. The units are the square of the units used for the points
|
||||
defining the surface. If subject geometry is defined in meters, then area is calculated
|
||||
in square meters.
|
||||
|
||||
The area calculation can be done in all three common coordinate systems, Cartesian, Spherical
|
||||
and Geographic as well.
|
||||
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_calc{area}
|
||||
|
||||
\qbk{[include reference/algorithms/area.qbk]}
|
||||
\qbk{[heading Examples]}
|
||||
\qbk{[area] [area_output]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline typename area_result<Geometry>::type
|
||||
area(Geometry const& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_dynamic::area<Geometry>::apply(geometry, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{area} \brief_strategy
|
||||
\ingroup area
|
||||
\details \details_calc{area} \brief_strategy. \details_strategy_reasons
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Area}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{area}
|
||||
\return \return_calc{area}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{
|
||||
[include reference/algorithms/area.qbk]
|
||||
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_area_cartesian Cartesian]
|
||||
\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
|
||||
\* [link geometry.reference.strategies.strategy_area_geographic Geographic]
|
||||
|
||||
[heading Example]
|
||||
[area_with_strategy]
|
||||
[area_with_strategy_output]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline typename area_result<Geometry, Strategy>::type
|
||||
area(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_dynamic::area<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
+141
@@ -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
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 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.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
|
||||
|
||||
#include <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/core/static_assert.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Assign a range of points to a linestring, ring or polygon
|
||||
\note The point-type of the range might be different from the point-type of the geometry
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Range \tparam_range_point
|
||||
\param geometry \param_geometry
|
||||
\param range \param_range_point
|
||||
|
||||
\qbk{
|
||||
[heading Notes]
|
||||
[note Assign automatically clears the geometry before assigning (use append if you don't want that)]
|
||||
[heading Example]
|
||||
[assign_points] [assign_points_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.append append]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Range>
|
||||
inline void assign_points(Geometry& geometry, Range const& range)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
clear(geometry);
|
||||
geometry::append(geometry, range, -1, 0);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief assign to a box inverse infinite
|
||||
\details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
|
||||
min corner is very large, the max corner is very small. This is a convenient starting point to
|
||||
collect the minimum bounding box of a geometry.
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_inverse] [assign_inverse_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.make.make_inverse make_inverse]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void assign_inverse(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign_inverse
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry
|
||||
>::apply(geometry);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief assign zero values to a box, point
|
||||
\ingroup assign
|
||||
\details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void assign_zero(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign_zero
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry
|
||||
>::apply(geometry);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign two coordinates to a geometry (usually a 2D point)
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Type \tparam_numeric to specify the coordinates
|
||||
\param geometry \param_geometry
|
||||
\param c1 \param_x
|
||||
\param c2 \param_y
|
||||
|
||||
\qbk{distinguish, 2 coordinate values}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_2d_point] [assign_2d_point_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Type>
|
||||
inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
geometry::dimension<Geometry>::type::value
|
||||
>::apply(geometry, c1, c2);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign three values to a geometry (usually a 3D point)
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Type \tparam_numeric to specify the coordinates
|
||||
\param geometry \param_geometry
|
||||
\param c1 \param_x
|
||||
\param c2 \param_y
|
||||
\param c3 \param_z
|
||||
|
||||
\qbk{distinguish, 3 coordinate values}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_3d_point] [assign_3d_point_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Type>
|
||||
inline void assign_values(Geometry& geometry,
|
||||
Type const& c1, Type const& c2, Type const& c3)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
geometry::dimension<Geometry>::type::value
|
||||
>::apply(geometry, c1, c2, c3);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assign four values to a geometry (usually a box or segment)
|
||||
\ingroup assign
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Type \tparam_numeric to specify the coordinates
|
||||
\param geometry \param_geometry
|
||||
\param c1 First coordinate (usually x1)
|
||||
\param c2 Second coordinate (usually y1)
|
||||
\param c3 Third coordinate (usually x2)
|
||||
\param c4 Fourth coordinate (usually y2)
|
||||
|
||||
\qbk{distinguish, 4 coordinate values}
|
||||
*/
|
||||
template <typename Geometry, typename Type>
|
||||
inline void assign_values(Geometry& geometry,
|
||||
Type const& c1, Type const& c2, Type const& c3, Type const& c4)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::assign
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
geometry::dimension<Geometry>::type::value
|
||||
>::apply(geometry, c1, c2, c3, c4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct assign
|
||||
{
|
||||
static inline void
|
||||
apply(Geometry1& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1>();
|
||||
concepts::check<Geometry2 const>();
|
||||
concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
|
||||
|
||||
static bool const same_point_order
|
||||
= point_order<Geometry1>::value == point_order<Geometry2>::value;
|
||||
BOOST_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_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
|
||||
{
|
||||
return assign
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply
|
||||
(geometry1, m_geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
return boost::apply_visitor(visitor(geometry2), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
Geometry1& m_geometry1;
|
||||
|
||||
visitor(Geometry1 const& geometry1)
|
||||
: m_geometry1(geometry1)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
result_type operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return assign
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply
|
||||
(m_geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(Geometry1& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
|
||||
{
|
||||
return boost::apply_visitor(visitor(geometry1), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
|
||||
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
result_type operator()(
|
||||
Geometry1& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return assign
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply
|
||||
(geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
|
||||
{
|
||||
return boost::apply_visitor(visitor(), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Assigns one geometry to another geometry
|
||||
\details The assign algorithm assigns one geometry, e.g. a BOX, to another
|
||||
geometry, e.g. a RING. This only works if it is possible and applicable.
|
||||
\ingroup assign
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry (target)
|
||||
\param geometry2 \param_geometry (source)
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign] [assign_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.convert convert]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
resolve_variant::assign<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
|
||||
+221
@@ -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
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// 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_BUFFER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/implementation.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
|
||||
+650
@@ -0,0 +1,650 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014-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.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/throw_exception.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/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/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/strategies/detail.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/views/closeable_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
|
||||
|
||||
/*!
|
||||
\brief Centroid Exception
|
||||
\ingroup centroid
|
||||
\details The centroid_exception is thrown if the free centroid function is called with
|
||||
geometries for which the centroid cannot be calculated. For example: a linestring
|
||||
without points, a polygon without points, an empty multi-geometry.
|
||||
\qbk{
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.centroid the centroid function]
|
||||
}
|
||||
|
||||
*/
|
||||
class centroid_exception : public geometry::exception
|
||||
{
|
||||
public:
|
||||
|
||||
inline centroid_exception() {}
|
||||
|
||||
char const* what() const noexcept override
|
||||
{
|
||||
return "Boost.Geometry Centroid calculation exception";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace centroid
|
||||
{
|
||||
|
||||
struct centroid_point
|
||||
{
|
||||
template<typename Point, typename PointCentroid, typename Strategy>
|
||||
static inline void apply(Point const& point, PointCentroid& centroid,
|
||||
Strategy const&)
|
||||
{
|
||||
geometry::convert(point, centroid);
|
||||
}
|
||||
};
|
||||
|
||||
struct centroid_indexed
|
||||
{
|
||||
template<typename Indexed, typename Point, typename Strategy>
|
||||
static inline void apply(Indexed const& indexed, Point& centroid,
|
||||
Strategy const&)
|
||||
{
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Indexed, Point
|
||||
>::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);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// There is one thing where centroid is different from e.g. within.
|
||||
// If the ring has only one point, it might make sense that
|
||||
// that point is the centroid.
|
||||
template<typename Point, typename Range>
|
||||
inline bool range_ok(Range const& range, Point& centroid)
|
||||
{
|
||||
std::size_t const n = boost::size(range);
|
||||
if (n > 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (n <= 0)
|
||||
{
|
||||
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
|
||||
BOOST_THROW_EXCEPTION(centroid_exception());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else // if (n == 1)
|
||||
{
|
||||
// Take over the first point in a "coordinate neutral way"
|
||||
geometry::convert(*boost::begin(range), centroid);
|
||||
return false;
|
||||
}
|
||||
//return true; // unreachable
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Calculate the centroid of a Ring or a Linestring.
|
||||
*/
|
||||
struct centroid_range_state
|
||||
{
|
||||
template<typename Ring, typename PointTransformer, typename Strategy, typename State>
|
||||
static inline void apply(Ring const& ring,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
State& state)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
|
||||
detail::closed_view<Ring const> const view(ring);
|
||||
auto it = boost::begin(view);
|
||||
auto const end = boost::end(view);
|
||||
|
||||
if (it != end)
|
||||
{
|
||||
typename PointTransformer::result_type
|
||||
previous_pt = transformer.apply(*it);
|
||||
|
||||
for ( ++it ; it != end ; ++it)
|
||||
{
|
||||
typename PointTransformer::result_type
|
||||
pt = transformer.apply(*it);
|
||||
|
||||
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);
|
||||
|
||||
previous_pt = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct centroid_range
|
||||
{
|
||||
template<typename Range, typename Point, typename Strategy>
|
||||
static inline bool apply(Range const& range, Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (range_ok(range, centroid))
|
||||
{
|
||||
// prepare translation transformer
|
||||
translating_transformer<Range> transformer(*boost::begin(range));
|
||||
|
||||
typename Strategy::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
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Centroid of a polygon.
|
||||
\note Because outer ring is clockwise, inners are counter clockwise,
|
||||
triangle approach is OK and works for polygons with rings.
|
||||
*/
|
||||
struct centroid_polygon_state
|
||||
{
|
||||
template<typename Polygon, typename PointTransformer, typename Strategy, typename State>
|
||||
static inline void apply(Polygon const& poly,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
State& state)
|
||||
{
|
||||
centroid_range_state::apply(exterior_ring(poly), transformer, strategy, state);
|
||||
|
||||
auto const& rings = interior_rings(poly);
|
||||
auto const end = boost::end(rings);
|
||||
for (auto it = boost::begin(rings); it != end; ++it)
|
||||
{
|
||||
centroid_range_state::apply(*it, transformer, strategy, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct centroid_polygon
|
||||
{
|
||||
template<typename Polygon, typename Point, typename Strategy>
|
||||
static inline bool apply(Polygon const& poly, Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (range_ok(exterior_ring(poly), centroid))
|
||||
{
|
||||
// prepare translation transformer
|
||||
translating_transformer<Polygon>
|
||||
transformer(*boost::begin(exterior_ring(poly)));
|
||||
|
||||
typename Strategy::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
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Building block of a multi-point, to be used as Policy in the
|
||||
more generec centroid_multi
|
||||
*/
|
||||
struct centroid_multi_point_state
|
||||
{
|
||||
template <typename Point, typename PointTransformer, typename Strategy, typename State>
|
||||
static inline void apply(Point const& point,
|
||||
PointTransformer const& transformer,
|
||||
Strategy const& strategy,
|
||||
State& state)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
strategy.apply(static_cast<Point const&>(transformer.apply(point)),
|
||||
state);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Generic implementation which calls a policy to calculate the
|
||||
centroid of the total of its single-geometries
|
||||
\details The Policy is, in general, the single-version, with state. So
|
||||
detail::centroid::centroid_polygon_state is used as a policy for this
|
||||
detail::centroid::centroid_multi
|
||||
|
||||
*/
|
||||
template <typename Policy>
|
||||
struct centroid_multi
|
||||
{
|
||||
template <typename Multi, typename Point, typename Strategy>
|
||||
static inline bool apply(Multi const& multi,
|
||||
Point& centroid,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
|
||||
// If there is nothing in any of the ranges, it is not possible
|
||||
// to calculate the centroid
|
||||
if (geometry::is_empty(multi))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(centroid_exception());
|
||||
}
|
||||
#endif
|
||||
|
||||
// prepare translation transformer
|
||||
translating_transformer<Multi> transformer(multi);
|
||||
|
||||
typename Strategy::template state_type
|
||||
<
|
||||
typename geometry::point_type<Multi>::type,
|
||||
Point
|
||||
>::type state;
|
||||
|
||||
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
|
||||
{
|
||||
Policy::apply(*it, transformer, strategy, state);
|
||||
}
|
||||
|
||||
if (strategy.result(state, centroid))
|
||||
{
|
||||
// translate the result back
|
||||
transformer.apply_reverse(centroid);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Algorithm>
|
||||
struct centroid_linear_areal
|
||||
{
|
||||
template <typename Geometry, typename Point, typename Strategies>
|
||||
static inline void apply(Geometry const& geom,
|
||||
Point& centroid,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
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
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
struct centroid: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct centroid<Geometry, point_tag>
|
||||
: detail::centroid::centroid_point
|
||||
{};
|
||||
|
||||
template <typename Box>
|
||||
struct centroid<Box, box_tag>
|
||||
: detail::centroid::centroid_indexed
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct centroid<Segment, segment_tag>
|
||||
: detail::centroid::centroid_indexed
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct centroid<Ring, ring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_range
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Linestring>
|
||||
struct centroid<Linestring, linestring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_range
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct centroid<Polygon, polygon_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct centroid<MultiLinestring, multi_linestring_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_range_state
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct centroid<MultiPolygon, multi_polygon_tag>
|
||||
: detail::centroid::centroid_linear_areal
|
||||
<
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_polygon_state
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct centroid<MultiPoint, multi_point_tag>
|
||||
: detail::centroid::centroid_pointlike
|
||||
<
|
||||
detail::centroid::centroid_multi
|
||||
<
|
||||
detail::centroid::centroid_multi_point_state
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct centroid
|
||||
{
|
||||
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)
|
||||
{
|
||||
using strategies::centroid::services::strategy_converter;
|
||||
dispatch::centroid
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, out, strategy_converter<Strategy>::get(strategy));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct centroid<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry, typename Point>
|
||||
static inline void apply(Geometry const& geometry, Point& out, default_strategy)
|
||||
{
|
||||
typedef typename strategies::centroid::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type strategies_type;
|
||||
|
||||
dispatch::centroid<Geometry>::apply(geometry, out, strategies_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic {
|
||||
|
||||
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<Strategy>::apply(geometry, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct centroid<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Point& out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
centroid<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid} \brief_strategy
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_strategy_reasons
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Point \tparam_point
|
||||
\tparam Strategy \tparam_strategy{Centroid}
|
||||
\param geometry \param_geometry
|
||||
\param c \param_point \param_set{centroid}
|
||||
\param strategy \param_strategy{centroid}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
\qbk{[include reference/algorithms/centroid_strategies.qbk]}
|
||||
}
|
||||
|
||||
*/
|
||||
template<typename Geometry, typename Point, typename Strategy>
|
||||
inline void centroid(Geometry const& geometry, Point& c, Strategy const& strategy)
|
||||
{
|
||||
resolve_dynamic::centroid<Geometry>::apply(geometry, c, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid}
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_default_strategy
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Point \tparam_point
|
||||
\param geometry \param_geometry
|
||||
\param c The calculated centroid will be assigned to this point reference
|
||||
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[centroid]
|
||||
[centroid_output]
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Point>
|
||||
inline void centroid(Geometry const& geometry, Point& c)
|
||||
{
|
||||
geometry::centroid(geometry, c, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid}
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}.
|
||||
\tparam Point \tparam_point
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_calc{centroid}
|
||||
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
*/
|
||||
template<typename Point, typename Geometry>
|
||||
inline Point return_centroid(Geometry const& geometry)
|
||||
{
|
||||
Point c;
|
||||
geometry::centroid(geometry, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{centroid} \brief_strategy
|
||||
\ingroup centroid
|
||||
\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. \details_strategy_reasons
|
||||
\tparam Point \tparam_point
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{centroid}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{centroid}
|
||||
\return \return_calc{centroid}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/centroid.qbk]}
|
||||
\qbk{[include reference/algorithms/centroid_strategies.qbk]}
|
||||
*/
|
||||
template<typename Point, typename Geometry, typename Strategy>
|
||||
inline Point return_centroid(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
Point c;
|
||||
geometry::centroid(geometry, c, strategy);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
// 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 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.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.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>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace clear
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct collection_clear
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
{
|
||||
traits::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Polygon>
|
||||
struct polygon_clear
|
||||
{
|
||||
static inline void apply(Polygon& polygon)
|
||||
{
|
||||
traits::clear
|
||||
<
|
||||
typename std::remove_reference
|
||||
<
|
||||
typename traits::interior_mutable_type<Polygon>::type
|
||||
>::type
|
||||
>::apply(interior_rings(polygon));
|
||||
traits::clear
|
||||
<
|
||||
typename std::remove_reference
|
||||
<
|
||||
typename traits::ring_mutable_type<Polygon>::type
|
||||
>::type
|
||||
>::apply(exterior_ring(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct no_action
|
||||
{
|
||||
static inline void apply(Geometry& )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::clear
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
|
||||
>
|
||||
struct clear: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
// Point/box/segment do not have clear. So specialize to do nothing.
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, point_tag>
|
||||
: detail::clear::no_action<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, box_tag>
|
||||
: detail::clear::no_action<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, segment_tag>
|
||||
: detail::clear::no_action<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, linestring_tag>
|
||||
: detail::clear::collection_clear<Geometry>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, ring_tag>
|
||||
: detail::clear::collection_clear<Geometry>
|
||||
{};
|
||||
|
||||
|
||||
// Polygon can (indirectly) use std for clear
|
||||
template <typename Polygon>
|
||||
struct clear<Polygon, polygon_tag>
|
||||
: detail::clear::polygon_clear<Polygon>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, multi_tag>
|
||||
: detail::clear::collection_clear<Geometry>
|
||||
{};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct clear<Geometry, geometry_collection_tag>
|
||||
{
|
||||
static void apply(Geometry& geometry)
|
||||
{
|
||||
traits::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
/*!
|
||||
\brief Clears a linestring, ring or polygon (exterior+interiors) or multi*
|
||||
\details Generic function to clear a geometry. All points will be removed from the collection or collections
|
||||
making up the geometry. In most cases this is equivalent to the .clear() method of a std::vector<...>. In
|
||||
the case of a polygon, this clear functionality is automatically called for the exterior ring, and for the
|
||||
interior ring collection. In the case of a point, boxes and segments, nothing will happen.
|
||||
\ingroup clear
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry which will be cleared
|
||||
\note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero"
|
||||
|
||||
\qbk{[include reference/algorithms/clear.qbk]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void clear(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
dispatch::clear<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
|
||||
+16
@@ -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
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
|
||||
+573
@@ -0,0 +1,573 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 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
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/numeric/conversion/cast.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/algorithms/clear.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/not_implemented.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
|
||||
{
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
// Silence warning C4512: assignment operator could not be generated
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127 4512)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace conversion
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Box,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_to_box
|
||||
{
|
||||
static inline void apply(Point const& point, Box& box)
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
set<Index, Dimension>(box,
|
||||
boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
|
||||
point_to_box
|
||||
<
|
||||
Point, Box,
|
||||
Index, Dimension + 1, DimensionCount
|
||||
>::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Box,
|
||||
std::size_t Index,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Point const& , Box& )
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename Box, typename Range, bool Close, bool Reverse>
|
||||
struct box_to_range
|
||||
{
|
||||
static inline void apply(Box const& box, Range& range)
|
||||
{
|
||||
traits::resize<Range>::apply(range, Close ? 5 : 4);
|
||||
assign_box_corners_oriented<Reverse>(box, range);
|
||||
if (Close)
|
||||
{
|
||||
range::at(range, 4) = range::at(range, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Segment, typename Range>
|
||||
struct segment_to_range
|
||||
{
|
||||
static inline void apply(Segment const& segment, Range& range)
|
||||
{
|
||||
traits::resize<Range>::apply(range, 2);
|
||||
|
||||
auto it = boost::begin(range);
|
||||
|
||||
assign_point_from_index<0>(segment, *it);
|
||||
++it;
|
||||
assign_point_from_index<1>(segment, *it);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Range1,
|
||||
typename Range2,
|
||||
bool Reverse = false
|
||||
>
|
||||
struct range_to_range
|
||||
{
|
||||
struct default_policy
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline void apply(Point1 const& point1, Point2 & point2)
|
||||
{
|
||||
geometry::detail::conversion::convert_point_to_point(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void apply(Range1 const& source, Range2& destination)
|
||||
{
|
||||
apply(source, destination, default_policy());
|
||||
}
|
||||
|
||||
template <typename ConvertPointPolicy>
|
||||
static inline ConvertPointPolicy apply(Range1 const& source, Range2& destination,
|
||||
ConvertPointPolicy convert_point)
|
||||
{
|
||||
geometry::clear(destination);
|
||||
|
||||
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 const view(source);
|
||||
|
||||
typedef typename boost::range_size<Range1>::type size_type;
|
||||
size_type n = boost::size(view);
|
||||
if (geometry::closure<Range2>::value == geometry::open)
|
||||
{
|
||||
n--;
|
||||
}
|
||||
|
||||
// If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()
|
||||
// but ok, sice below it == end()
|
||||
|
||||
size_type i = 0;
|
||||
for (auto it = boost::begin(view);
|
||||
it != boost::end(view) && i < n;
|
||||
++it, ++i)
|
||||
{
|
||||
typename boost::range_value<Range2>::type point;
|
||||
convert_point.apply(*it, point);
|
||||
range::push_back(destination, point);
|
||||
}
|
||||
|
||||
return convert_point;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct polygon_to_polygon
|
||||
{
|
||||
typedef range_to_range
|
||||
<
|
||||
typename geometry::ring_type<Polygon1>::type,
|
||||
typename geometry::ring_type<Polygon2>::type,
|
||||
geometry::point_order<Polygon1>::value
|
||||
!= geometry::point_order<Polygon2>::value
|
||||
> per_ring;
|
||||
|
||||
static inline void apply(Polygon1 const& source, Polygon2& destination)
|
||||
{
|
||||
// Clearing managed per ring, and in the resizing of interior rings
|
||||
|
||||
per_ring::apply(geometry::exterior_ring(source),
|
||||
geometry::exterior_ring(destination));
|
||||
|
||||
// Container should be resizeable
|
||||
traits::resize
|
||||
<
|
||||
typename std::remove_reference
|
||||
<
|
||||
typename traits::interior_mutable_type<Polygon2>::type
|
||||
>::type
|
||||
>::apply(interior_rings(destination), num_interior_rings(source));
|
||||
|
||||
auto const& rings_source = interior_rings(source);
|
||||
auto&& rings_dest = interior_rings(destination);
|
||||
|
||||
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)
|
||||
{
|
||||
per_ring::apply(*it_source, *it_dest);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Single, typename Multi, typename Policy>
|
||||
struct single_to_multi: private Policy
|
||||
{
|
||||
static inline void apply(Single const& single, Multi& multi)
|
||||
{
|
||||
traits::resize<Multi>::apply(multi, 1);
|
||||
Policy::apply(single, *boost::begin(multi));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename Multi1, typename Multi2, typename Policy>
|
||||
struct multi_to_multi: private Policy
|
||||
{
|
||||
static inline void apply(Multi1 const& multi1, Multi2& multi2)
|
||||
{
|
||||
traits::resize<Multi2>::apply(multi2, boost::size(multi1));
|
||||
|
||||
auto it1 = boost::begin(multi1);
|
||||
auto it2 = boost::begin(multi2);
|
||||
|
||||
for (; it1 != boost::end(multi1); ++it1, ++it2)
|
||||
{
|
||||
Policy::apply(*it1, *it2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::conversion
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
// 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 = std::is_same<Geometry1, Geometry2>::value
|
||||
&& !std::is_array<Geometry1>::value
|
||||
>
|
||||
struct convert
|
||||
: not_implemented
|
||||
<
|
||||
Tag1, Tag2,
|
||||
std::integral_constant<std::size_t, DimensionCount>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
|
||||
{
|
||||
// Same geometry type -> copy whole geometry
|
||||
static inline void apply(Geometry1 const& source, Geometry2& destination)
|
||||
{
|
||||
destination = source;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
|
||||
: detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
|
||||
: detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment1, typename Segment2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
|
||||
: detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment, typename LineString, std::size_t DimensionCount>
|
||||
struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
|
||||
: detail::conversion::segment_to_range<Segment, LineString>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring1, typename Ring2, std::size_t DimensionCount>
|
||||
struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
|
||||
: detail::conversion::range_to_range
|
||||
<
|
||||
Ring1,
|
||||
Ring2,
|
||||
geometry::point_order<Ring1>::value
|
||||
!= geometry::point_order<Ring2>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename LineString1, typename LineString2, std::size_t DimensionCount>
|
||||
struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
|
||||
: detail::conversion::range_to_range<LineString1, LineString2>
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
|
||||
struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
|
||||
: detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
|
||||
{};
|
||||
|
||||
template <typename Box, typename Ring>
|
||||
struct convert<Box, Ring, box_tag, ring_tag, 2, false>
|
||||
: detail::conversion::box_to_range
|
||||
<
|
||||
Box,
|
||||
Ring,
|
||||
geometry::closure<Ring>::value == closed,
|
||||
geometry::point_order<Ring>::value == counterclockwise
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box, typename Polygon>
|
||||
struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
|
||||
{
|
||||
static inline void apply(Box const& box, Polygon& polygon)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
convert
|
||||
<
|
||||
Box, ring_type,
|
||||
box_tag, ring_tag,
|
||||
2, false
|
||||
>::apply(box, exterior_ring(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Point, typename Box, std::size_t DimensionCount>
|
||||
struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
|
||||
{
|
||||
static inline void apply(Point const& point, Box& box)
|
||||
{
|
||||
detail::conversion::point_to_box
|
||||
<
|
||||
Point, Box, min_corner, 0, DimensionCount
|
||||
>::apply(point, box);
|
||||
detail::conversion::point_to_box
|
||||
<
|
||||
Point, Box, max_corner, 0, DimensionCount
|
||||
>::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring, typename Polygon, std::size_t DimensionCount>
|
||||
struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
|
||||
{
|
||||
static inline void apply(Ring const& ring, Polygon& polygon)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
convert
|
||||
<
|
||||
Ring, ring_type,
|
||||
ring_tag, ring_tag,
|
||||
DimensionCount, false
|
||||
>::apply(ring, exterior_ring(polygon));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon, typename Ring, std::size_t DimensionCount>
|
||||
struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
|
||||
{
|
||||
static inline void apply(Polygon const& polygon, Ring& ring)
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
convert
|
||||
<
|
||||
ring_type, Ring,
|
||||
ring_tag, ring_tag,
|
||||
DimensionCount, false
|
||||
>::apply(exterior_ring(polygon), ring);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Dispatch for multi <-> multi, specifying their single-version as policy.
|
||||
// Note that, even if the multi-types are mutually different, their single
|
||||
// version types might be the same and therefore we call std::is_same again
|
||||
|
||||
template <typename Multi1, typename Multi2, std::size_t DimensionCount>
|
||||
struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
|
||||
: detail::conversion::multi_to_multi
|
||||
<
|
||||
Multi1,
|
||||
Multi2,
|
||||
convert
|
||||
<
|
||||
typename boost::range_value<Multi1>::type,
|
||||
typename boost::range_value<Multi2>::type,
|
||||
typename single_tag_of
|
||||
<
|
||||
typename tag<Multi1>::type
|
||||
>::type,
|
||||
typename single_tag_of
|
||||
<
|
||||
typename tag<Multi2>::type
|
||||
>::type,
|
||||
DimensionCount
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>
|
||||
struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>
|
||||
: detail::conversion::single_to_multi
|
||||
<
|
||||
Single,
|
||||
Multi,
|
||||
convert
|
||||
<
|
||||
Single,
|
||||
typename boost::range_value<Multi>::type,
|
||||
typename tag<Single>::type,
|
||||
typename single_tag_of
|
||||
<
|
||||
typename tag<Multi>::type
|
||||
>::type,
|
||||
DimensionCount,
|
||||
false
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct convert
|
||||
{
|
||||
static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
|
||||
dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
Geometry2& m_geometry2;
|
||||
|
||||
visitor(Geometry2& geometry2)
|
||||
: m_geometry2(geometry2)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
inline void operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void apply(
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2& geometry2
|
||||
)
|
||||
{
|
||||
boost::apply_visitor(visitor(geometry2), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Converts one geometry to another geometry
|
||||
\details The convert algorithm converts one geometry, e.g. a BOX, to another
|
||||
geometry, e.g. a RING. This only works if it is possible and applicable.
|
||||
If the point-order is different, or the closure is different between two
|
||||
geometry types, it will be converted correctly by explicitly reversing the
|
||||
points or closing or opening the polygon rings.
|
||||
\ingroup convert
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry (source)
|
||||
\param geometry2 \param_geometry (target)
|
||||
|
||||
\qbk{[include reference/algorithms/convert.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
|
||||
{
|
||||
resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// 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 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_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
|
||||
|
||||
#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
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#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/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
|
||||
{
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace correct
|
||||
{
|
||||
|
||||
struct correct_nop
|
||||
{
|
||||
template <typename Geometry, typename Strategy>
|
||||
static inline void apply(Geometry& , Strategy const& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Correct a box: make min/max correct
|
||||
struct correct_box
|
||||
{
|
||||
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
|
||||
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 Predicate = std::less<>>
|
||||
struct correct_ring
|
||||
{
|
||||
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::apply(r);
|
||||
|
||||
// NOTE: calculate_point_order should probably be used here instead.
|
||||
|
||||
// Check area
|
||||
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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all
|
||||
// inner rings counter clockwise (or vice versa depending on orientation)
|
||||
struct correct_polygon
|
||||
{
|
||||
template <typename Polygon, typename Strategy>
|
||||
static inline void apply(Polygon& poly, Strategy const& strategy)
|
||||
{
|
||||
correct_ring<std::less<>>::apply(exterior_ring(poly), strategy);
|
||||
|
||||
auto&& rings = interior_rings(poly);
|
||||
auto const end = boost::end(rings);
|
||||
for (auto it = boost::begin(rings); it != end; ++it)
|
||||
{
|
||||
correct_ring<std::greater<>>::apply(*it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::correct
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Point>
|
||||
struct correct<Point, point_tag>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
template <typename LineString>
|
||||
struct correct<LineString, linestring_tag>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct correct<Segment, segment_tag>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct correct<Box, box_tag>
|
||||
: detail::correct::correct_box
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct correct<Ring, ring_tag>
|
||||
: detail::correct::correct_ring<>
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct correct<Polygon, polygon_tag>
|
||||
: detail::correct::correct_polygon
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct correct<MultiPoint, multi_point_tag>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLineString>
|
||||
struct correct<MultiLineString, multi_linestring_tag>
|
||||
: detail::correct::correct_nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct<Geometry, multi_polygon_tag>
|
||||
: detail::multi_modify<detail::correct::correct_polygon>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
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>();
|
||||
resolve_strategy::correct<Strategy>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
traits::visit<Geometry>::apply([&](auto & g)
|
||||
{
|
||||
correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
|
||||
/*!
|
||||
\brief Corrects a geometry
|
||||
\details Corrects a geometry: all rings which are wrongly oriented with respect
|
||||
to their expected orientation are reversed. To all rings which do not have a
|
||||
closing point and are typed as they should have one, the first point is
|
||||
appended. Also boxes can be corrected.
|
||||
\ingroup correct
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry which will be corrected if necessary
|
||||
|
||||
\qbk{[include reference/algorithms/correct.qbk]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void correct(Geometry& geometry)
|
||||
{
|
||||
resolve_dynamic::correct<Geometry>::apply(geometry, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Corrects a geometry
|
||||
\details Corrects a geometry: all rings which are wrongly oriented with respect
|
||||
to their expected orientation are reversed. To all rings which do not have a
|
||||
closing point and are typed as they should have one, the first point is
|
||||
appended. Also boxes can be corrected.
|
||||
\ingroup correct
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Area}
|
||||
\param geometry \param_geometry which will be corrected if necessary
|
||||
\param strategy \param_strategy{area}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{[include reference/algorithms/correct.qbk]}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline void correct(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
resolve_dynamic::correct<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_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/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/adapted/boost_variant.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace correct_closure
|
||||
{
|
||||
|
||||
struct nop
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline void apply(Geometry& )
|
||||
{}
|
||||
};
|
||||
|
||||
// Close a ring, if not closed, or open it
|
||||
struct close_or_open_ring
|
||||
{
|
||||
template <typename Ring>
|
||||
static inline void apply(Ring& r)
|
||||
{
|
||||
auto size = boost::size(r);
|
||||
if (size <= 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 && closure == closed)
|
||||
{
|
||||
// Close it by adding first point
|
||||
geometry::append(r, *boost::begin(r));
|
||||
}
|
||||
else if (! disjoint && closure == open)
|
||||
{
|
||||
// Open it by removing last point
|
||||
range::resize(r, size - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Close/open exterior ring and all its interior rings
|
||||
struct close_or_open_polygon
|
||||
{
|
||||
template <typename Polygon>
|
||||
static inline void apply(Polygon& poly)
|
||||
{
|
||||
close_or_open_ring::apply(exterior_ring(poly));
|
||||
|
||||
auto&& rings = interior_rings(poly);
|
||||
auto const end = boost::end(rings);
|
||||
for (auto it = boost::begin(rings); it != end; ++it)
|
||||
{
|
||||
close_or_open_ring::apply(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::correct_closure
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct_closure: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Point>
|
||||
struct correct_closure<Point, point_tag>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
template <typename LineString>
|
||||
struct correct_closure<LineString, linestring_tag>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct correct_closure<Segment, segment_tag>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct correct_closure<Box, box_tag>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct correct_closure<Ring, ring_tag>
|
||||
: detail::correct_closure::close_or_open_ring
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct correct_closure<Polygon, polygon_tag>
|
||||
: detail::correct_closure::close_or_open_polygon
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct correct_closure<MultiPoint, multi_point_tag>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLineString>
|
||||
struct correct_closure<MultiLineString, multi_linestring_tag>
|
||||
: detail::correct_closure::nop
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_closure<Geometry, multi_polygon_tag>
|
||||
: detail::multi_modify
|
||||
<
|
||||
detail::correct_closure::close_or_open_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct_closure
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
dispatch::correct_closure<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_closure<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
static void apply(Geometry& geometry)
|
||||
{
|
||||
traits::visit<Geometry>::apply([](auto & g)
|
||||
{
|
||||
correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_closure<Geometry, geometry_collection_tag>
|
||||
{
|
||||
static void apply(Geometry& 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
|
||||
have a closing point and are typed as they should have one, the first point
|
||||
is appended.
|
||||
\ingroup correct_closure
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry which will be corrected if necessary
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void correct_closure(Geometry& geometry)
|
||||
{
|
||||
resolve_variant::correct_closure<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013-2022.
|
||||
// Modifications copyright (c) 2013-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_COVERED_BY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
|
||||
|
||||
#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
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2014-2022.
|
||||
// Modifications copyright (c) 2014-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_CROSSES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#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
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct crosses
|
||||
: detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_crosses_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct crosses
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return dispatch::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename 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 strategies::crosses::services::default_strategy
|
||||
typedef typename strategies::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return crosses
|
||||
<
|
||||
strategy_type
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
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 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)
|
||||
{
|
||||
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
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Crosses}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{crosses}
|
||||
\return \return_check2{crosses}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/crosses.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool crosses(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_dynamic::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{crosses}
|
||||
\ingroup crosses
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_check2{crosses}
|
||||
|
||||
\qbk{[include reference/algorithms/crosses.qbk]}
|
||||
\qbk{
|
||||
[heading Examples]
|
||||
[crosses]
|
||||
[crosses_output]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_dynamic::crosses
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CROSSES_HPP
|
||||
+41
@@ -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
|
||||
+504
@@ -0,0 +1,504 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_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
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace densify
|
||||
{
|
||||
|
||||
template <typename Range>
|
||||
struct push_back_policy
|
||||
{
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
|
||||
inline explicit push_back_policy(Range & rng)
|
||||
: m_rng(rng)
|
||||
{}
|
||||
|
||||
inline void apply(point_type const& p)
|
||||
{
|
||||
range::push_back(m_rng, p);
|
||||
}
|
||||
|
||||
private:
|
||||
Range & m_rng;
|
||||
};
|
||||
|
||||
template <typename Range, typename Point>
|
||||
inline void convert_and_push_back(Range & range, Point const& p)
|
||||
{
|
||||
typename boost::range_value<Range>::type p2;
|
||||
geometry::detail::conversion::convert_point_to_point(p, p2);
|
||||
range::push_back(range, p2);
|
||||
}
|
||||
|
||||
template <bool AppendLastPoint = true>
|
||||
struct densify_range
|
||||
{
|
||||
template <typename FwdRng, typename MutRng, typename T, typename Strategies>
|
||||
static inline void apply(FwdRng const& rng, MutRng & rng_out,
|
||||
T const& len, Strategies const& strategies)
|
||||
{
|
||||
typedef typename boost::range_value<FwdRng>::type point_t;
|
||||
|
||||
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);
|
||||
|
||||
auto prev = it;
|
||||
for ( ++it ; it != end ; prev = it++)
|
||||
{
|
||||
point_t const& p0 = *prev;
|
||||
point_t const& p1 = *it;
|
||||
|
||||
convert_and_push_back(rng_out, p0);
|
||||
|
||||
strategy.apply(p0, p1, policy, len);
|
||||
}
|
||||
|
||||
if BOOST_GEOMETRY_CONSTEXPR (AppendLastPoint)
|
||||
{
|
||||
convert_and_push_back(rng_out, *prev); // back(rng)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <bool IsClosed1, bool IsClosed2> // false, X
|
||||
struct densify_ring
|
||||
{
|
||||
template <typename Geometry, typename GeometryOut, typename T, typename Strategies>
|
||||
static inline void apply(Geometry const& ring, GeometryOut & ring_out,
|
||||
T const& len, Strategies const& strategies)
|
||||
{
|
||||
geometry::detail::densify::densify_range<true>
|
||||
::apply(ring, ring_out, len, strategies);
|
||||
|
||||
if (boost::size(ring) <= 1)
|
||||
return;
|
||||
|
||||
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_CONSTEXPR (IsClosed2)
|
||||
{
|
||||
convert_and_push_back(ring_out, p1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct densify_ring<true, true>
|
||||
: densify_range<true>
|
||||
{};
|
||||
|
||||
template <>
|
||||
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
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename GeometryOut,
|
||||
typename Tag1 = typename tag<Geometry>::type,
|
||||
typename Tag2 = typename tag<GeometryOut>::type
|
||||
>
|
||||
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<>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, multi_linestring_tag, multi_linestring_tag>
|
||||
{
|
||||
template <typename T, typename Strategy>
|
||||
static void apply(Geometry const& mls, GeometryOut & mls_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
std::size_t count = boost::size(mls);
|
||||
range::resize(mls_out, count);
|
||||
|
||||
for (std::size_t i = 0 ; i < count ; ++i)
|
||||
{
|
||||
geometry::detail::densify::densify_range<>
|
||||
::apply(range::at(mls, i), range::at(mls_out, i),
|
||||
len, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, ring_tag, ring_tag>
|
||||
: geometry::detail::densify::densify_ring
|
||||
<
|
||||
geometry::closure<Geometry>::value != geometry::open,
|
||||
geometry::closure<GeometryOut>::value != geometry::open
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, polygon_tag, polygon_tag>
|
||||
{
|
||||
template <typename T, typename Strategy>
|
||||
static void apply(Geometry const& poly, GeometryOut & poly_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
apply_ring(exterior_ring(poly), exterior_ring(poly_out),
|
||||
len, strategy);
|
||||
|
||||
std::size_t count = boost::size(interior_rings(poly));
|
||||
range::resize(interior_rings(poly_out), count);
|
||||
|
||||
for (std::size_t i = 0 ; i < count ; ++i)
|
||||
{
|
||||
apply_ring(range::at(interior_rings(poly), i),
|
||||
range::at(interior_rings(poly_out), i),
|
||||
len, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ring, typename RingOut, typename T, typename Strategy>
|
||||
static void apply_ring(Ring const& ring, RingOut & ring_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
densify<Ring, RingOut, ring_tag, ring_tag>
|
||||
::apply(ring, ring_out, len, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, multi_polygon_tag, multi_polygon_tag>
|
||||
{
|
||||
template <typename T, typename Strategy>
|
||||
static void apply(Geometry const& mpoly, GeometryOut & mpoly_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
std::size_t count = boost::size(mpoly);
|
||||
range::resize(mpoly_out, count);
|
||||
|
||||
for (std::size_t i = 0 ; i < count ; ++i)
|
||||
{
|
||||
apply_poly(range::at(mpoly, i),
|
||||
range::at(mpoly_out, i),
|
||||
len, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Poly, typename PolyOut, typename T, typename Strategy>
|
||||
static void apply_poly(Poly const& poly, PolyOut & poly_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
densify<Poly, PolyOut, polygon_tag, polygon_tag>::
|
||||
apply(poly, poly_out, len, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct densify
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 const&)
|
||||
{
|
||||
typedef typename strategies::densify::services::default_strategy
|
||||
<
|
||||
Geometry
|
||||
>::type strategies_type;
|
||||
|
||||
dispatch::densify
|
||||
<
|
||||
Geometry, Geometry
|
||||
>::apply(geometry, out, max_distance, strategies_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic {
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct densify
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_strategy::densify
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct densify<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
static inline void
|
||||
apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
|
||||
/*!
|
||||
\brief Densify a geometry using a specified strategy
|
||||
\ingroup densify
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Distance A numerical distance measure
|
||||
\tparam Strategy A type fulfilling a DensifyStrategy concept
|
||||
\param geometry Input geometry, to be densified
|
||||
\param out Output geometry, densified version of the input geometry
|
||||
\param max_distance Distance threshold (in units depending on strategy)
|
||||
\param strategy Densify strategy to be used for densification
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/densify.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_densify_cartesian Cartesian]
|
||||
\* [link geometry.reference.strategies.strategy_densify_spherical Spherical]
|
||||
\* [link geometry.reference.strategies.strategy_densify_geographic Geographic]
|
||||
|
||||
[heading Example]
|
||||
[densify_strategy]
|
||||
[densify_strategy_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.line_interpolate line_interpolate]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Distance, typename Strategy>
|
||||
inline void densify(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
if (max_distance <= Distance(0))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
|
||||
}
|
||||
|
||||
geometry::clear(out);
|
||||
|
||||
resolve_dynamic::densify
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Densify a geometry
|
||||
\ingroup densify
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Distance A numerical distance measure
|
||||
\param geometry Input geometry, to be densified
|
||||
\param out Output geometry, densified version of the input geometry
|
||||
\param max_distance Distance threshold (in units depending on coordinate system)
|
||||
|
||||
\qbk{[include reference/algorithms/densify.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[densify]
|
||||
[densify_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.line_interpolate line_interpolate]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Distance>
|
||||
inline void densify(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance)
|
||||
{
|
||||
densify(geometry, out, max_distance, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
// Note: this is moved to namespace detail because the names and parameter orders
|
||||
// are not yet 100% clear.
|
||||
|
||||
/*!
|
||||
\brief Assign the four points of a 2D box
|
||||
\ingroup assign
|
||||
\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT
|
||||
so this is how it is implemented.
|
||||
\tparam Box \tparam_box
|
||||
\tparam Point \tparam_point
|
||||
\param box \param_box
|
||||
\param lower_left point being assigned to lower left coordinates of the box
|
||||
\param lower_right point being assigned to lower right coordinates of the box
|
||||
\param upper_left point being assigned to upper left coordinates of the box
|
||||
\param upper_right point being assigned to upper right coordinates of the box
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_box_corners] [assign_box_corners_output]
|
||||
}
|
||||
*/
|
||||
template <typename Box, typename Point>
|
||||
inline void assign_box_corners(Box const& box,
|
||||
Point& lower_left, Point& lower_right,
|
||||
Point& upper_left, Point& upper_right)
|
||||
{
|
||||
concepts::check<Box const>();
|
||||
concepts::check<Point>();
|
||||
|
||||
detail::assign::assign_box_2d_corner
|
||||
<min_corner, min_corner>(box, lower_left);
|
||||
detail::assign::assign_box_2d_corner
|
||||
<max_corner, min_corner>(box, lower_right);
|
||||
detail::assign::assign_box_2d_corner
|
||||
<min_corner, max_corner>(box, upper_left);
|
||||
detail::assign::assign_box_2d_corner
|
||||
<max_corner, max_corner>(box, upper_right);
|
||||
}
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
|
||||
template <bool Reverse, typename Box, typename Range>
|
||||
inline void assign_box_corners_oriented(Box const& box, Range& corners)
|
||||
{
|
||||
if (Reverse)
|
||||
{
|
||||
// make counterclockwise ll,lr,ur,ul
|
||||
assign_box_corners(box,
|
||||
range::at(corners, 0), range::at(corners, 1),
|
||||
range::at(corners, 3), range::at(corners, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// make clockwise ll,ul,ur,lr
|
||||
assign_box_corners(box,
|
||||
range::at(corners, 0), range::at(corners, 3),
|
||||
range::at(corners, 1), range::at(corners, 2));
|
||||
}
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// 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 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.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/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/util/algorithm.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Assign a box or segment with the value of a point
|
||||
\ingroup assign
|
||||
\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
|
||||
or which point of segment (0/1)
|
||||
\tparam Point \tparam_point
|
||||
\tparam Geometry \tparam_box_or_segment
|
||||
\param point \param_point
|
||||
\param geometry \param_box_or_segment
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_point_to_index] [assign_point_to_index_output]
|
||||
}
|
||||
*/
|
||||
template <std::size_t Index, typename Geometry, typename Point>
|
||||
inline void assign_point_to_index(Point const& point, Geometry& geometry)
|
||||
{
|
||||
concepts::check<Point const>();
|
||||
concepts::check<Geometry>();
|
||||
|
||||
detail::for_each_dimension<Geometry>([&](auto dimension)
|
||||
{
|
||||
geometry::set<Index, dimension>(geometry,
|
||||
boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>(geometry::get<dimension>(point)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Assign a point with a point of a box or segment
|
||||
\ingroup assign
|
||||
\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
|
||||
or which point of segment (0/1)
|
||||
\tparam Geometry \tparam_box_or_segment
|
||||
\tparam Point \tparam_point
|
||||
\param geometry \param_box_or_segment
|
||||
\param point \param_point
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[assign_point_from_index] [assign_point_from_index_output]
|
||||
}
|
||||
*/
|
||||
template <std::size_t Index, typename Point, typename Geometry>
|
||||
inline void assign_point_from_index(Geometry const& geometry, Point& point)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
concepts::check<Point>();
|
||||
|
||||
detail::for_each_dimension<Geometry>([&](auto dimension)
|
||||
{
|
||||
geometry::set<dimension>(point,
|
||||
boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<Point>::type
|
||||
>(geometry::get<Index, dimension>(geometry)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
// 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.
|
||||
|
||||
// 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/concept/requires.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <boost/numeric/conversion/cast.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>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace assign
|
||||
{
|
||||
|
||||
|
||||
struct assign_zero_point
|
||||
{
|
||||
template <typename Point>
|
||||
static inline void apply(Point& point)
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const zero = 0;
|
||||
detail::for_each_dimension<Point>([&](auto dimension)
|
||||
{
|
||||
set<dimension>(point, zero);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct assign_inverse_box_or_segment
|
||||
{
|
||||
|
||||
template <typename BoxOrSegment>
|
||||
static inline void apply(BoxOrSegment& geometry)
|
||||
{
|
||||
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct assign_zero_box_or_segment
|
||||
{
|
||||
template <typename BoxOrSegment>
|
||||
static inline void apply(BoxOrSegment& geometry)
|
||||
{
|
||||
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
|
||||
|
||||
coordinate_type const zero = 0;
|
||||
detail::for_each_dimension<BoxOrSegment>([&](auto dimension)
|
||||
{
|
||||
set<0, dimension>(geometry, zero);
|
||||
set<1, dimension>(geometry, zero);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Corner1, std::size_t Corner2,
|
||||
typename Box, typename Point
|
||||
>
|
||||
inline void assign_box_2d_corner(Box const& box, Point& point)
|
||||
{
|
||||
// Be sure both are 2-Dimensional
|
||||
assert_dimension<Box, 2>();
|
||||
assert_dimension<Point, 2>();
|
||||
|
||||
// Copy coordinates
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
|
||||
geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct assign_2d_box_or_segment
|
||||
{
|
||||
typedef typename coordinate_type<Geometry>::type coordinate_type;
|
||||
|
||||
// Here we assign 4 coordinates to a box of segment
|
||||
// -> Most logical is: x1,y1,x2,y2
|
||||
// In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)
|
||||
|
||||
template <typename Type>
|
||||
static inline void apply(Geometry& geometry,
|
||||
Type const& x1, Type const& y1, Type const& x2, Type const& y2)
|
||||
{
|
||||
geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));
|
||||
geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
|
||||
geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
|
||||
geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::assign
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
|
||||
struct assign
|
||||
{
|
||||
BOOST_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>
|
||||
struct assign<point_tag, Point, 2>
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
template <typename T>
|
||||
static inline void apply(Point& point, T const& c1, T const& c2)
|
||||
{
|
||||
set<0>(point, boost::numeric_cast<coordinate_type>(c1));
|
||||
set<1>(point, boost::numeric_cast<coordinate_type>(c2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct assign<point_tag, Point, 3>
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
template <typename T>
|
||||
static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
|
||||
{
|
||||
set<0>(point, boost::numeric_cast<coordinate_type>(c1));
|
||||
set<1>(point, boost::numeric_cast<coordinate_type>(c2));
|
||||
set<2>(point, boost::numeric_cast<coordinate_type>(c3));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct assign<box_tag, Box, 2>
|
||||
: detail::assign::assign_2d_box_or_segment<Box>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign<segment_tag, Segment, 2>
|
||||
: detail::assign::assign_2d_box_or_segment<Segment>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
template <typename GeometryTag, typename Geometry>
|
||||
struct assign_zero {};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct assign_zero<point_tag, Point>
|
||||
: detail::assign::assign_zero_point
|
||||
{};
|
||||
|
||||
template <typename Box>
|
||||
struct assign_zero<box_tag, Box>
|
||||
: detail::assign::assign_zero_box_or_segment
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign_zero<segment_tag, Segment>
|
||||
: detail::assign::assign_zero_box_or_segment
|
||||
{};
|
||||
|
||||
|
||||
template <typename GeometryTag, typename Geometry>
|
||||
struct assign_inverse {};
|
||||
|
||||
template <typename Box>
|
||||
struct assign_inverse<box_tag, Box>
|
||||
: detail::assign::assign_inverse_box_or_segment
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign_inverse<segment_tag, Segment>
|
||||
: detail::assign::assign_inverse_box_or_segment
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2018-2019 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_BUFFER_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
|
||||
struct box_loop
|
||||
{
|
||||
typedef typename coordinate_type<BoxOut>::type coordinate_type;
|
||||
|
||||
static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
coordinate_type d = distance;
|
||||
set<C, D>(box_out, get<C, D>(box_in) + d);
|
||||
box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
|
||||
struct box_loop<BoxIn, BoxOut, T, C, N, N>
|
||||
{
|
||||
static inline void apply(BoxIn const&, T const&, BoxOut&) {}
|
||||
};
|
||||
|
||||
// Extends a box with the same amount in all directions
|
||||
template<typename BoxIn, typename BoxOut, typename T>
|
||||
inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
assert_dimension_equal<BoxIn, BoxOut>();
|
||||
|
||||
static const std::size_t N = dimension<BoxIn>::value;
|
||||
|
||||
box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
|
||||
box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
+1062
File diff suppressed because it is too large
Load Diff
+300
@@ -0,0 +1,300 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.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>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
class backtrack_for_buffer
|
||||
{
|
||||
public :
|
||||
typedef detail::overlay::backtrack_state state_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Operation,
|
||||
typename Rings,
|
||||
typename Turns,
|
||||
typename Geometry,
|
||||
typename Strategy,
|
||||
typename RobustPolicy,
|
||||
typename Visitor
|
||||
>
|
||||
static inline void apply(std::size_t size_at_start,
|
||||
Rings& rings, typename boost::range_value<Rings>::type& ring,
|
||||
Turns& turns,
|
||||
typename boost::range_value<Turns>::type const& /*turn*/,
|
||||
Operation& operation,
|
||||
detail::overlay::traverse_error_type /*traverse_error*/,
|
||||
Geometry const& ,
|
||||
Geometry const& ,
|
||||
Strategy const& ,
|
||||
RobustPolicy const& ,
|
||||
state_type& state,
|
||||
Visitor& /*visitor*/
|
||||
)
|
||||
{
|
||||
#if defined(BOOST_GEOMETRY_COUNT_BACKTRACK_WARNINGS)
|
||||
extern int g_backtrack_warning_count;
|
||||
g_backtrack_warning_count++;
|
||||
#endif
|
||||
//std::cout << "!";
|
||||
//std::cout << "WARNING " << traverse_error_string(traverse_error) << std::endl;
|
||||
|
||||
state.m_good = false;
|
||||
|
||||
// Make bad output clean
|
||||
rings.resize(size_at_start);
|
||||
ring.clear();
|
||||
|
||||
// Reject this as a starting point
|
||||
operation.visited.set_rejected();
|
||||
|
||||
// And clear all visit info
|
||||
clear_visit_info(turns);
|
||||
}
|
||||
};
|
||||
|
||||
struct buffer_overlay_visitor
|
||||
{
|
||||
public :
|
||||
void print(char const* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void visit_turns(int , Turns const& ) {}
|
||||
|
||||
template <typename Clusters, typename Turns>
|
||||
void visit_clusters(Clusters const& , Turns const& ) {}
|
||||
|
||||
template <typename Turns, typename Turn, typename Operation>
|
||||
void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns, typename Turn, typename Operation>
|
||||
void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
|
||||
detail::overlay::traverse_error_type )
|
||||
{}
|
||||
|
||||
template <typename Rings>
|
||||
void visit_generated_rings(Rings const& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Should follow traversal-turn-concept (enrichment, visit structure)
|
||||
// and adds index in piece vector to find it back
|
||||
template <typename Point, typename SegmentRatio>
|
||||
struct buffer_turn_operation
|
||||
: public detail::overlay::traversal_turn_operation<Point, SegmentRatio>
|
||||
{
|
||||
signed_size_type piece_index;
|
||||
signed_size_type index_in_robust_ring;
|
||||
|
||||
inline buffer_turn_operation()
|
||||
: piece_index(-1)
|
||||
, index_in_robust_ring(-1)
|
||||
{}
|
||||
};
|
||||
|
||||
// Version 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
|
||||
<
|
||||
Point,
|
||||
SegmentRatio,
|
||||
buffer_turn_operation<Point, SegmentRatio>
|
||||
>
|
||||
{
|
||||
typedef Point point_type;
|
||||
|
||||
std::size_t turn_index;
|
||||
|
||||
// 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;
|
||||
signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
|
||||
|
||||
inline buffer_turn_info()
|
||||
: turn_index(0)
|
||||
, is_turn_traversable(true)
|
||||
, is_linear_end_point(false)
|
||||
, within_original(false)
|
||||
, count_in_original(0)
|
||||
{}
|
||||
};
|
||||
|
||||
struct buffer_less
|
||||
{
|
||||
template <typename Indexed>
|
||||
inline bool operator()(Indexed const& left, Indexed const& right) const
|
||||
{
|
||||
if (! (left.subject->seg_id == right.subject->seg_id))
|
||||
{
|
||||
return left.subject->seg_id < right.subject->seg_id;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
Vendored
Executable
+1100
File diff suppressed because it is too large
Load Diff
+290
@@ -0,0 +1,290 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
struct buffered_ring_collection_tag : polygonal_tag, multi_tag
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct buffered_ring : public Ring
|
||||
{
|
||||
bool has_concave;
|
||||
bool has_accepted_intersections;
|
||||
bool has_discarded_intersections;
|
||||
bool is_untouched_outside_original;
|
||||
|
||||
inline buffered_ring()
|
||||
: has_concave(false)
|
||||
, has_accepted_intersections(false)
|
||||
, has_discarded_intersections(false)
|
||||
, is_untouched_outside_original(false)
|
||||
{}
|
||||
|
||||
inline bool discarded() const
|
||||
{
|
||||
return has_discarded_intersections && ! has_accepted_intersections;
|
||||
}
|
||||
inline bool has_intersections() const
|
||||
{
|
||||
return has_discarded_intersections || has_accepted_intersections;
|
||||
}
|
||||
};
|
||||
|
||||
// This is a collection now special for overlay (needs vector of rings)
|
||||
template <typename Ring>
|
||||
struct buffered_ring_collection : public std::vector<Ring>
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace detail::buffer
|
||||
|
||||
|
||||
// Turn off concept checking (for now)
|
||||
namespace concepts
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct concept_type<Geometry, geometry::detail::buffer::buffered_ring_collection_tag>
|
||||
{
|
||||
struct dummy {};
|
||||
using type = dummy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
// Register the types
|
||||
namespace traits
|
||||
{
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct tag<geometry::detail::buffer::buffered_ring<Ring> >
|
||||
{
|
||||
typedef ring_tag type;
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct point_order<geometry::detail::buffer::buffered_ring<Ring> >
|
||||
{
|
||||
static const order_selector value = geometry::point_order<Ring>::value;
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct closure<geometry::detail::buffer::buffered_ring<Ring> >
|
||||
{
|
||||
static const closure_selector value = geometry::closure<Ring>::value;
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct point_type<geometry::detail::buffer::buffered_ring_collection<Ring> >
|
||||
{
|
||||
typedef typename geometry::point_type<Ring>::type type;
|
||||
};
|
||||
|
||||
template <typename Ring>
|
||||
struct tag<geometry::detail::buffer::buffered_ring_collection<Ring> >
|
||||
{
|
||||
typedef geometry::detail::buffer::buffered_ring_collection_tag type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
|
||||
|
||||
namespace core_dispatch
|
||||
{
|
||||
|
||||
template <typename Ring>
|
||||
struct ring_type
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
detail::buffer::buffered_ring_collection<Ring>
|
||||
>
|
||||
{
|
||||
typedef Ring type;
|
||||
};
|
||||
|
||||
|
||||
// There is a specific tag, so this specialization cannot be placed in traits
|
||||
template <typename Ring>
|
||||
struct point_order<detail::buffer::buffered_ring_collection_tag,
|
||||
geometry::detail::buffer::buffered_ring_collection
|
||||
<
|
||||
geometry::detail::buffer::buffered_ring<Ring>
|
||||
> >
|
||||
{
|
||||
static const order_selector value
|
||||
= core_dispatch::point_order<ring_tag, Ring>::value;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
struct single_tag_of<detail::buffer::buffered_ring_collection_tag>
|
||||
{
|
||||
typedef ring_tag type;
|
||||
};
|
||||
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiRing,
|
||||
bool Reverse,
|
||||
typename SegmentIdentifier,
|
||||
typename PointOut
|
||||
>
|
||||
struct copy_segment_point
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
MultiRing,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
PointOut
|
||||
>
|
||||
: detail::copy_segments::copy_segment_point_multi
|
||||
<
|
||||
MultiRing,
|
||||
SegmentIdentifier,
|
||||
PointOut,
|
||||
detail::copy_segments::copy_segment_point_range
|
||||
<
|
||||
typename boost::range_value<MultiRing>::type,
|
||||
Reverse,
|
||||
SegmentIdentifier,
|
||||
PointOut
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template<bool Reverse>
|
||||
struct copy_segments
|
||||
<
|
||||
detail::buffer::buffered_ring_collection_tag,
|
||||
Reverse
|
||||
>
|
||||
: detail::copy_segments::copy_segments_multi
|
||||
<
|
||||
detail::copy_segments::copy_segments_ring<Reverse>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiGeometry>
|
||||
struct within
|
||||
<
|
||||
Point,
|
||||
MultiGeometry,
|
||||
point_tag,
|
||||
detail::buffer::buffered_ring_collection_tag
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point,
|
||||
MultiGeometry const& multi, Strategy const& strategy)
|
||||
{
|
||||
return detail::within::point_in_geometry(point, multi, strategy) == 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct is_empty<Geometry, detail::buffer::buffered_ring_collection_tag>
|
||||
: detail::is_empty::multi_is_empty<detail::is_empty::range_is_empty>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct envelope<Geometry, detail::buffer::buffered_ring_collection_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_range
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template<>
|
||||
struct get_ring<detail::buffer::buffered_ring_collection_tag>
|
||||
{
|
||||
template<typename MultiGeometry>
|
||||
static inline typename ring_type<MultiGeometry>::type const& apply(
|
||||
ring_identifier const& id,
|
||||
MultiGeometry const& multi_ring)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(
|
||||
id.multi_index >= 0
|
||||
&& id.multi_index < int(boost::size(multi_ring))
|
||||
);
|
||||
return get_ring<ring_tag>::apply(id, multi_ring[id.multi_index]);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.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/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
// Implements a unique_sub_range for a buffered piece,
|
||||
// the range can return subsequent points
|
||||
// known as "i", "j" and "k" (and further), indexed as 0,1,2,3
|
||||
template <typename Ring>
|
||||
struct unique_sub_range_from_piece
|
||||
{
|
||||
typedef typename boost::range_iterator<Ring const>::type iterator_type;
|
||||
typedef typename geometry::point_type<Ring const>::type point_type;
|
||||
|
||||
unique_sub_range_from_piece(Ring const& ring,
|
||||
iterator_type iterator_at_i, iterator_type iterator_at_j)
|
||||
: m_ring(ring)
|
||||
, m_iterator_at_i(iterator_at_i)
|
||||
, m_iterator_at_j(iterator_at_j)
|
||||
, m_point_retrieved(false)
|
||||
{}
|
||||
|
||||
static inline bool is_first_segment() { return false; }
|
||||
static inline bool is_last_segment() { return false; }
|
||||
|
||||
static inline std::size_t size() { return 3u; }
|
||||
|
||||
inline point_type const& at(std::size_t index) const
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(index < size());
|
||||
switch (index)
|
||||
{
|
||||
case 0 : return *m_iterator_at_i;
|
||||
case 1 : return *m_iterator_at_j;
|
||||
case 2 : return get_point_k();
|
||||
default : return *m_iterator_at_i;
|
||||
}
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
inline point_type const& get_point_k() const
|
||||
{
|
||||
if (! m_point_retrieved)
|
||||
{
|
||||
m_iterator_at_k = advance_one(m_iterator_at_j);
|
||||
m_point_retrieved = true;
|
||||
}
|
||||
return *m_iterator_at_k;
|
||||
}
|
||||
|
||||
inline void circular_advance_one(iterator_type& next) const
|
||||
{
|
||||
++next;
|
||||
if (next == boost::end(m_ring))
|
||||
{
|
||||
next = boost::begin(m_ring) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline iterator_type advance_one(iterator_type it) const
|
||||
{
|
||||
iterator_type result = it;
|
||||
circular_advance_one(result);
|
||||
|
||||
// TODO: we could also use piece-boundaries
|
||||
// to check if the point equals the last one
|
||||
while (geometry::equals(*it, *result))
|
||||
{
|
||||
circular_advance_one(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Ring const& m_ring;
|
||||
iterator_type m_iterator_at_i;
|
||||
iterator_type m_iterator_at_j;
|
||||
mutable iterator_type m_iterator_at_k;
|
||||
mutable bool m_point_retrieved;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Pieces,
|
||||
typename Rings,
|
||||
typename Turns,
|
||||
typename Strategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
class piece_turn_visitor
|
||||
{
|
||||
Pieces const& m_pieces;
|
||||
Rings const& m_rings;
|
||||
Turns& m_turns;
|
||||
Strategy const& m_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
template <typename Piece>
|
||||
inline bool is_adjacent(Piece const& piece1, Piece const& piece2) const
|
||||
{
|
||||
if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return piece1.index == piece2.left_index
|
||||
|| piece1.index == piece2.right_index;
|
||||
}
|
||||
|
||||
template <typename Piece>
|
||||
inline bool is_on_same_convex_ring(Piece const& piece1, Piece const& piece2) const
|
||||
{
|
||||
if (piece1.first_seg_id.multi_index != piece2.first_seg_id.multi_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
|
||||
signed_size_type& index, int dir,
|
||||
Box const& this_bounding_box,
|
||||
Box const& other_bounding_box)
|
||||
{
|
||||
for(; it_begin != it_beyond
|
||||
&& it_begin + 1 != it_beyond
|
||||
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
|
||||
this_bounding_box,
|
||||
other_bounding_box,
|
||||
m_robust_policy);
|
||||
++it_begin, index++)
|
||||
{}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
|
||||
int dir, Box const& this_bounding_box,
|
||||
Box const& other_bounding_box)
|
||||
{
|
||||
while (it_beyond != it_begin
|
||||
&& it_beyond - 1 != it_begin
|
||||
&& it_beyond - 2 != it_begin)
|
||||
{
|
||||
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
|
||||
this_bounding_box, other_bounding_box, m_robust_policy))
|
||||
{
|
||||
--it_beyond;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Piece, typename Section>
|
||||
inline void calculate_turns(Piece const& piece1, Piece const& piece2,
|
||||
Section const& section1, Section const& section2)
|
||||
{
|
||||
typedef typename boost::range_value<Rings const>::type ring_type;
|
||||
typedef typename boost::range_value<Turns const>::type turn_type;
|
||||
|
||||
signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;
|
||||
signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;
|
||||
if (piece1_first_index < 0 || piece2_first_index < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get indices of part of offsetted_rings for this monotonic section:
|
||||
signed_size_type const sec1_first_index = piece1_first_index + section1.begin_index;
|
||||
signed_size_type const sec2_first_index = piece2_first_index + section2.begin_index;
|
||||
|
||||
// index of last point in section, beyond-end is one further
|
||||
signed_size_type const sec1_last_index = piece1_first_index + section1.end_index;
|
||||
signed_size_type const sec2_last_index = piece2_first_index + section2.end_index;
|
||||
|
||||
// get geometry and iterators over these sections
|
||||
ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
|
||||
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];
|
||||
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;
|
||||
move_begin_iterator<0>(it1_first, it1_beyond, index1,
|
||||
section1.directions[0], section1.bounding_box, section2.bounding_box);
|
||||
move_end_iterator<0>(it1_first, it1_beyond,
|
||||
section1.directions[0], section1.bounding_box, section2.bounding_box);
|
||||
move_begin_iterator<1>(it1_first, it1_beyond, index1,
|
||||
section1.directions[1], section1.bounding_box, section2.bounding_box);
|
||||
move_end_iterator<1>(it1_first, it1_beyond,
|
||||
section1.directions[1], section1.bounding_box, section2.bounding_box);
|
||||
|
||||
signed_size_type index2 = sec2_first_index;
|
||||
move_begin_iterator<0>(it2_first, it2_beyond, index2,
|
||||
section2.directions[0], section2.bounding_box, section1.bounding_box);
|
||||
move_end_iterator<0>(it2_first, it2_beyond,
|
||||
section2.directions[0], section2.bounding_box, section1.bounding_box);
|
||||
move_begin_iterator<1>(it2_first, it2_beyond, index2,
|
||||
section2.directions[1], section2.bounding_box, section1.bounding_box);
|
||||
move_end_iterator<1>(it2_first, it2_beyond,
|
||||
section2.directions[1], section2.bounding_box, section1.bounding_box);
|
||||
|
||||
turn_type the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
the_model.operations[0].seg_id = piece1.first_seg_id;
|
||||
the_model.operations[0].seg_id.segment_index = index1; // override
|
||||
|
||||
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
|
||||
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
|
||||
|
||||
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);
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
detail::overlay::assign_policy_only_start_turns
|
||||
> turn_policy;
|
||||
|
||||
turn_policy::apply(unique_sub_range1, unique_sub_range2,
|
||||
the_model,
|
||||
m_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
piece_turn_visitor(Pieces const& pieces,
|
||||
Rings const& ring_collection,
|
||||
Turns& turns,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_pieces(pieces)
|
||||
, m_rings(ring_collection)
|
||||
, m_turns(turns)
|
||||
, m_strategy(strategy)
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
template <typename Section>
|
||||
inline bool apply(Section const& section1, Section const& section2,
|
||||
bool first = true)
|
||||
{
|
||||
boost::ignore_unused(first);
|
||||
|
||||
typedef typename boost::range_value<Pieces const>::type piece_type;
|
||||
piece_type const& piece1 = m_pieces[section1.ring_id.source_index];
|
||||
piece_type const& piece2 = m_pieces[section2.ring_id.source_index];
|
||||
|
||||
if ( piece1.index == piece2.index
|
||||
|| is_adjacent(piece1, piece2)
|
||||
|| is_on_same_convex_ring(piece1, piece2)
|
||||
|| detail::disjoint::disjoint_box_box(section1.bounding_box,
|
||||
section2.bounding_box,
|
||||
m_strategy) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
calculate_turns(piece1, piece2, section1, section2);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
+214
@@ -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
|
||||
+279
@@ -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
|
||||
Vendored
Executable
+120
@@ -0,0 +1,120 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/make/make.hpp>
|
||||
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
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 bool
|
||||
apply(Point const& pi, Point const& pj, Point const& qi, Point const& qj,
|
||||
Point const& vertex, bool equidistant, Point& ip)
|
||||
{
|
||||
// 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.
|
||||
|
||||
using ct = typename coordinate_type<Point>::type;
|
||||
|
||||
auto const p = detail::make::make_infinite_line<ct>(pi, pj);
|
||||
auto const q = detail::make::make_infinite_line<ct>(qi, qj);
|
||||
|
||||
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);
|
||||
static decltype(denominator_pq) const zero = 0;
|
||||
|
||||
if (equidistant)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
|
||||
+512
@@ -0,0 +1,512 @@
|
||||
// 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/range/size.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
|
||||
Vendored
Executable
+300
@@ -0,0 +1,300 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
|
||||
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range/size.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>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
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>
|
||||
inline void apply(Box& total, Original const& original) const
|
||||
{
|
||||
assert_coordinate_type_equal(total, original.m_box);
|
||||
geometry::expand(total, original.m_box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct original_overlaps_box
|
||||
{
|
||||
explicit original_overlaps_box(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename 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,
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
struct include_turn_policy
|
||||
{
|
||||
template <typename Turn>
|
||||
static inline bool apply(Turn const& turn)
|
||||
{
|
||||
return turn.is_turn_traversable;
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
inline bool apply(Box const& box, Turn const& turn) const
|
||||
{
|
||||
if (! turn.is_turn_traversable || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(
|
||||
turn.point, box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
//! Check if specified is in range of specified iterators
|
||||
//! Return value of strategy (true if we can bail out)
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
typename State,
|
||||
typename Point,
|
||||
typename Iterator
|
||||
>
|
||||
inline bool point_in_range(Strategy& strategy, State& state,
|
||||
Point const& point, Iterator begin, Iterator end)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
|
||||
Iterator it = begin;
|
||||
for (Iterator previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
if (! strategy.apply(point, *previous, *it, state))
|
||||
{
|
||||
// We're probably on the boundary
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
typename State,
|
||||
typename Point,
|
||||
typename CoordinateType,
|
||||
typename Iterator
|
||||
>
|
||||
inline bool point_in_section(Strategy& strategy, State& state,
|
||||
Point const& point, CoordinateType const& point_x,
|
||||
Iterator begin, Iterator end,
|
||||
int direction)
|
||||
{
|
||||
if (direction == 0)
|
||||
{
|
||||
// Not a monotonic section, or no change in X-direction
|
||||
return point_in_range(strategy, state, point, begin, end);
|
||||
}
|
||||
|
||||
// We're in a monotonic section in x-direction
|
||||
Iterator it = begin;
|
||||
|
||||
for (Iterator previous = it++; it != end; ++previous, ++it)
|
||||
{
|
||||
// Depending on sections.direction we can quit for this section
|
||||
CoordinateType const previous_x = geometry::get<0>(*previous);
|
||||
|
||||
if (direction == 1 && point_x < previous_x)
|
||||
{
|
||||
// Section goes upwards, x increases, point is is below section
|
||||
return true;
|
||||
}
|
||||
else if (direction == -1 && point_x > previous_x)
|
||||
{
|
||||
// Section goes downwards, x decreases, point is above section
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! strategy.apply(point, *previous, *it, state))
|
||||
{
|
||||
// We're probably on the boundary
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename Point, typename Original, typename PointInGeometryStrategy>
|
||||
inline int point_in_original(Point const& point, Original const& original,
|
||||
PointInGeometryStrategy const& strategy)
|
||||
{
|
||||
typename PointInGeometryStrategy::state_type state;
|
||||
|
||||
if (boost::size(original.m_sections) == 0
|
||||
|| boost::size(original.m_ring) - boost::size(original.m_sections) < 16)
|
||||
{
|
||||
// There are no sections, or it does not profit to walk over sections
|
||||
// instead of over points. Boundary of 16 is arbitrary but can influence
|
||||
// performance
|
||||
point_in_range(strategy, state, point,
|
||||
original.m_ring.begin(), original.m_ring.end());
|
||||
return strategy.result(state);
|
||||
}
|
||||
|
||||
auto const point_x = geometry::get<0>(point);
|
||||
|
||||
// Walk through all monotonic sections of this original
|
||||
for (auto const& section : original.m_sections)
|
||||
{
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box)
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box))
|
||||
{
|
||||
// x-coordinate of point overlaps with section
|
||||
if (! point_in_section(strategy, state, point, point_x,
|
||||
boost::begin(original.m_ring) + section.begin_index,
|
||||
boost::begin(original.m_ring) + section.end_index + 1,
|
||||
section.directions[0]))
|
||||
{
|
||||
// We're probably on the boundary
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strategy.result(state);
|
||||
}
|
||||
|
||||
|
||||
template <typename Turns, typename Strategy>
|
||||
class turn_in_original_visitor
|
||||
{
|
||||
public:
|
||||
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)
|
||||
{
|
||||
if (boost::empty(original.m_ring))
|
||||
{
|
||||
// Skip empty rings
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! turn.is_turn_traversable || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return true;
|
||||
}
|
||||
|
||||
if (geometry::disjoint(turn.point, original.m_box, m_strategy))
|
||||
{
|
||||
// Skip all disjoint
|
||||
return true;
|
||||
}
|
||||
|
||||
int const code = point_in_original(turn.point, original,
|
||||
m_strategy.relate(turn.point, original.m_ring));
|
||||
|
||||
if (code == -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Turn& mutable_turn = m_mutable_turns[turn.turn_index];
|
||||
|
||||
if (code == 0)
|
||||
{
|
||||
// On border of original: always discard
|
||||
mutable_turn.is_turn_traversable = false;
|
||||
}
|
||||
|
||||
// Point is inside an original ring
|
||||
if (original.m_is_interior)
|
||||
{
|
||||
mutable_turn.count_in_original--;
|
||||
}
|
||||
else if (original.m_has_interiors)
|
||||
{
|
||||
mutable_turn.count_in_original++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is an exterior ring and there are no interior rings.
|
||||
// Then we are completely ready with this turn
|
||||
mutable_turn.within_original = true;
|
||||
mutable_turn.count_in_original = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private :
|
||||
Turns& m_mutable_turns;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_ORIGINAL_VISITOR
|
||||
Vendored
Executable
+194
@@ -0,0 +1,194 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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_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/algorithms/comparable_distance.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/dummy_geometries.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename CsTag,
|
||||
typename Turns,
|
||||
typename Pieces,
|
||||
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
|
||||
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
|
||||
{
|
||||
if (op.piece_index == piece.index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Piece const& pc = m_pieces[op.piece_index];
|
||||
if (pc.left_index == piece.index || pc.right_index == piece.index)
|
||||
{
|
||||
if (pc.type == strategy::buffer::buffered_flat_end)
|
||||
{
|
||||
// If it is a flat end, don't compare against its neighbor:
|
||||
// it will always be located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
if (pc.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// If it is concave, the same applies: the IP will be
|
||||
// located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
UmbrellaStrategy const& umbrella_strategy)
|
||||
: m_turns(turns)
|
||||
, m_pieces(pieces)
|
||||
, m_distance_strategy(distance_strategy)
|
||||
, m_umbrella_strategy(umbrella_strategy)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
inline bool apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
if (! turn.is_turn_traversable)
|
||||
{
|
||||
// Already handled
|
||||
return true;
|
||||
}
|
||||
|
||||
if (piece.type == strategy::buffer::buffered_flat_end
|
||||
|| piece.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// Turns cannot be located within flat-end or concave pieces
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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 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);
|
||||
|
||||
if (d < border.m_min_comparable_radius)
|
||||
{
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
mutable_turn.is_turn_traversable = false;
|
||||
return true;
|
||||
}
|
||||
if (d > border.m_max_comparable_radius)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
typename Border::state_type state;
|
||||
if (! border.point_on_piece(turn.point, one_sided,
|
||||
turn.is_linear_end_point, state))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (state.is_inside() && ! state.is_on_boundary())
|
||||
{
|
||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||
mutable_turn.is_turn_traversable = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_TURN_IN_PIECE_VISITOR_HPP
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct calculate_null
|
||||
{
|
||||
template<typename ReturnType, typename Geometry, typename Strategy>
|
||||
static inline ReturnType apply(Geometry const& , Strategy const&)
|
||||
{
|
||||
return ReturnType();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
|
||||
+364
@@ -0,0 +1,364 @@
|
||||
// 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/range/size.hpp>
|
||||
|
||||
#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
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016-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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
class calculate_polygon_sum
|
||||
{
|
||||
template <typename ReturnType, typename Policy, typename Rings, typename Strategy>
|
||||
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
|
||||
{
|
||||
ReturnType sum = ReturnType(0);
|
||||
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
sum += Policy::apply(*it, strategy);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public :
|
||||
template <typename ReturnType, typename Policy, typename Polygon, typename Strategy>
|
||||
static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)
|
||||
{
|
||||
return Policy::apply(exterior_ring(poly), strategy)
|
||||
+ sum_interior_rings<ReturnType, Policy>(interior_rings(poly), strategy)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
|
||||
Vendored
Executable
+119
@@ -0,0 +1,119 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/core/ref.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/point_iterator.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace centroid
|
||||
{
|
||||
|
||||
|
||||
// NOTE: There is no need to translate in other coordinate systems than
|
||||
// cartesian. But if it was needed then one should translate using
|
||||
// CS-specific technique, e.g. in spherical/geographic a translation
|
||||
// vector should contain coordinates being multiplies of 2PI or 360 deg.
|
||||
template <typename Geometry,
|
||||
typename CastedTag = typename tag_cast
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
areal_tag
|
||||
>::type,
|
||||
typename CSTag = typename cs_tag<Geometry>::type>
|
||||
struct translating_transformer
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef boost::reference_wrapper<point_type const> result_type;
|
||||
|
||||
explicit translating_transformer(Geometry const&) {}
|
||||
explicit translating_transformer(point_type const&) {}
|
||||
|
||||
result_type apply(point_type const& pt) const
|
||||
{
|
||||
return result_type(pt);
|
||||
}
|
||||
|
||||
template <typename ResPt>
|
||||
void apply_reverse(ResPt &) const {}
|
||||
};
|
||||
|
||||
// Specialization for Areal Geometries in cartesian CS
|
||||
template <typename Geometry>
|
||||
struct translating_transformer<Geometry, areal_tag, cartesian_tag>
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef point_type result_type;
|
||||
|
||||
explicit translating_transformer(Geometry const& geom)
|
||||
: m_origin(NULL)
|
||||
{
|
||||
geometry::point_iterator<Geometry const>
|
||||
pt_it = geometry::points_begin(geom);
|
||||
if ( pt_it != geometry::points_end(geom) )
|
||||
{
|
||||
m_origin = boost::addressof(*pt_it);
|
||||
}
|
||||
}
|
||||
|
||||
explicit translating_transformer(point_type const& origin)
|
||||
: m_origin(boost::addressof(origin))
|
||||
{}
|
||||
|
||||
result_type apply(point_type const& pt) const
|
||||
{
|
||||
point_type res = pt;
|
||||
if ( m_origin )
|
||||
geometry::subtract_point(res, *m_origin);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename ResPt>
|
||||
void apply_reverse(ResPt & res_pt) const
|
||||
{
|
||||
if ( m_origin )
|
||||
geometry::add_point(res_pt, *m_origin);
|
||||
}
|
||||
|
||||
const point_type * m_origin;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::centroid
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CENTROID_TRANSLATING_TRANSFORMER_HPP
|
||||
Vendored
Executable
+145
@@ -0,0 +1,145 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace closest_feature
|
||||
{
|
||||
|
||||
|
||||
|
||||
// returns the range iterator the realizes the closest
|
||||
// distance between the geometry and the element of the range
|
||||
class geometry_to_range
|
||||
{
|
||||
private:
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename RangeIterator,
|
||||
typename Strategy,
|
||||
typename Distance
|
||||
>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
RangeIterator first,
|
||||
RangeIterator last,
|
||||
Strategy const& strategy,
|
||||
RangeIterator& it_min,
|
||||
Distance& dist_min)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( first != last );
|
||||
|
||||
Distance const zero = Distance(0);
|
||||
|
||||
// start with first distance
|
||||
it_min = first;
|
||||
dist_min = dispatch::distance
|
||||
<
|
||||
Geometry,
|
||||
typename std::iterator_traits<RangeIterator>::value_type,
|
||||
Strategy
|
||||
>::apply(geometry, *it_min, strategy);
|
||||
|
||||
// check if other elements in the range are closer
|
||||
for (RangeIterator it = ++first; it != last; ++it)
|
||||
{
|
||||
Distance dist = dispatch::distance
|
||||
<
|
||||
Geometry,
|
||||
typename std::iterator_traits<RangeIterator>::value_type,
|
||||
Strategy
|
||||
>::apply(geometry, *it, strategy);
|
||||
|
||||
if (geometry::math::equals(dist, zero))
|
||||
{
|
||||
dist_min = dist;
|
||||
it_min = it;
|
||||
return;
|
||||
}
|
||||
else if (dist < dist_min)
|
||||
{
|
||||
dist_min = dist;
|
||||
it_min = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename RangeIterator,
|
||||
typename Strategy,
|
||||
typename Distance
|
||||
>
|
||||
static inline RangeIterator apply(Geometry const& geometry,
|
||||
RangeIterator first,
|
||||
RangeIterator last,
|
||||
Strategy const& strategy,
|
||||
Distance& dist_min)
|
||||
{
|
||||
RangeIterator it_min;
|
||||
apply(geometry, first, last, strategy, it_min, dist_min);
|
||||
|
||||
return it_min;
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename RangeIterator,
|
||||
typename Strategy
|
||||
>
|
||||
static inline RangeIterator apply(Geometry const& geometry,
|
||||
RangeIterator first,
|
||||
RangeIterator last,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Geometry>::type,
|
||||
typename point_type
|
||||
<
|
||||
typename std::iterator_traits
|
||||
<
|
||||
RangeIterator
|
||||
>::value_type
|
||||
>::type
|
||||
>::type dist_min;
|
||||
|
||||
return apply(geometry, first, last, strategy, dist_min);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::closest_feature
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
|
||||
Vendored
Executable
+257
@@ -0,0 +1,257 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace closest_feature
|
||||
{
|
||||
|
||||
|
||||
// returns the segment (pair of iterators) that realizes the closest
|
||||
// distance of the point to the range
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Range,
|
||||
closure_selector Closure
|
||||
>
|
||||
class point_to_point_range
|
||||
{
|
||||
protected:
|
||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
||||
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline void apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
Strategy const& strategy,
|
||||
iterator_type& it_min1,
|
||||
iterator_type& it_min2,
|
||||
Distance& dist_min)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( first != last );
|
||||
|
||||
Distance const zero = Distance(0);
|
||||
|
||||
iterator_type it = first;
|
||||
iterator_type prev = it++;
|
||||
if (it == last)
|
||||
{
|
||||
it_min1 = it_min2 = first;
|
||||
dist_min = strategy.apply(point, *first, *first);
|
||||
return;
|
||||
}
|
||||
|
||||
// start with first segment distance
|
||||
dist_min = strategy.apply(point, *prev, *it);
|
||||
iterator_type prev_min_dist = prev;
|
||||
|
||||
// check if other segments are closer
|
||||
for (++prev, ++it; it != last; ++prev, ++it)
|
||||
{
|
||||
Distance 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;
|
||||
it_min2 = it;
|
||||
return;
|
||||
}
|
||||
else if (dist < dist_min)
|
||||
{
|
||||
dist_min = dist;
|
||||
prev_min_dist = prev;
|
||||
}
|
||||
}
|
||||
|
||||
it_min1 = it_min2 = prev_min_dist;
|
||||
++it_min2;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename std::pair<iterator_type, iterator_type> return_type;
|
||||
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
Strategy const& strategy,
|
||||
Distance& dist_min)
|
||||
{
|
||||
iterator_type it_min1, it_min2;
|
||||
apply(point, first, last, strategy, it_min1, it_min2, dist_min);
|
||||
|
||||
return std::make_pair(it_min1, it_min2);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename boost::range_value<Range>::type
|
||||
>::type dist_min;
|
||||
|
||||
return apply(point, first, last, strategy, dist_min);
|
||||
}
|
||||
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy,
|
||||
Distance& dist_min)
|
||||
{
|
||||
return apply(point,
|
||||
boost::begin(range),
|
||||
boost::end(range),
|
||||
strategy,
|
||||
dist_min);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(point, boost::begin(range), boost::end(range), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// specialization for open ranges
|
||||
template <typename Point, typename Range>
|
||||
class point_to_point_range<Point, Range, open>
|
||||
: point_to_point_range<Point, Range, closed>
|
||||
{
|
||||
private:
|
||||
typedef point_to_point_range<Point, Range, closed> base_type;
|
||||
typedef typename base_type::iterator_type iterator_type;
|
||||
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline void apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
Strategy const& strategy,
|
||||
iterator_type& it_min1,
|
||||
iterator_type& it_min2,
|
||||
Distance& dist_min)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( first != last );
|
||||
|
||||
base_type::apply(point, first, last, strategy,
|
||||
it_min1, it_min2, dist_min);
|
||||
|
||||
iterator_type it_back = --last;
|
||||
Distance const zero = Distance(0);
|
||||
Distance dist = strategy.apply(point, *it_back, *first);
|
||||
|
||||
if (geometry::math::equals(dist, zero))
|
||||
{
|
||||
dist_min = zero;
|
||||
it_min1 = it_back;
|
||||
it_min2 = first;
|
||||
}
|
||||
else if (dist < dist_min)
|
||||
{
|
||||
dist_min = dist;
|
||||
it_min1 = it_back;
|
||||
it_min2 = first;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename std::pair<iterator_type, iterator_type> return_type;
|
||||
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
Strategy const& strategy,
|
||||
Distance& dist_min)
|
||||
{
|
||||
iterator_type it_min1, it_min2;
|
||||
|
||||
apply(point, first, last, strategy, it_min1, it_min2, dist_min);
|
||||
|
||||
return std::make_pair(it_min1, it_min2);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
iterator_type first,
|
||||
iterator_type last,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
Point,
|
||||
typename boost::range_value<Range>::type
|
||||
>::type distance_return_type;
|
||||
|
||||
distance_return_type dist_min;
|
||||
|
||||
return apply(point, first, last, strategy, dist_min);
|
||||
}
|
||||
|
||||
template <typename Strategy, typename Distance>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy,
|
||||
Distance& dist_min)
|
||||
{
|
||||
return apply(point,
|
||||
boost::begin(range),
|
||||
boost::end(range),
|
||||
strategy,
|
||||
dist_min);
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline return_type apply(Point const& point,
|
||||
Range const& range,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(point, boost::begin(range), boost::end(range), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::closest_feature
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
|
||||
Vendored
Executable
+202
@@ -0,0 +1,202 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/index/rtree.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace closest_feature
|
||||
{
|
||||
|
||||
|
||||
// returns a pair of a objects where the first is an object of the
|
||||
// r-tree range and the second an object of the query range that
|
||||
// realizes the closest feature of the two ranges
|
||||
class range_to_range_rtree
|
||||
{
|
||||
private:
|
||||
template
|
||||
<
|
||||
typename RTreeRangeIterator,
|
||||
typename QueryRangeIterator,
|
||||
typename Strategies,
|
||||
typename RTreeValueType,
|
||||
typename Distance
|
||||
>
|
||||
static inline void apply(RTreeRangeIterator rtree_first,
|
||||
RTreeRangeIterator rtree_last,
|
||||
QueryRangeIterator queries_first,
|
||||
QueryRangeIterator queries_last,
|
||||
Strategies const& strategies,
|
||||
RTreeValueType& rtree_min,
|
||||
QueryRangeIterator& qit_min,
|
||||
Distance& dist_min)
|
||||
{
|
||||
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 );
|
||||
|
||||
Distance const zero = Distance(0);
|
||||
dist_min = zero;
|
||||
|
||||
// create -- packing algorithm
|
||||
rtree_type rt(rtree_first, rtree_last,
|
||||
index_parameters_type(index::linear<8>(), strategies));
|
||||
|
||||
RTreeValueType t_v;
|
||||
bool first = true;
|
||||
|
||||
for (QueryRangeIterator qit = queries_first;
|
||||
qit != queries_last; ++qit, first = false)
|
||||
{
|
||||
std::size_t n = rt.query(index::nearest(*qit, 1), &t_v);
|
||||
|
||||
BOOST_GEOMETRY_ASSERT( n > 0 );
|
||||
// n above is unused outside BOOST_GEOMETRY_ASSERT,
|
||||
// hence the call to boost::ignore_unused below
|
||||
//
|
||||
// however, t_v (initialized by the call to rt.query(...))
|
||||
// is used below, which is why we cannot put the call to
|
||||
// rt.query(...) inside BOOST_GEOMETRY_ASSERT
|
||||
boost::ignore_unused(n);
|
||||
|
||||
Distance dist = dispatch::distance
|
||||
<
|
||||
RTreeValueType,
|
||||
typename std::iterator_traits
|
||||
<
|
||||
QueryRangeIterator
|
||||
>::value_type,
|
||||
Strategies
|
||||
>::apply(t_v, *qit, strategies);
|
||||
|
||||
if (first || dist < dist_min)
|
||||
{
|
||||
dist_min = dist;
|
||||
rtree_min = t_v;
|
||||
qit_min = qit;
|
||||
if ( math::equals(dist_min, zero) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename RTreeRangeIterator, typename QueryRangeIterator>
|
||||
struct return_type
|
||||
{
|
||||
typedef std::pair
|
||||
<
|
||||
typename std::iterator_traits<RTreeRangeIterator>::value_type,
|
||||
QueryRangeIterator
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RTreeRangeIterator,
|
||||
typename QueryRangeIterator,
|
||||
typename Strategy,
|
||||
typename Distance
|
||||
>
|
||||
static inline typename return_type
|
||||
<
|
||||
RTreeRangeIterator, QueryRangeIterator
|
||||
>::type apply(RTreeRangeIterator rtree_first,
|
||||
RTreeRangeIterator rtree_last,
|
||||
QueryRangeIterator queries_first,
|
||||
QueryRangeIterator queries_last,
|
||||
Strategy const& strategy,
|
||||
Distance& dist_min)
|
||||
{
|
||||
typedef typename std::iterator_traits
|
||||
<
|
||||
RTreeRangeIterator
|
||||
>::value_type rtree_value_type;
|
||||
|
||||
rtree_value_type rtree_min;
|
||||
QueryRangeIterator qit_min;
|
||||
|
||||
apply(rtree_first, rtree_last, queries_first, queries_last,
|
||||
strategy, rtree_min, qit_min, dist_min);
|
||||
|
||||
return std::make_pair(rtree_min, qit_min);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RTreeRangeIterator,
|
||||
typename QueryRangeIterator,
|
||||
typename Strategy
|
||||
>
|
||||
static inline typename return_type
|
||||
<
|
||||
RTreeRangeIterator, QueryRangeIterator
|
||||
>::type apply(RTreeRangeIterator rtree_first,
|
||||
RTreeRangeIterator rtree_last,
|
||||
QueryRangeIterator queries_first,
|
||||
QueryRangeIterator queries_last,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename std::iterator_traits
|
||||
<
|
||||
RTreeRangeIterator
|
||||
>::value_type rtree_value_type;
|
||||
|
||||
typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<rtree_value_type>::type,
|
||||
typename point_type
|
||||
<
|
||||
typename std::iterator_traits
|
||||
<
|
||||
QueryRangeIterator
|
||||
>::value_type
|
||||
>::type
|
||||
>::type dist_min;
|
||||
|
||||
return apply(rtree_first, rtree_last, queries_first, queries_last,
|
||||
strategy, dist_min);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::closest_feature
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_RANGE_TO_RANGE_HPP
|
||||
Vendored
Executable
+28
@@ -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
|
||||
Vendored
Executable
+225
@@ -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
|
||||
Vendored
Executable
+261
@@ -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
|
||||
Vendored
Executable
+155
@@ -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
|
||||
Vendored
Executable
+327
@@ -0,0 +1,327 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range/size.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/linestring.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace closest_points
|
||||
{
|
||||
|
||||
|
||||
struct multipoint_to_multipoint
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiPoint1,
|
||||
typename MultiPoint2,
|
||||
typename Segment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Segment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (boost::size(multipoint1) < boost::size(multipoint2))
|
||||
{
|
||||
point_or_segment_range_to_geometry_rtree::apply(
|
||||
boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
multipoint1,
|
||||
shortest_seg,
|
||||
strategies);
|
||||
detail::closest_points::swap_segment_points::apply(shortest_seg);
|
||||
return;
|
||||
}
|
||||
point_or_segment_range_to_geometry_rtree::apply(
|
||||
boost::begin(multipoint1),
|
||||
boost::end(multipoint1),
|
||||
multipoint2,
|
||||
shortest_seg,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
struct multipoint_to_linear
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiPoint,
|
||||
typename Linear,
|
||||
typename Segment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(MultiPoint const& multipoint,
|
||||
Linear const& linear,
|
||||
Segment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
point_or_segment_range_to_geometry_rtree::apply(
|
||||
boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
linear,
|
||||
shortest_seg,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
struct linear_to_multipoint
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Linear,
|
||||
typename MultiPoint,
|
||||
typename Segment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Linear const& linear,
|
||||
MultiPoint const& multipoint,
|
||||
Segment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
multipoint_to_linear::apply(multipoint, linear, shortest_seg, strategies);
|
||||
detail::closest_points::swap_segment_points::apply(shortest_seg);
|
||||
}
|
||||
};
|
||||
|
||||
struct segment_to_multipoint
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename MultiPoint,
|
||||
typename OutSegment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Segment const& segment,
|
||||
MultiPoint const& multipoint,
|
||||
OutSegment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
using linestring_type = geometry::model::linestring
|
||||
<
|
||||
typename point_type<Segment>::type
|
||||
>;
|
||||
linestring_type linestring;
|
||||
convert(segment, linestring);
|
||||
multipoint_to_linear::apply(multipoint, linestring, shortest_seg, strategies);
|
||||
detail::closest_points::swap_segment_points::apply(shortest_seg);
|
||||
}
|
||||
};
|
||||
|
||||
struct multipoint_to_segment
|
||||
{
|
||||
template
|
||||
<
|
||||
typename MultiPoint,
|
||||
typename Segment,
|
||||
typename OutSegment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(MultiPoint const& multipoint,
|
||||
Segment const& segment,
|
||||
OutSegment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
using linestring_type = geometry::model::linestring
|
||||
<
|
||||
typename point_type<Segment>::type
|
||||
>;
|
||||
linestring_type linestring;
|
||||
convert(segment, linestring);
|
||||
multipoint_to_linear::apply(multipoint, linestring, shortest_seg,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct multipoint_to_areal
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
template <typename Areal, typename Strategies>
|
||||
struct covered_by_areal
|
||||
{
|
||||
covered_by_areal(Areal const& areal, Strategies const& strategy)
|
||||
: m_areal(areal), m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
inline bool operator()(Point const& point) const
|
||||
{
|
||||
return geometry::covered_by(point, m_areal, m_strategy);
|
||||
}
|
||||
|
||||
Areal const& m_areal;
|
||||
Strategies const& m_strategy;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiPoint,
|
||||
typename Areal,
|
||||
typename Segment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(MultiPoint const& multipoint,
|
||||
Areal const& areal,
|
||||
Segment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
covered_by_areal<Areal, Strategies> predicate(areal, strategies);
|
||||
|
||||
auto it = std::find_if(
|
||||
boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
predicate);
|
||||
|
||||
if (it != boost::end(multipoint))
|
||||
{
|
||||
return set_segment_from_points::apply(*it, *it, shortest_seg);
|
||||
|
||||
}
|
||||
|
||||
point_or_segment_range_to_geometry_rtree::apply(
|
||||
boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
areal,
|
||||
shortest_seg,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
struct areal_to_multipoint
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Areal,
|
||||
typename MultiPoint,
|
||||
typename Segment,
|
||||
typename Strategies
|
||||
>
|
||||
static inline void apply(Areal const& areal,
|
||||
MultiPoint const& multipoint,
|
||||
Segment& shortest_seg,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
multipoint_to_areal::apply(multipoint, areal, shortest_seg, strategies);
|
||||
detail::closest_points::swap_segment_points::apply(shortest_seg);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::closest_points
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2>
|
||||
struct closest_points
|
||||
<
|
||||
MultiPoint1, MultiPoint2,
|
||||
multi_point_tag, multi_point_tag,
|
||||
false
|
||||
> : detail::closest_points::multipoint_to_multipoint
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear>
|
||||
struct closest_points
|
||||
<
|
||||
MultiPoint, Linear,
|
||||
multi_point_tag, linear_tag,
|
||||
false
|
||||
> : detail::closest_points::multipoint_to_linear
|
||||
{};
|
||||
|
||||
|
||||
template <typename Linear, typename MultiPoint>
|
||||
struct closest_points
|
||||
<
|
||||
Linear, MultiPoint,
|
||||
linear_tag, multi_point_tag,
|
||||
false
|
||||
> : detail::closest_points::linear_to_multipoint
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Segment>
|
||||
struct closest_points
|
||||
<
|
||||
MultiPoint, Segment,
|
||||
multi_point_tag, segment_tag,
|
||||
false
|
||||
> : detail::closest_points::multipoint_to_segment
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment, typename MultiPoint>
|
||||
struct closest_points
|
||||
<
|
||||
Segment, MultiPoint,
|
||||
segment_tag, multi_point_tag,
|
||||
false
|
||||
> : detail::closest_points::segment_to_multipoint
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal>
|
||||
struct closest_points
|
||||
<
|
||||
MultiPoint, Areal,
|
||||
multi_point_tag, areal_tag,
|
||||
false
|
||||
> : detail::closest_points::multipoint_to_areal
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename MultiPoint>
|
||||
struct closest_points
|
||||
<
|
||||
Areal, MultiPoint,
|
||||
areal_tag, multi_point_tag,
|
||||
false
|
||||
> : detail::closest_points::areal_to_multipoint
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
Vendored
Executable
+456
@@ -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
|
||||
Vendored
Executable
+110
@@ -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
|
||||
Vendored
Executable
+145
@@ -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
|
||||
Vendored
Executable
+69
@@ -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
|
||||
Vendored
Executable
+24
@@ -0,0 +1,24 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/implementation.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_IMPLEMENTATION_HPP
|
||||
Vendored
Executable
+289
@@ -0,0 +1,289 @@
|
||||
// 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) 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 Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_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/strategies/distance/comparable.hpp>
|
||||
#include <boost/geometry/strategies/distance/services.hpp>
|
||||
|
||||
|
||||
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>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
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_strategies_type
|
||||
>::apply(geometry1,
|
||||
geometry2,
|
||||
comparable_strategies_type(
|
||||
strategy_converter<Strategy>::get(strategy)));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct comparable_distance<default_strategy, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
using comparable_strategy_type = strategies::distance::detail::comparable
|
||||
<
|
||||
typename strategies::distance::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type
|
||||
>;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, comparable_strategy_type
|
||||
>::apply(geometry1, geometry2, comparable_strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename geometry::tag<Geometry1>::type,
|
||||
typename Tag2 = typename geometry::tag<Geometry2>::type
|
||||
>
|
||||
struct comparable_distance
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::comparable_distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{comparable distance measurement} \brief_strategy
|
||||
\ingroup distance
|
||||
\details The free function comparable_distance does not necessarily calculate the distance,
|
||||
but it calculates a distance measure such that two distances are comparable to each other.
|
||||
For example: for the Cartesian coordinate system, Pythagoras is used but the square root
|
||||
is not taken, which makes it faster and the results of two point pairs can still be
|
||||
compared to each other.
|
||||
\tparam Geometry1 first geometry type
|
||||
\tparam Geometry2 second geometry type
|
||||
\tparam Strategy \tparam_strategy{Distance}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{distance}
|
||||
\return \return_calc{comparable distance}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline auto comparable_distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return resolve_dynamic::comparable_distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{comparable distance measurement}
|
||||
\ingroup distance
|
||||
\details The free function comparable_distance does not necessarily calculate the distance,
|
||||
but it calculates a distance measure such that two distances are comparable to each other.
|
||||
For example: for the Cartesian coordinate system, Pythagoras is used but the square root
|
||||
is not taken, which makes it faster and the results of two point pairs can still be
|
||||
compared to each other.
|
||||
\tparam Geometry1 first geometry type
|
||||
\tparam Geometry2 second geometry type
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_calc{comparable distance}
|
||||
|
||||
\qbk{[include reference/algorithms/comparable_distance.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline auto comparable_distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
return geometry::comparable_distance(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COMPARABLE_DISTANCE_INTERFACE_HPP
|
||||
Vendored
Executable
+80
@@ -0,0 +1,80 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace conversion
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Source,
|
||||
typename Destination,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct indexed_to_indexed
|
||||
{
|
||||
static inline void apply(Source const& source, Destination& destination)
|
||||
{
|
||||
typedef typename coordinate_type<Destination>::type coordinate_type;
|
||||
|
||||
geometry::set<min_corner, Dimension>(destination,
|
||||
boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<min_corner, Dimension>(source)));
|
||||
geometry::set<max_corner, Dimension>(destination,
|
||||
boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<max_corner, Dimension>(source)));
|
||||
|
||||
indexed_to_indexed
|
||||
<
|
||||
Source, Destination,
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(source, destination);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Source,
|
||||
typename Destination,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct indexed_to_indexed<Source, Destination, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Source const& , Destination& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::conversion
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
|
||||
|
||||
// Note: extracted from "convert.hpp" to avoid circular references convert/append
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace conversion
|
||||
{
|
||||
|
||||
|
||||
// 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
|
||||
{
|
||||
static inline void apply(Source const& source, Destination& destination)
|
||||
{
|
||||
typedef typename coordinate_type<Destination>::type coordinate_type;
|
||||
|
||||
set<Dimension>(destination, boost::numeric_cast<coordinate_type>(get<Dimension>(source)));
|
||||
point_to_point<Source, Destination, Dimension + 1, DimensionCount>::apply(source, destination);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source, typename Destination, std::size_t DimensionCount>
|
||||
struct point_to_point<Source, Destination, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline void apply(Source const& , Destination& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Source, typename Destination>
|
||||
inline void convert_point_to_point(Source const& source, Destination& destination)
|
||||
{
|
||||
point_to_point<Source, Destination, 0, dimension<Destination>::value>::apply(source, destination);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::conversion
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
|
||||
Vendored
Executable
+312
@@ -0,0 +1,312 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
// 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_GRAHAM_ANDREW_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range/size.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/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
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace convex_hull
|
||||
{
|
||||
|
||||
// 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)
|
||||
{
|
||||
bool first = true;
|
||||
in_proxy.for_each_range([&](auto const& range)
|
||||
{
|
||||
if (boost::empty(range))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First iterate through this range
|
||||
// (this two-stage approach avoids many point copies,
|
||||
// because iterators are kept in memory. Because iterators are
|
||||
// not persistent (in MSVC) this approach is not applicable
|
||||
// for more ranges together)
|
||||
|
||||
auto left_it = boost::begin(range);
|
||||
auto right_it = boost::begin(range);
|
||||
|
||||
auto it = boost::begin(range);
|
||||
for (++it; it != boost::end(range); ++it)
|
||||
{
|
||||
if (less(*it, *left_it))
|
||||
{
|
||||
left_it = it;
|
||||
}
|
||||
|
||||
if (less(*right_it, *it))
|
||||
{
|
||||
right_it = it;
|
||||
}
|
||||
}
|
||||
|
||||
// Then compare with earlier
|
||||
if (first)
|
||||
{
|
||||
// First time, assign left/right
|
||||
left = *left_it;
|
||||
right = *right_it;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Next time, check if this range was left/right from
|
||||
// the extremes already collected
|
||||
if (less(*left_it, left))
|
||||
{
|
||||
left = *left_it;
|
||||
}
|
||||
|
||||
if (less(right, *right_it))
|
||||
{
|
||||
right = *right_it;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
in_proxy.for_each_range([&](auto const& range)
|
||||
{
|
||||
// Put points in one of the two output sequences
|
||||
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);
|
||||
switch(dir)
|
||||
{
|
||||
case 1 : // left side
|
||||
upper_points.push_back(*it);
|
||||
break;
|
||||
case -1 : // right side
|
||||
lower_points.push_back(*it);
|
||||
break;
|
||||
|
||||
// 0: on line most_left-most_right,
|
||||
// or most_left, or most_right,
|
||||
// -> all never part of hull
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Graham scan algorithm to calculate convex hull
|
||||
*/
|
||||
template <typename InputPoint>
|
||||
class graham_andrew
|
||||
{
|
||||
typedef InputPoint point_type;
|
||||
typedef typename std::vector<point_type> container_type;
|
||||
|
||||
class partitions
|
||||
{
|
||||
friend class graham_andrew;
|
||||
|
||||
container_type m_lower_hull;
|
||||
container_type m_upper_hull;
|
||||
container_type m_copied_input;
|
||||
};
|
||||
|
||||
public:
|
||||
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);
|
||||
|
||||
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
|
||||
// This makes use of the geometry::less/greater predicates
|
||||
|
||||
// For the left boundary it is important that multiple points
|
||||
// are sorted from bottom to top. Therefore the less predicate
|
||||
// does not take the x-only template parameter (this fixes ticket #6019.
|
||||
// For the right boundary it is not necessary (though also not harmful),
|
||||
// because points are sorted from bottom to top in a later stage.
|
||||
// For symmetry and to get often more balanced lower/upper halves
|
||||
// we keep it.
|
||||
|
||||
point_type most_left, most_right;
|
||||
|
||||
geometry::less_exact<point_type, -1, Strategy> less;
|
||||
|
||||
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::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)
|
||||
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>(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 <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,
|
||||
SideStrategy const& side)
|
||||
{
|
||||
output.push_back(left);
|
||||
for (auto const& i : input)
|
||||
{
|
||||
add_to_hull<Factor>(i, output, side);
|
||||
}
|
||||
add_to_hull<Factor>(right, output, side);
|
||||
}
|
||||
|
||||
|
||||
template <int Factor, typename SideStrategy>
|
||||
static inline void add_to_hull(point_type const& p, container_type& output,
|
||||
SideStrategy const& side)
|
||||
{
|
||||
output.push_back(p);
|
||||
std::size_t output_size = output.size();
|
||||
while (output_size >= 3)
|
||||
{
|
||||
auto rit = output.rbegin();
|
||||
point_type const last = *rit++;
|
||||
point_type const& last2 = *rit++;
|
||||
|
||||
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.
|
||||
output.pop_back();
|
||||
output.pop_back();
|
||||
output.push_back(last);
|
||||
output_size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename OutputIterator>
|
||||
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);
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(closed ? !boost::empty(second) : boost::size(second) > 1);
|
||||
std::copy(++boost::rbegin(second), // skip the first Point
|
||||
closed ? boost::rend(second) : --boost::rend(second), // skip the last Point if open
|
||||
out);
|
||||
|
||||
typedef typename boost::range_size<container_type>::type size_type;
|
||||
size_type const count = boost::size(first) + boost::size(second) - 1;
|
||||
// count describes a closed case but comparison with min size of closed
|
||||
// gives the result compatible also with open
|
||||
// here core_detail::closure::minimum_ring_size<closed> could be used
|
||||
if (count < 4)
|
||||
{
|
||||
// there should be only one missing
|
||||
*out++ = *boost::begin(first);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::convex_hull
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_GRAHAM_ANDREW_HPP
|
||||
+619
@@ -0,0 +1,619 @@
|
||||
// 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/range/size.hpp>
|
||||
|
||||
#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
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014-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.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range/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>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace counting
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t D>
|
||||
struct other_count
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline std::size_t apply(Geometry const&)
|
||||
{
|
||||
return D;
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
static inline std::size_t apply(Geometry const&, bool)
|
||||
{
|
||||
return D;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename RangeCount>
|
||||
struct polygon_count
|
||||
{
|
||||
template <typename Polygon>
|
||||
static inline std::size_t apply(Polygon const& poly)
|
||||
{
|
||||
std::size_t n = RangeCount::apply(exterior_ring(poly));
|
||||
|
||||
auto const& rings = interior_rings(poly);
|
||||
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
n += RangeCount::apply(*it);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename SingleCount>
|
||||
struct multi_count
|
||||
{
|
||||
template <typename MultiGeometry>
|
||||
static inline std::size_t apply(MultiGeometry const& multi)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
|
||||
{
|
||||
n += SingleCount::apply(*it);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::counting
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COUNTING_HPP
|
||||
Vendored
Executable
+349
@@ -0,0 +1,349 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
// (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_COVERED_BY_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#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
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace covered_by {
|
||||
|
||||
struct use_point_in_geometry
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::within::covered_by_point_geometry(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
struct use_relate
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::relate::relate_impl
|
||||
<
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::covered_by
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
// P/P
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct covered_by<Point1, Point2, point_tag, point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPoint>
|
||||
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Point>
|
||||
struct covered_by<MultiPoint, Point, multi_point_tag, point_tag>
|
||||
: public detail::within::multi_point_point
|
||||
{};
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2>
|
||||
struct covered_by<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
|
||||
: public detail::within::multi_point_multi_point
|
||||
{};
|
||||
|
||||
// P/L
|
||||
|
||||
template <typename Point, typename Segment>
|
||||
struct covered_by<Point, Segment, point_tag, segment_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Linestring>
|
||||
struct covered_by<Point, Linestring, point_tag, linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiLinestring>
|
||||
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Segment>
|
||||
struct covered_by<MultiPoint, Segment, multi_point_tag, segment_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Linestring>
|
||||
struct covered_by<MultiPoint, Linestring, multi_point_tag, linestring_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename MultiLinestring>
|
||||
struct covered_by<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
|
||||
: public detail::within::multi_point_multi_geometry<false>
|
||||
{};
|
||||
|
||||
// P/A
|
||||
|
||||
template <typename Point, typename Ring>
|
||||
struct covered_by<Point, Ring, point_tag, ring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Polygon>
|
||||
struct covered_by<Point, Polygon, point_tag, polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPolygon>
|
||||
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Ring>
|
||||
struct covered_by<MultiPoint, Ring, multi_point_tag, ring_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Polygon>
|
||||
struct covered_by<MultiPoint, Polygon, multi_point_tag, polygon_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename MultiPolygon>
|
||||
struct covered_by<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
|
||||
: public detail::within::multi_point_multi_geometry<false>
|
||||
{};
|
||||
|
||||
// L/L
|
||||
|
||||
template <typename Linestring1, typename Linestring2>
|
||||
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiLinestring>
|
||||
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Linestring>
|
||||
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring1, typename MultiLinestring2>
|
||||
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// L/A
|
||||
|
||||
template <typename Linestring, typename Ring>
|
||||
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Ring>
|
||||
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename Polygon>
|
||||
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Polygon>
|
||||
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiPolygon>
|
||||
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename MultiPolygon>
|
||||
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// A/A
|
||||
|
||||
template <typename Ring1, typename Ring2>
|
||||
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename Polygon>
|
||||
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Ring>
|
||||
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename MultiPolygon>
|
||||
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Ring>
|
||||
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename MultiPolygon>
|
||||
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Polygon>
|
||||
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon1, typename MultiPolygon2>
|
||||
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// 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
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
|
||||
Vendored
Executable
+46
@@ -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
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
// (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_COVERED_BY_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/within/interface.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.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
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct covered_by
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::within::check<Geometry1, Geometry2, Strategy>();
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
assert_dimension_equal<Geometry1, Geometry2>();
|
||||
|
||||
return dispatch::covered_by
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename 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 strategies::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return covered_by
|
||||
<
|
||||
strategy_type
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic {
|
||||
|
||||
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>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag2>
|
||||
struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool result = false;
|
||||
traits::visit<Geometry1>::apply([&](auto const& g1)
|
||||
{
|
||||
result = resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, geometry2, strategy);
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1>
|
||||
struct covered_by<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool result = false;
|
||||
traits::visit<Geometry2>::apply([&](auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, g2, strategy);
|
||||
}, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool result = false;
|
||||
traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::covered_by
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border}
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
\note The default strategy is used for covered_by detection
|
||||
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
\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_dynamic::covered_by
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border} \brief_strategy
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\param strategy strategy to be used
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_dynamic::covered_by
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
|
||||
+288
@@ -0,0 +1,288 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// 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
|
||||
|
||||
// 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_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>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename CSTag>
|
||||
struct direction_code_impl
|
||||
{
|
||||
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
|
||||
"Not implemented for this coordinate system.",
|
||||
CSTag);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct direction_code_impl<cartesian_tag>
|
||||
{
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
|
||||
Point2 const& point)
|
||||
{
|
||||
using calc_t = typename geometry::select_coordinate_type
|
||||
<
|
||||
PointSegmentA, PointSegmentB, Point2
|
||||
>::type;
|
||||
|
||||
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 const sv = arithmetic::side_value(line, point);
|
||||
static calc_t const zero = 0;
|
||||
return sv == zero ? 0 : sv > zero ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct direction_code_impl<spherical_equatorial_tag>
|
||||
{
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
|
||||
Point2 const& p)
|
||||
{
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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_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))) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: as opposed to the implementation for cartesian CS
|
||||
// here point b is the origin
|
||||
|
||||
calc_t const dlon1 = math::longitude_distance_signed<units_t, calc_t>(b0, a0);
|
||||
calc_t const dlon2 = math::longitude_distance_signed<units_t, calc_t>(b0, p0);
|
||||
|
||||
bool is_antilon1 = false, is_antilon2 = false;
|
||||
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 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)
|
||||
{
|
||||
s1 = dlon1 > 0 ? 1 : -1;
|
||||
s2 = dlon2 > 0 ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = dlat1 > 0 ? 1 : -1;
|
||||
s2 = dlat2 > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return s1 == s2 ? -1 : 1;
|
||||
}
|
||||
|
||||
template <typename Units, typename T>
|
||||
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
|
||||
{
|
||||
using constants = math::detail::constants_on_spheroid<T, Units>;
|
||||
static T const pi = constants::half_period();
|
||||
static T const c0 = 0;
|
||||
|
||||
T res = lat2 - lat1;
|
||||
|
||||
is_antilon = math::equals(math::abs(lon_ds), pi);
|
||||
if (is_antilon)
|
||||
{
|
||||
res = lat2 + lat1;
|
||||
if (res >= c0)
|
||||
res = pi - res;
|
||||
else
|
||||
res = -pi - res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct direction_code_impl<spherical_polar_tag>
|
||||
{
|
||||
template <typename PointSegmentA, typename PointSegmentB, typename Point2>
|
||||
static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
|
||||
Point2 p)
|
||||
{
|
||||
using constants_sa_t = 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 cs_angular_units<Point2>::type
|
||||
>;
|
||||
|
||||
geometry::set<1>(segment_a,
|
||||
constants_sa_t::max_latitude() - geometry::get<1>(segment_a));
|
||||
geometry::set<1>(segment_b,
|
||||
constants_sa_t::max_latitude() - geometry::get<1>(segment_b));
|
||||
geometry::set<1>(p,
|
||||
constants_p_t::max_latitude() - geometry::get<1>(p));
|
||||
|
||||
return direction_code_impl
|
||||
<
|
||||
spherical_equatorial_tag
|
||||
>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
};
|
||||
|
||||
// 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)
|
||||
// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
|
||||
// Returns 1 if p goes forward, so extends (a,b)
|
||||
// Returns 0 if p is equal with b, or if (a,b) is degenerate
|
||||
// Note that it does not do any collinearity test, that should be done before
|
||||
// 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<CSTag>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/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/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/for_each.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool point_on_border_covered_by(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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 Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool rings_containing(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::detail::any_range_of(geometry2, [&](auto const& range)
|
||||
{
|
||||
return point_on_border_covered_by(range, geometry1, strategy);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct areal_areal
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no intersection of segments, they might located
|
||||
// inside each other
|
||||
|
||||
// We check that using a point on the border (external boundary),
|
||||
// and see if that is contained in the other geometry. And vice versa.
|
||||
|
||||
if ( rings_containing(geometry1, geometry2, strategy)
|
||||
|| rings_containing(geometry2, geometry1, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Areal, typename Box>
|
||||
struct areal_box
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Areal const& areal,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (! geometry::all_segments_of(areal, [&](auto const& s)
|
||||
{
|
||||
return disjoint_segment_box::apply(s, box, strategy);
|
||||
}) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Areal1, typename Areal2>
|
||||
struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false>
|
||||
: detail::disjoint::areal_areal<Areal1, Areal2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Box>
|
||||
struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>
|
||||
: detail::disjoint::areal_box<Areal, Box>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect if boxes are disjoint
|
||||
\note Is used from other algorithms, declared separately
|
||||
to avoid circular references
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2, 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);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount>
|
||||
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
typedef decltype(strategy.disjoint(box1, box2)) strategy_type;
|
||||
return strategy_type::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_BOX_BOX_HPP
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_IMPLEMENTATION_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/areal_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
|
||||
|
||||
#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
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/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/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/relate/services.hpp>
|
||||
|
||||
|
||||
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>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::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 strategies::relate::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::disjoint
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic {
|
||||
|
||||
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)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions
|
||||
<
|
||||
Geometry1 const,
|
||||
Geometry2 const
|
||||
>();
|
||||
|
||||
return resolve_strategy::disjoint
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct disjoint<Geometry1, Geometry2, true, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// 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>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{are disjoint}
|
||||
\ingroup disjoint
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Disjoint}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{disjoint}
|
||||
\return \return_check2{are disjoint}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/disjoint.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool disjoint(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_dynamic::disjoint
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{are disjoint}
|
||||
\ingroup disjoint
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_check2{are disjoint}
|
||||
|
||||
\qbk{[include reference/algorithms/disjoint.qbk]}
|
||||
\qbk{
|
||||
[heading Examples]
|
||||
[disjoint]
|
||||
[disjoint_output]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool disjoint(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_dynamic::disjoint
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_INTERFACE_HPP
|
||||
+290
@@ -0,0 +1,290 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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 Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#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>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/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/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename Geometry1, typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
|
||||
struct disjoint_no_intersections_policy
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Tag1>
|
||||
struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
// TODO: use partition or rtree on g2
|
||||
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))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Geometry1, typename Geometry2,
|
||||
typename NoIntersectionsPolicy
|
||||
= disjoint_no_intersections_policy<Geometry1, Geometry2> >
|
||||
struct disjoint_linear_areal
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
// if there are intersections - return false
|
||||
if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return NoIntersectionsPolicy::apply(g1, g2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Areal,
|
||||
typename Tag = typename tag<Areal>::type
|
||||
>
|
||||
struct disjoint_segment_areal
|
||||
: not_implemented<Segment, Areal>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment, typename Polygon>
|
||||
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
|
||||
{
|
||||
|
||||
template <typename InteriorRings, typename Strategy>
|
||||
static inline
|
||||
bool check_interior_rings(InteriorRings const& interior_rings,
|
||||
Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using ring_type = typename boost::range_value<InteriorRings>::type;
|
||||
|
||||
using unary_predicate_type = unary_disjoint_geometry_to_query_geometry
|
||||
<
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
template <typename IntersectionStrategy>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Polygon const& polygon,
|
||||
IntersectionStrategy const& 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))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typename point_type<Segment>::type p;
|
||||
detail::assign_point_from_index<0>(segment, p);
|
||||
|
||||
return ! geometry::covered_by(p, polygon, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Segment, typename MultiPolygon>
|
||||
struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
|
||||
{
|
||||
template <typename IntersectionStrategy>
|
||||
static inline bool apply(Segment const& segment, MultiPolygon const& multipolygon,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
return multirange_constant_size_geometry
|
||||
<
|
||||
MultiPolygon, Segment
|
||||
>::apply(multipolygon, segment, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Segment, typename Ring>
|
||||
struct disjoint_segment_areal<Segment, Ring, ring_tag>
|
||||
{
|
||||
template <typename IntersectionStrategy>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Ring const& ring,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
if (! disjoint_range_segment_or_box<Ring, Segment>::apply(ring, segment, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typename point_type<Segment>::type p;
|
||||
detail::assign_point_from_index<0>(segment, p);
|
||||
|
||||
return ! geometry::covered_by(p, ring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Areal>
|
||||
struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>
|
||||
: public detail::disjoint::disjoint_linear_areal<Linear, Areal>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Linear>
|
||||
struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Areal const& areal, Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::disjoint::disjoint_linear_areal
|
||||
<
|
||||
Linear, Areal
|
||||
>::apply(linear, areal, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Areal, typename Segment>
|
||||
struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Areal const& g1, Segment const& g2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::disjoint::disjoint_segment_areal
|
||||
<
|
||||
Segment, Areal
|
||||
>::apply(g2, g1, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Segment, typename Areal>
|
||||
struct disjoint<Segment, Areal, 2, segment_tag, areal_tag, false>
|
||||
: detail::disjoint::disjoint_segment_areal<Segment, Areal>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
||||
#include <boost/geometry/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/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename Segment1, typename Segment2>
|
||||
struct disjoint_segment
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Segment1>::type point_type;
|
||||
|
||||
typedef segment_intersection_points<point_type> intersection_return_type;
|
||||
|
||||
typedef policies::relate::segments_intersection_points
|
||||
<
|
||||
intersection_return_type
|
||||
> intersection_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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct assign_disjoint_policy
|
||||
{
|
||||
// We want to include all points:
|
||||
static bool const include_no_turn = true;
|
||||
static bool const include_degenerate = true;
|
||||
static bool const include_opposite = true;
|
||||
static bool const include_start_turn = false;
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct disjoint_linear
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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
|
||||
<
|
||||
typename coordinate_type<point_type>::type
|
||||
> ;
|
||||
using turn_info_type = overlay::turn_info
|
||||
<
|
||||
mutable_point_type,
|
||||
ratio_type,
|
||||
typename detail::get_turns::turn_operation_type
|
||||
<
|
||||
Geometry1, Geometry2, mutable_point_type, ratio_type
|
||||
>::type
|
||||
>;
|
||||
|
||||
std::deque<turn_info_type> turns;
|
||||
|
||||
// Specify two policies:
|
||||
// 1) Stop at any intersection
|
||||
// 2) In assignment, include also degenerate points (which are normally skipped)
|
||||
disjoint_interrupt_policy interrupt_policy;
|
||||
dispatch::get_turns
|
||||
<
|
||||
typename geometry::tag<Geometry1>::type,
|
||||
typename geometry::tag<Geometry2>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, // should be false
|
||||
overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, // should be false
|
||||
detail::get_turns::get_turn_info_type
|
||||
<
|
||||
Geometry1, Geometry2, assign_disjoint_policy
|
||||
>
|
||||
>::apply(0, geometry1, 1, geometry2,
|
||||
strategy, detail::no_rescale_policy(), turns, interrupt_policy);
|
||||
|
||||
return !interrupt_policy.has_intersections;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear1, typename Linear2>
|
||||
struct disjoint<Linear1, Linear2, 2, linear_tag, linear_tag, false>
|
||||
: detail::disjoint::disjoint_linear<Linear1, Linear2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment1, typename Segment2>
|
||||
struct disjoint<Segment1, Segment2, 2, segment_tag, segment_tag, false>
|
||||
: detail::disjoint::disjoint_segment<Segment1, Segment2>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_LINEAR_HPP
|
||||
Vendored
Executable
+187
@@ -0,0 +1,187 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP
|
||||
|
||||
|
||||
#include <boost/range/size.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
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
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>
|
||||
static inline bool apply(Range const& range,
|
||||
SegmentOrBox const& segment_or_box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using point_type = typename point_type<Range>::type;
|
||||
using range_segment = typename geometry::model::referring_segment<point_type const>;
|
||||
|
||||
detail::closed_view<Range const> const view(range);
|
||||
|
||||
auto const count = ::boost::size(view);
|
||||
|
||||
if ( count == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ( count == 1 )
|
||||
{
|
||||
return disjoint_point_segment_or_box
|
||||
<
|
||||
SegmentOrBox
|
||||
>::apply(range::front(view), segment_or_box, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it0 = ::boost::begin(view);
|
||||
auto it1 = ::boost::begin(view) + 1;
|
||||
auto const last = ::boost::end(view);
|
||||
|
||||
for ( ; it1 != last ; ++it0, ++it1 )
|
||||
{
|
||||
point_type const& p0 = *it0;
|
||||
point_type const& p1 = *it1;
|
||||
range_segment rng_segment(p0, p1);
|
||||
if ( !dispatch::disjoint
|
||||
<
|
||||
range_segment, SegmentOrBox
|
||||
>::apply(rng_segment, segment_or_box, strategy) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Linear,
|
||||
typename SegmentOrBox,
|
||||
typename Tag = typename tag<Linear>::type
|
||||
>
|
||||
struct disjoint_linear_segment_or_box
|
||||
: not_implemented<Linear, SegmentOrBox>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Linestring, typename SegmentOrBox>
|
||||
struct disjoint_linear_segment_or_box<Linestring, SegmentOrBox, linestring_tag>
|
||||
: disjoint_range_segment_or_box<Linestring, SegmentOrBox>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLinestring, typename SegmentOrBox>
|
||||
struct disjoint_linear_segment_or_box
|
||||
<
|
||||
MultiLinestring, SegmentOrBox, multi_linestring_tag
|
||||
> : multirange_constant_size_geometry<MultiLinestring, SegmentOrBox>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Segment>
|
||||
struct disjoint<Linear, Segment, 2, linear_tag, segment_tag, false>
|
||||
: detail::disjoint::disjoint_linear_segment_or_box<Linear, Segment>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Linear, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint<Linear, Box, DimensionCount, linear_tag, box_tag, false>
|
||||
: detail::disjoint::disjoint_linear_segment_or_box<Linear, Box>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_SEGMENT_OR_BOX_HPP
|
||||
Vendored
Executable
+579
@@ -0,0 +1,579 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range/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>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#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
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
class multipoint_multipoint
|
||||
{
|
||||
private:
|
||||
template <typename Iterator, typename Strategy>
|
||||
class unary_not_disjoint_predicate
|
||||
: geometry::less<void, -1, Strategy>
|
||||
{
|
||||
private:
|
||||
using less_type = geometry::less<void, -1, Strategy>;
|
||||
|
||||
public:
|
||||
unary_not_disjoint_predicate(Iterator first, Iterator last)
|
||||
: less_type(), m_first(first), m_last(last)
|
||||
{}
|
||||
|
||||
template <typename Point>
|
||||
inline bool operator()(Point const& point) const
|
||||
{
|
||||
return std::binary_search(m_first,
|
||||
m_last,
|
||||
point,
|
||||
static_cast<less_type const&>(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator m_first, m_last;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
static inline bool apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const&)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
|
||||
|
||||
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(), less_type());
|
||||
|
||||
using predicate_type = unary_not_disjoint_predicate
|
||||
<
|
||||
typename std::vector<point1_type>::const_iterator,
|
||||
Strategy
|
||||
>;
|
||||
|
||||
return none_of(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
predicate_type(points1.begin(), points1.end()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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>
|
||||
void apply(Box& total, Point const& point) const
|
||||
{
|
||||
geometry::expand(total, point, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct expand_box_segment
|
||||
{
|
||||
explicit expand_box_segment(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
void apply(Box& total, Segment const& segment) const
|
||||
{
|
||||
geometry::expand(total,
|
||||
geometry::return_envelope<Box>(segment, m_strategy),
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_point
|
||||
{
|
||||
explicit overlaps_box_point(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Point>
|
||||
bool apply(Box const& box, Point const& point) const
|
||||
{
|
||||
return ! detail::disjoint::disjoint_point_box(point, box,
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_segment
|
||||
{
|
||||
explicit overlaps_box_segment(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
bool apply(Box const& box, Segment const& segment) const
|
||||
{
|
||||
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
class item_visitor_type
|
||||
{
|
||||
public:
|
||||
item_visitor_type(Strategy const& strategy)
|
||||
: m_intersection_found(false)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Item1, typename Item2>
|
||||
inline bool apply(Item1 const& item1, Item2 const& item2)
|
||||
{
|
||||
if (! m_intersection_found
|
||||
&& ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
|
||||
{
|
||||
m_intersection_found = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool intersection_found() const { return m_intersection_found; }
|
||||
|
||||
private:
|
||||
bool m_intersection_found;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
// structs for partition -- end
|
||||
|
||||
class segment_range
|
||||
{
|
||||
public:
|
||||
typedef geometry::segment_iterator<Linear const> const_iterator;
|
||||
typedef const_iterator iterator;
|
||||
|
||||
segment_range(Linear const& linear)
|
||||
: m_linear(linear)
|
||||
{}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return geometry::segments_begin(m_linear);
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return geometry::segments_end(m_linear);
|
||||
}
|
||||
|
||||
private:
|
||||
Linear const& m_linear;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy)
|
||||
{
|
||||
item_visitor_type<Strategy> visitor(strategy);
|
||||
|
||||
// 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.
|
||||
// Alternatively instead of a range of segments a range of Segment/Envelope pairs
|
||||
// should be passed, where envelope would be lazily calculated when needed the first time
|
||||
geometry::partition
|
||||
<
|
||||
geometry::model::box<typename point_type<MultiPoint>::type>
|
||||
>::apply(multipoint, segment_range(linear), visitor,
|
||||
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)
|
||||
{
|
||||
return apply(multipoint, linear, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename SingleGeometry>
|
||||
class multi_point_single_geometry
|
||||
{
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multi_point,
|
||||
SingleGeometry const& single_geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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);
|
||||
geometry::detail::expand_by_epsilon(box2);
|
||||
|
||||
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, strategy)
|
||||
&& ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(multi_point, single_geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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>
|
||||
void apply(Box& total, Point const& point) const
|
||||
{
|
||||
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>
|
||||
void apply(Box& total, BoxPair const& box_pair) const
|
||||
{
|
||||
geometry::expand(total, box_pair.first, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_point
|
||||
{
|
||||
explicit overlaps_box_point(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Point>
|
||||
bool apply(Box const& box, Point const& point) const
|
||||
{
|
||||
return ! detail::disjoint::disjoint_point_box(point, box, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
struct overlaps_box_box_pair
|
||||
{
|
||||
explicit overlaps_box_box_pair(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename BoxPair>
|
||||
bool apply(Box const& box, BoxPair const& box_pair) const
|
||||
{
|
||||
return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
|
||||
m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
class item_visitor_type
|
||||
{
|
||||
public:
|
||||
item_visitor_type(MultiGeometry const& multi_geometry,
|
||||
Strategy const& strategy)
|
||||
: m_intersection_found(false)
|
||||
, m_multi_geometry(multi_geometry)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Point, typename BoxPair>
|
||||
inline bool apply(Point const& point, BoxPair const& box_pair)
|
||||
{
|
||||
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, 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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool intersection_found() const { return m_intersection_found; }
|
||||
|
||||
private:
|
||||
bool m_intersection_found;
|
||||
MultiGeometry const& m_multi_geometry;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
// structs for partition -- end
|
||||
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<MultiPoint>::type point1_type;
|
||||
typedef typename point_type<MultiGeometry>::type point2_type;
|
||||
typedef model::box<point1_type> box1_type;
|
||||
typedef model::box<point2_type> box2_type;
|
||||
typedef std::pair<box2_type, std::size_t> box_pair_type;
|
||||
|
||||
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, strategy);
|
||||
geometry::detail::expand_by_epsilon(boxes[i].first);
|
||||
boxes[i].second = i;
|
||||
}
|
||||
|
||||
item_visitor_type<Strategy> visitor(multi_geometry, strategy);
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
box1_type
|
||||
>::apply(multi_point, boxes, visitor,
|
||||
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();
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiGeometry const& multi_geometry, MultiPoint const& multi_point, Strategy const& strategy)
|
||||
{
|
||||
return apply(multi_point, multi_geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Tag = typename tag<Areal>::type>
|
||||
struct multipoint_areal
|
||||
: multi_point_single_geometry<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Areal>
|
||||
struct multipoint_areal<MultiPoint, Areal, multi_polygon_tag>
|
||||
: multi_point_multi_geometry<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename MultiPoint, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false
|
||||
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Point>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Segment, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false
|
||||
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Segment>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false
|
||||
> : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Box>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename MultiPoint1,
|
||||
typename MultiPoint2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint1, MultiPoint2, DimensionCount,
|
||||
multi_point_tag, multi_point_tag, false
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( boost::size(multipoint2) < boost::size(multipoint1) )
|
||||
{
|
||||
return detail::disjoint::multipoint_multipoint
|
||||
::apply(multipoint2, multipoint1, strategy);
|
||||
}
|
||||
|
||||
return detail::disjoint::multipoint_multipoint
|
||||
::apply(multipoint1, multipoint2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Linear, typename MultiPoint, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false
|
||||
> : detail::disjoint::multipoint_linear<MultiPoint, Linear>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false
|
||||
> : detail::disjoint::multipoint_linear<MultiPoint, Linear>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename MultiPoint, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
Areal, MultiPoint, DimensionCount, areal_tag, multi_point_tag, false
|
||||
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Areal, DimensionCount, multi_point_tag, areal_tag, false
|
||||
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
|
||||
Vendored
Executable
+96
@@ -0,0 +1,96 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, typename Strategy, typename BinaryPredicate>
|
||||
class unary_disjoint_geometry_to_query_geometry
|
||||
{
|
||||
public:
|
||||
unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
: m_geometry(geometry)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename QueryGeometry>
|
||||
inline bool operator()(QueryGeometry const& query_geometry) const
|
||||
{
|
||||
return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
|
||||
}
|
||||
|
||||
private:
|
||||
Geometry const& m_geometry;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
|
||||
template<typename MultiRange, typename ConstantSizeGeometry>
|
||||
struct multirange_constant_size_geometry
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiRange const& multirange,
|
||||
ConstantSizeGeometry const& constant_size_geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
using disjoint = unary_disjoint_geometry_to_query_geometry
|
||||
<
|
||||
ConstantSizeGeometry,
|
||||
Strategy,
|
||||
dispatch::disjoint
|
||||
<
|
||||
typename boost::range_value<MultiRange>::type,
|
||||
ConstantSizeGeometry
|
||||
>
|
||||
>;
|
||||
|
||||
return std::all_of(boost::begin(multirange),
|
||||
boost::end(multirange),
|
||||
disjoint(constant_size_geometry, strategy));
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(ConstantSizeGeometry const& constant_size_geometry,
|
||||
MultiRange const& multirange,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(multirange, constant_size_geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/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/strategies/detail.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect if point/box are disjoint
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point, typename Box, 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);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef decltype(strategy.covered_by(point, box)) strategy_type;
|
||||
// ! covered_by(point, box)
|
||||
return ! strategy_type::apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
struct reverse_covered_by
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return ! geometry::covered_by(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template<typename Point, typename Linear, std::size_t DimensionCount>
|
||||
struct disjoint<Point, Linear, DimensionCount, point_tag, linear_tag, false>
|
||||
: detail::disjoint::reverse_covered_by
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Areal, std::size_t DimensionCount>
|
||||
struct disjoint<Point, Areal, DimensionCount, point_tag, areal_tag, false>
|
||||
: detail::disjoint::reverse_covered_by
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename Segment, std::size_t DimensionCount>
|
||||
struct disjoint<Point, Segment, DimensionCount, point_tag, segment_tag, false>
|
||||
: detail::disjoint::reverse_covered_by
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <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>
|
||||
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point1, typename Point2, std::size_t DimensionCount>
|
||||
struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-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
|
||||
// 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_DISJOINT_SEGMENT_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/vertex_longitude.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
// Temporary, for envelope_segment_impl
|
||||
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename CS_Tag>
|
||||
struct disjoint_segment_box_sphere_or_spheroid
|
||||
{
|
||||
struct disjoint_info
|
||||
{
|
||||
enum type
|
||||
{
|
||||
intersect,
|
||||
disjoint_no_vertex,
|
||||
disjoint_vertex
|
||||
};
|
||||
disjoint_info(type t) : m_(t){}
|
||||
operator type () const {return m_;}
|
||||
type m_;
|
||||
private :
|
||||
//prevent automatic conversion for any other built-in types
|
||||
template <typename T>
|
||||
operator T () const;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment, typename Box,
|
||||
typename AzimuthStrategy,
|
||||
typename NormalizeStrategy,
|
||||
typename DisjointPointBoxStrategy,
|
||||
typename DisjointBoxBoxStrategy
|
||||
>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Box const& box,
|
||||
AzimuthStrategy const& azimuth_strategy,
|
||||
NormalizeStrategy const& normalize_strategy,
|
||||
DisjointPointBoxStrategy const& disjoint_point_box_strategy,
|
||||
DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
|
||||
{
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
segment_point vertex;
|
||||
return apply(segment, box, vertex,
|
||||
azimuth_strategy,
|
||||
normalize_strategy,
|
||||
disjoint_point_box_strategy,
|
||||
disjoint_box_box_strategy) != disjoint_info::intersect;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment, typename Box,
|
||||
typename P,
|
||||
typename AzimuthStrategy,
|
||||
typename NormalizeStrategy,
|
||||
typename DisjointPointBoxStrategy,
|
||||
typename DisjointBoxBoxStrategy
|
||||
>
|
||||
static inline disjoint_info apply(Segment const& segment,
|
||||
Box const& box,
|
||||
P& vertex,
|
||||
AzimuthStrategy const& azimuth_strategy,
|
||||
NormalizeStrategy const& ,
|
||||
DisjointPointBoxStrategy const& disjoint_point_box_strategy,
|
||||
DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
|
||||
{
|
||||
assert_dimension_equal<Segment, Box>();
|
||||
|
||||
typedef typename point_type<Segment>::type segment_point_type;
|
||||
|
||||
segment_point_type p0, p1;
|
||||
geometry::detail::assign_point_from_index<0>(segment, p0);
|
||||
geometry::detail::assign_point_from_index<1>(segment, p1);
|
||||
|
||||
//vertex not computed here
|
||||
disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex;
|
||||
|
||||
// Simplest cases first
|
||||
|
||||
// Case 1: if box contains one of segment's endpoints then they are not disjoint
|
||||
if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy)
|
||||
|| ! disjoint_point_box(p1, box, disjoint_point_box_strategy) )
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
|
||||
// Case 2: disjoint if bounding boxes are disjoint
|
||||
|
||||
typedef typename coordinate_type<segment_point_type>::type CT;
|
||||
|
||||
segment_point_type p0_normalized;
|
||||
NormalizeStrategy::apply(p0, p0_normalized);
|
||||
segment_point_type p1_normalized;
|
||||
NormalizeStrategy::apply(p1, p1_normalized);
|
||||
|
||||
CT lon1 = geometry::get_as_radian<0>(p0_normalized);
|
||||
CT lat1 = geometry::get_as_radian<1>(p0_normalized);
|
||||
CT lon2 = geometry::get_as_radian<0>(p1_normalized);
|
||||
CT lat2 = geometry::get_as_radian<1>(p1_normalized);
|
||||
|
||||
if (lon1 > lon2)
|
||||
{
|
||||
std::swap(lon1, lon2);
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
|
||||
geometry::model::box<segment_point_type> box_seg;
|
||||
|
||||
strategy::envelope::detail::envelope_segment_impl
|
||||
<
|
||||
CS_Tag
|
||||
>::template apply<geometry::radian>(lon1, lat1,
|
||||
lon2, lat2,
|
||||
box_seg,
|
||||
azimuth_strategy);
|
||||
|
||||
if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy))
|
||||
{
|
||||
return disjoint_return_value;
|
||||
}
|
||||
|
||||
// Case 3: test intersection by comparing angles
|
||||
|
||||
CT alp1, a_b0, a_b1, a_b2, a_b3;
|
||||
|
||||
CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
|
||||
CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
|
||||
CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
|
||||
CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
|
||||
|
||||
azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
|
||||
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);
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
// Case 4: The only intersection case not covered above is when all four
|
||||
// points of the box are above (below) the segment in northern (southern)
|
||||
// hemisphere. Then we have to compute the vertex of the segment
|
||||
|
||||
CT vertex_lat;
|
||||
|
||||
if ((lat1 < b_lat_min && vertex_north)
|
||||
|| (lat1 > b_lat_max && !vertex_north))
|
||||
{
|
||||
CT b_lat_below; //latitude of box closest to equator
|
||||
|
||||
if (vertex_north)
|
||||
{
|
||||
vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
|
||||
b_lat_below = b_lat_min;
|
||||
} else {
|
||||
vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg);
|
||||
b_lat_below = b_lat_max;
|
||||
}
|
||||
|
||||
//optimization TODO: computing the spherical longitude should suffice for
|
||||
// the majority of cases
|
||||
CT vertex_lon = geometry::formula::vertex_longitude<CT, CS_Tag>
|
||||
::apply(lon1, lat1,
|
||||
lon2, lat2,
|
||||
vertex_lat,
|
||||
alp1,
|
||||
azimuth_strategy);
|
||||
|
||||
geometry::set_from_radian<0>(vertex, vertex_lon);
|
||||
geometry::set_from_radian<1>(vertex, vertex_lat);
|
||||
disjoint_return_value = disjoint_info::disjoint_vertex; //vertex_computed
|
||||
|
||||
// Check if the vertex point is within the band defined by the
|
||||
// minimum and maximum longitude of the box; if yes, then return
|
||||
// false if the point is above the min latitude of the box; return
|
||||
// true in all other cases
|
||||
if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
|
||||
&& std::abs(vertex_lat) > std::abs(b_lat_below))
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
}
|
||||
|
||||
return disjoint_return_value;
|
||||
}
|
||||
};
|
||||
|
||||
struct disjoint_segment_box
|
||||
{
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return strategy.disjoint(segment, box).apply(segment, box);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
|
||||
: detail::disjoint::disjoint_segment_box
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_SEGMENT_BOX_HPP
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, typename Strategies>
|
||||
struct distance
|
||||
<
|
||||
Box1, Box2, Strategies, box_tag, box_tag,
|
||||
strategy_tag_distance_box_box, false
|
||||
>
|
||||
{
|
||||
static inline auto apply(Box1 const& box1, Box2 const& box2, Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(strategies);
|
||||
return strategies.distance(box1, box2).apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_BOX_TO_BOX_HPP
|
||||
Vendored
Executable
+239
@@ -0,0 +1,239 @@
|
||||
// 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/range/size.hpp>
|
||||
|
||||
#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
|
||||
Vendored
Executable
+420
@@ -0,0 +1,420 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range/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/iterators/point_iterator.hpp>
|
||||
#include <boost/geometry/iterators/segment_iterator.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 distance
|
||||
{
|
||||
|
||||
|
||||
// closure of segment or box point range
|
||||
template
|
||||
<
|
||||
typename SegmentOrBox,
|
||||
typename Tag = typename tag<SegmentOrBox>::type
|
||||
>
|
||||
struct segment_or_box_point_range_closure
|
||||
: not_implemented<SegmentOrBox>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct segment_or_box_point_range_closure<Segment, segment_tag>
|
||||
{
|
||||
static const closure_selector value = closed;
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct segment_or_box_point_range_closure<Box, box_tag>
|
||||
{
|
||||
static const closure_selector value = open;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename SegmentOrBox,
|
||||
typename Strategies,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
class geometry_to_segment_or_box
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<SegmentOrBox>::type segment_or_box_point;
|
||||
|
||||
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
|
||||
> point_to_point_range;
|
||||
|
||||
typedef detail::closest_feature::geometry_to_range geometry_to_range;
|
||||
|
||||
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
|
||||
template
|
||||
<
|
||||
typename SegOrBox,
|
||||
typename SegOrBoxTag = typename tag<SegOrBox>::type
|
||||
>
|
||||
struct assign_new_min_iterator
|
||||
: not_implemented<SegOrBox>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct assign_new_min_iterator<Segment, segment_tag>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline void apply(Iterator&, Iterator)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box>
|
||||
struct assign_new_min_iterator<Box, box_tag>
|
||||
{
|
||||
template <typename Iterator>
|
||||
static inline void apply(Iterator& it_min, Iterator it)
|
||||
{
|
||||
it_min = it;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// assign the points of a segment or a box to a range
|
||||
template
|
||||
<
|
||||
typename SegOrBox,
|
||||
typename PointRange,
|
||||
typename SegOrBoxTag = typename tag<SegOrBox>::type
|
||||
>
|
||||
struct assign_segment_or_box_points
|
||||
{};
|
||||
|
||||
template <typename Segment, typename PointRange>
|
||||
struct assign_segment_or_box_points<Segment, PointRange, segment_tag>
|
||||
{
|
||||
static inline void apply(Segment const& segment, PointRange& range)
|
||||
{
|
||||
detail::assign_point_from_index<0>(segment, range[0]);
|
||||
detail::assign_point_from_index<1>(segment, range[1]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box, typename PointRange>
|
||||
struct assign_segment_or_box_points<Box, PointRange, box_tag>
|
||||
{
|
||||
static inline void apply(Box const& box, PointRange& range)
|
||||
{
|
||||
detail::assign_box_corners_oriented<true>(box, range);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef distance::return_t<Geometry, SegmentOrBox, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Geometry const& geometry,
|
||||
SegmentOrBox const& segment_or_box,
|
||||
Strategies const& strategies,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
typedef geometry::segment_iterator
|
||||
<
|
||||
Geometry const
|
||||
> segment_iterator_type;
|
||||
|
||||
typedef assign_new_min_iterator<SegmentOrBox> assign_new_value;
|
||||
|
||||
|
||||
if (check_intersection
|
||||
&& geometry::intersects(geometry, segment_or_box, strategies))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
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>
|
||||
seg_or_box_points(geometry::num_points(segment_or_box));
|
||||
|
||||
assign_segment_or_box_points
|
||||
<
|
||||
SegmentOrBox,
|
||||
std::vector<segment_or_box_point>
|
||||
>::apply(segment_or_box, seg_or_box_points);
|
||||
|
||||
// consider all distances of the points in the geometry to the
|
||||
// segment or box
|
||||
comparable_return_type cd_min1(0);
|
||||
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 (auto pit = pit_min;
|
||||
pit != points_end(geometry); ++pit, first = false)
|
||||
{
|
||||
comparable_return_type 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)
|
||||
{
|
||||
cd_min1 = cd;
|
||||
pit_min = pit;
|
||||
assign_new_value::apply(it_min1, it_pair.first);
|
||||
assign_new_value::apply(it_min2, it_pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
// consider all distances of the points in the segment or box to the
|
||||
// segments of the geometry
|
||||
comparable_return_type cd_min2(0);
|
||||
segment_iterator_type sit_min;
|
||||
auto it_min = boost::const_begin(seg_or_box_points);
|
||||
|
||||
first = true;
|
||||
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;
|
||||
segment_iterator_type sit
|
||||
= geometry_to_range::apply(*it,
|
||||
segments_begin(geometry),
|
||||
segments_end(geometry),
|
||||
cstrategy,
|
||||
cd);
|
||||
|
||||
if (first || cd < cd_min2)
|
||||
{
|
||||
cd_min2 = cd;
|
||||
it_min = it;
|
||||
sit_min = sit;
|
||||
}
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<strategy_type>::value))
|
||||
{
|
||||
return (std::min)(cd_min1, cd_min2);
|
||||
}
|
||||
|
||||
if (cd_min1 < cd_min2)
|
||||
{
|
||||
return strategy.apply(*pit_min, *it_min1, *it_min2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
segment_or_box_point,
|
||||
typename std::iterator_traits
|
||||
<
|
||||
segment_iterator_type
|
||||
>::value_type,
|
||||
Strategies
|
||||
>::apply(*it_min, *sit_min, strategies);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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, strategies, check_intersection);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename MultiPoint, typename SegmentOrBox, typename Strategies>
|
||||
class geometry_to_segment_or_box
|
||||
<
|
||||
MultiPoint, SegmentOrBox, Strategies, multi_point_tag
|
||||
>
|
||||
{
|
||||
private:
|
||||
typedef detail::closest_feature::geometry_to_range base_type;
|
||||
typedef detail::closest_feature::geometry_to_range geometry_to_range;
|
||||
typedef distance::strategy_t<MultiPoint, SegmentOrBox, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef distance::return_t<MultiPoint, SegmentOrBox, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint const& multipoint,
|
||||
SegmentOrBox const& segment_or_box,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
distance::creturn_t<MultiPoint, SegmentOrBox, Strategies> cd_min;
|
||||
|
||||
auto const it_min
|
||||
= geometry_to_range::apply(segment_or_box,
|
||||
boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
strategy_type
|
||||
>::apply(strategies.distance(multipoint, segment_or_box)),
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
dispatch::distance
|
||||
<
|
||||
typename point_type<MultiPoint>::type,
|
||||
SegmentOrBox,
|
||||
Strategies
|
||||
>::apply(*it_min, segment_or_box, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Segment, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Segment, Strategy, linear_tag, segment_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::geometry_to_segment_or_box<Linear, Segment, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Segment, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Segment, Strategy, areal_tag, segment_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Segment, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Segment, Areal, Strategy, segment_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::geometry_to_segment_or_box<Areal, Segment, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Linear, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Box, Strategy, linear_tag, box_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::geometry_to_segment_or_box
|
||||
<
|
||||
Linear, Box, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Box, Strategy, areal_tag, box_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::geometry_to_segment_or_box<Areal, Box, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Segment, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint, Segment, Strategy,
|
||||
multi_point_tag, segment_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::geometry_to_segment_or_box
|
||||
<
|
||||
MultiPoint, Segment, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint, Box, Strategy,
|
||||
multi_point_tag, box_tag,
|
||||
strategy_tag_distance_point_box, false
|
||||
> : detail::distance::geometry_to_segment_or_box
|
||||
<
|
||||
MultiPoint, Box, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_TO_SEGMENT_OR_BOX_HPP
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by 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_DETAIL_DISTANCE_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_IMPLEMENTATION_HPP
|
||||
|
||||
// the implementation details
|
||||
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/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/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
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
|
||||
|
||||
#include <boost/concept_check.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>
|
||||
|
||||
// TODO: move these to algorithms
|
||||
#include <boost/geometry/strategies/default_distance_result.hpp>
|
||||
#include <boost/geometry/strategies/distance_result.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
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
// If reversal is needed, perform it
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2, typename Strategy,
|
||||
typename Tag1, typename Tag2, typename StrategyTag
|
||||
>
|
||||
struct distance
|
||||
<
|
||||
Geometry1, Geometry2, Strategy,
|
||||
Tag1, Tag2, StrategyTag,
|
||||
true
|
||||
>
|
||||
: distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
|
||||
{
|
||||
static inline auto apply(Geometry1 const& g1, Geometry2 const& g2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return distance
|
||||
<
|
||||
Geometry2, Geometry1, Strategy,
|
||||
Tag2, Tag1, StrategyTag,
|
||||
false
|
||||
>::apply(g2, g1, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct distance
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
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, false>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategies::distance::services::default_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::distance
|
||||
<
|
||||
Geometry1, Geometry2, strategy_type
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
|
||||
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 auto apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
|
||||
struct 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::distance_result<DynamicGeometry1, Geometry2, Strategy>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
|
||||
{
|
||||
result = resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, geometry2, strategy);
|
||||
}, geometry1);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
|
||||
struct 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::distance_result<Geometry1, DynamicGeometry2, Strategy>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, g2, strategy);
|
||||
}, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename DynamicGeometry1, typename DynamicGeometry2>
|
||||
struct 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::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type;
|
||||
result_t result = 0;
|
||||
traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
|
||||
{
|
||||
result = resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(g1, g2, strategy);
|
||||
}, geometry1, geometry2);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief Calculate the distance between two geometries \brief_strategy
|
||||
\ingroup distance
|
||||
\details
|
||||
\details The free function distance calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
|
||||
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Distance}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{distance}
|
||||
\return \return_calc{distance}
|
||||
\note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
|
||||
it may also be a point-segment strategy.
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
|
||||
\* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
|
||||
\* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
|
||||
\* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
|
||||
\* more (currently extensions): Vincenty\, Andoyer (geographic)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Note, in case of a Compilation Error:
|
||||
if you get:
|
||||
- "Failed to specialize function template ..."
|
||||
- "error: no matching function for call to ..."
|
||||
for distance, it is probably so that there is no specialization
|
||||
for return_type<...> for your strategy.
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline auto distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
detail::throw_on_empty_input(geometry1);
|
||||
detail::throw_on_empty_input(geometry2);
|
||||
|
||||
return resolve_dynamic::distance
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Calculate the distance between two geometries.
|
||||
\ingroup distance
|
||||
\details The free function distance calculates the distance between two geometries. \details_default_strategy
|
||||
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_calc{distance}
|
||||
|
||||
\qbk{[include reference/algorithms/distance.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline auto distance(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2)
|
||||
{
|
||||
return geometry::distance(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_INTERFACE_HPP
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
// metafunction to determine is a strategy is comparable or not
|
||||
template <typename Strategy>
|
||||
struct is_comparable
|
||||
: std::is_same
|
||||
<
|
||||
Strategy,
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_IS_COMPARABLE_HPP
|
||||
Vendored
Executable
+70
@@ -0,0 +1,70 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP
|
||||
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/point_iterator.hpp>
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
// class to choose between point_iterator and segment_iterator
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct iterator_selector
|
||||
{
|
||||
typedef geometry::segment_iterator<Geometry> iterator_type;
|
||||
|
||||
static inline iterator_type begin(Geometry& geometry)
|
||||
{
|
||||
return segments_begin(geometry);
|
||||
}
|
||||
|
||||
static inline iterator_type end(Geometry& geometry)
|
||||
{
|
||||
return segments_end(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct iterator_selector<MultiPoint, multi_point_tag>
|
||||
{
|
||||
typedef geometry::point_iterator<MultiPoint> iterator_type;
|
||||
|
||||
static inline iterator_type begin(MultiPoint& multipoint)
|
||||
{
|
||||
return points_begin(multipoint);
|
||||
}
|
||||
|
||||
static inline iterator_type end(MultiPoint& multipoint)
|
||||
{
|
||||
return points_end(multipoint);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHS_DETAIL_DISTANCE_ITERATOR_SELECTOR_HPP
|
||||
Vendored
Executable
+136
@@ -0,0 +1,136 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear, typename Areal, typename Strategies>
|
||||
struct linear_to_areal
|
||||
{
|
||||
typedef distance::return_t<Linear, Areal, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
Areal const& areal,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( geometry::intersects(linear, areal, strategies) )
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return linear_to_linear
|
||||
<
|
||||
Linear, Areal, Strategies
|
||||
>::apply(linear, areal, strategies, false);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type apply(Areal const& areal,
|
||||
Linear const& linear,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(linear, areal, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Strategies>
|
||||
struct areal_to_areal
|
||||
{
|
||||
typedef distance::return_t<Areal1, Areal2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Areal1 const& areal1,
|
||||
Areal2 const& areal2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( geometry::intersects(areal1, areal2, strategies) )
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return linear_to_linear
|
||||
<
|
||||
Areal1, Areal2, Strategies
|
||||
>::apply(areal1, areal2, strategies, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Linear, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Areal, Strategy,
|
||||
linear_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::linear_to_areal
|
||||
<
|
||||
Linear, Areal, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Areal, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Linear, Strategy,
|
||||
areal_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::linear_to_areal
|
||||
<
|
||||
Linear, Areal, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal1, Areal2, Strategy,
|
||||
areal_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::areal_to_areal
|
||||
<
|
||||
Areal1, Areal2, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_OR_AREAL_TO_AREAL_HPP
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_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
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
template <typename Linear, typename Box, typename Strategies>
|
||||
struct linear_to_box
|
||||
{
|
||||
typedef distance::return_t<Linear, Box, Strategies> return_type;
|
||||
|
||||
template <typename Iterator>
|
||||
static inline return_type apply(Box const& box,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
bool first = true;
|
||||
return_type d_min(0);
|
||||
for (Iterator it = begin; it != end; ++it, first = false)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type
|
||||
Segment;
|
||||
|
||||
return_type d = dispatch::distance<Segment, Box, Strategies>
|
||||
::apply(*it, box, strategies);
|
||||
|
||||
if ( first || d < d_min )
|
||||
{
|
||||
d_min = d;
|
||||
}
|
||||
}
|
||||
return d_min;
|
||||
}
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
Box const& box,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if ( geometry::intersects(linear, box) )
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return apply(box,
|
||||
geometry::segments_begin(linear),
|
||||
geometry::segments_end(linear),
|
||||
strategies);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type apply(Box const& box,
|
||||
Linear const& linear,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(linear, box, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Linear, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Box, Strategy,
|
||||
linear_tag, box_tag,
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
: detail::distance::linear_to_box
|
||||
<
|
||||
Linear, Box, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Box, Strategy,
|
||||
areal_tag, box_tag,
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
: detail::distance::linear_to_box
|
||||
<
|
||||
Areal, Box, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
Vendored
Executable
+118
@@ -0,0 +1,118 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_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/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/point_iterator.hpp>
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Linear1, typename Linear2, typename Strategies>
|
||||
struct linear_to_linear
|
||||
{
|
||||
typedef distance::return_t<Linear1, Linear2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Linear1 const& linear1,
|
||||
Linear2 const& linear2,
|
||||
Strategies const& strategies,
|
||||
bool = false)
|
||||
{
|
||||
if (geometry::num_points(linear1) == 1)
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
typename point_type<Linear1>::type,
|
||||
Linear2,
|
||||
Strategies
|
||||
>::apply(*points_begin(linear1), linear2, strategies);
|
||||
}
|
||||
|
||||
if (geometry::num_points(linear2) == 1)
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
typename point_type<Linear2>::type,
|
||||
Linear1,
|
||||
Strategies
|
||||
>::apply(*points_begin(linear2), linear1, strategies);
|
||||
}
|
||||
|
||||
if (geometry::num_segments(linear2) < geometry::num_segments(linear1))
|
||||
{
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
geometry::segment_iterator<Linear2 const>,
|
||||
Linear1,
|
||||
Strategies
|
||||
>::apply(geometry::segments_begin(linear2),
|
||||
geometry::segments_end(linear2),
|
||||
linear1,
|
||||
strategies);
|
||||
|
||||
}
|
||||
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
geometry::segment_iterator<Linear1 const>,
|
||||
Linear2,
|
||||
Strategies
|
||||
>::apply(geometry::segments_begin(linear1),
|
||||
geometry::segments_end(linear1),
|
||||
linear2,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Linear1, typename Linear2, typename Strategy, typename StrategyTag>
|
||||
struct distance
|
||||
<
|
||||
Linear1, Linear2, Strategy,
|
||||
linear_tag, linear_tag,
|
||||
StrategyTag, false
|
||||
> : detail::distance::linear_to_linear
|
||||
<
|
||||
Linear1, Linear2, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_LINEAR_HPP
|
||||
Vendored
Executable
+221
@@ -0,0 +1,221 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_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>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategies>
|
||||
struct multipoint_to_multipoint
|
||||
{
|
||||
typedef distance::return_t<MultiPoint1, MultiPoint2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint1 const& multipoint1,
|
||||
MultiPoint2 const& multipoint2,
|
||||
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,
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint2),
|
||||
boost::end(multipoint2),
|
||||
multipoint1,
|
||||
strategies);
|
||||
}
|
||||
|
||||
return point_or_segment_range_to_geometry_rtree
|
||||
<
|
||||
typename boost::range_iterator<MultiPoint1 const>::type,
|
||||
MultiPoint2,
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint1),
|
||||
boost::end(multipoint1),
|
||||
multipoint2,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, typename Strategies>
|
||||
struct multipoint_to_linear
|
||||
{
|
||||
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,
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
linear,
|
||||
strategies);
|
||||
}
|
||||
|
||||
static inline auto apply(Linear const& linear,
|
||||
MultiPoint const& multipoint,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(multipoint, linear, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Strategies>
|
||||
class multipoint_to_areal
|
||||
{
|
||||
private:
|
||||
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:
|
||||
typedef distance::return_t<MultiPoint, Areal, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(MultiPoint const& multipoint,
|
||||
Areal const& areal,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
covered_by_areal predicate(areal, strategies);
|
||||
|
||||
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,
|
||||
Strategies
|
||||
>::apply(boost::begin(multipoint),
|
||||
boost::end(multipoint),
|
||||
areal,
|
||||
strategies);
|
||||
}
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
static inline return_type apply(Areal const& areal,
|
||||
MultiPoint const& multipoint,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(multipoint, areal, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint1, MultiPoint2, Strategy,
|
||||
multi_point_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_point, false
|
||||
> : detail::distance::multipoint_to_multipoint
|
||||
<
|
||||
MultiPoint1, MultiPoint2, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint, Linear, Strategy, multi_point_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Linear, typename MultiPoint, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, MultiPoint, Strategy, linear_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_linear<MultiPoint, Linear, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
MultiPoint, Areal, Strategy, multi_point_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename MultiPoint, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, MultiPoint, Strategy, areal_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::multipoint_to_areal<MultiPoint, Areal, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_MULTIPOINT_TO_GEOMETRY_HPP
|
||||
Vendored
Executable
+539
@@ -0,0 +1,539 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/relate/services.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename P1, typename P2, typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct point_to_point
|
||||
{
|
||||
static inline
|
||||
auto apply(P1 const& p1, P2 const& p2, Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(strategies);
|
||||
return strategies.distance(p1, p2).apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
// TEMP?
|
||||
// called by geometry_to_range
|
||||
template <typename P1, typename P2, typename Strategy>
|
||||
struct point_to_point<P1, P2, Strategy, false>
|
||||
{
|
||||
static inline
|
||||
auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point, typename Segment, typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct point_to_segment
|
||||
{
|
||||
static inline auto apply(Point const& point, Segment const& segment,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typename point_type<Segment>::type p[2];
|
||||
geometry::detail::assign_point_from_index<0>(segment, p[0]);
|
||||
geometry::detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
boost::ignore_unused(strategies);
|
||||
return strategies.distance(point, segment).apply(point, p[0], p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
// TEMP?
|
||||
// called by geometry_to_range
|
||||
template <typename Point, typename Segment, typename Strategy>
|
||||
struct point_to_segment<Point, Segment, Strategy, false>
|
||||
{
|
||||
static inline auto apply(Point const& point, Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename point_type<Segment>::type p[2];
|
||||
geometry::detail::assign_point_from_index<0>(segment, p[0]);
|
||||
geometry::detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(point, p[0], p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point, typename Box, typename Strategies,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
|
||||
>
|
||||
struct point_to_box
|
||||
{
|
||||
static inline auto apply(Point const& point, Box const& box,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
boost::ignore_unused(strategies);
|
||||
return strategies.distance(point, box).apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
// TEMP?
|
||||
// called by geometry_to_range
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
struct point_to_box<Point, Box, Strategy, false>
|
||||
{
|
||||
static inline auto apply(Point const& point, Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
return strategy.apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Range,
|
||||
closure_selector Closure,
|
||||
typename Strategies
|
||||
>
|
||||
class point_to_range
|
||||
{
|
||||
private:
|
||||
typedef distance::strategy_t<Point, Range, Strategies> strategy_type;
|
||||
|
||||
typedef detail::closest_feature::point_to_point_range
|
||||
<
|
||||
Point, Range, Closure
|
||||
> point_to_point_range;
|
||||
|
||||
public:
|
||||
typedef distance::return_t<Point, Range, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point, Range const& range,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (boost::size(range) == 0)
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
distance::creturn_t<Point, Range, Strategies> cd_min;
|
||||
|
||||
std::pair
|
||||
<
|
||||
typename boost::range_iterator<Range const>::type,
|
||||
typename boost::range_iterator<Range const>::type
|
||||
> it_pair
|
||||
= point_to_point_range::apply(point,
|
||||
boost::begin(range),
|
||||
boost::end(range),
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
strategy_type
|
||||
>::apply(strategies.distance(point, range)),
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
strategies.distance(point, range).apply(point, *it_pair.first, *it_pair.second);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Ring,
|
||||
closure_selector Closure,
|
||||
typename Strategies
|
||||
>
|
||||
struct point_to_ring
|
||||
{
|
||||
typedef distance::return_t<Point, Ring, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
Ring const& ring,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (within::within_point_geometry(point, ring, strategies))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return point_to_range
|
||||
<
|
||||
Point, Ring, closure<Ring>::value, Strategies
|
||||
>::apply(point, ring, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Polygon,
|
||||
closure_selector Closure,
|
||||
typename Strategies
|
||||
>
|
||||
class point_to_polygon
|
||||
{
|
||||
public:
|
||||
typedef distance::return_t<Point, Polygon, Strategies> return_type;
|
||||
|
||||
private:
|
||||
typedef point_to_range
|
||||
<
|
||||
Point, typename ring_type<Polygon>::type, Closure, Strategies
|
||||
> per_ring;
|
||||
|
||||
struct distance_to_interior_rings
|
||||
{
|
||||
template <typename InteriorRingIterator>
|
||||
static inline return_type apply(Point const& point,
|
||||
InteriorRingIterator first,
|
||||
InteriorRingIterator last,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
for (InteriorRingIterator it = first; it != last; ++it)
|
||||
{
|
||||
if (within::within_point_geometry(point, *it, strategies))
|
||||
{
|
||||
// the point is inside a polygon hole, so its distance
|
||||
// to the polygon its distance to the polygon's
|
||||
// hole boundary
|
||||
return per_ring::apply(point, *it, strategies);
|
||||
}
|
||||
}
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
template <typename InteriorRings>
|
||||
static inline return_type apply(Point const& point, InteriorRings const& interior_rings,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return apply(point,
|
||||
boost::begin(interior_rings),
|
||||
boost::end(interior_rings),
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
static inline return_type apply(Point const& point,
|
||||
Polygon const& polygon,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
|
||||
strategies))
|
||||
{
|
||||
// the point is outside the exterior ring, so its distance
|
||||
// to the polygon is its distance to the polygon's exterior ring
|
||||
return per_ring::apply(point, exterior_ring(polygon), strategies);
|
||||
}
|
||||
|
||||
// Check interior rings
|
||||
return distance_to_interior_rings::apply(point,
|
||||
interior_rings(polygon),
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename MultiGeometry,
|
||||
typename Strategies,
|
||||
bool CheckCoveredBy = std::is_same
|
||||
<
|
||||
typename tag<MultiGeometry>::type, multi_polygon_tag
|
||||
>::value
|
||||
>
|
||||
class point_to_multigeometry
|
||||
{
|
||||
private:
|
||||
typedef detail::closest_feature::geometry_to_range geometry_to_range;
|
||||
|
||||
typedef distance::strategy_t<Point, MultiGeometry, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef distance::return_t<Point, MultiGeometry, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
MultiGeometry const& multigeometry,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef iterator_selector<MultiGeometry const> selector_type;
|
||||
|
||||
distance::creturn_t<Point, MultiGeometry, Strategies> cd;
|
||||
|
||||
typename selector_type::iterator_type it_min
|
||||
= geometry_to_range::apply(point,
|
||||
selector_type::begin(multigeometry),
|
||||
selector_type::end(multigeometry),
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
strategy_type
|
||||
>::apply(strategies.distance(point, multigeometry)),
|
||||
cd);
|
||||
|
||||
// TODO - It would be possible to use a tool similar to result_from_distance
|
||||
// but working in the opposite way, i.e. calculating the distance
|
||||
// value from comparable distance value. This way the additional distance
|
||||
// call would not be needed.
|
||||
return
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd
|
||||
:
|
||||
dispatch::distance
|
||||
<
|
||||
Point,
|
||||
typename std::iterator_traits
|
||||
<
|
||||
typename selector_type::iterator_type
|
||||
>::value_type,
|
||||
Strategies
|
||||
>::apply(point, *it_min, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// this is called only for multipolygons, hence the change in the
|
||||
// template parameter name MultiGeometry to MultiPolygon
|
||||
template <typename Point, typename MultiPolygon, typename Strategies>
|
||||
struct point_to_multigeometry<Point, MultiPolygon, Strategies, true>
|
||||
{
|
||||
typedef distance::return_t<Point, MultiPolygon, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Point const& point,
|
||||
MultiPolygon const& multipolygon,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (within::covered_by_point_geometry(point, multipolygon, strategies))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
return point_to_multigeometry
|
||||
<
|
||||
Point, MultiPolygon, Strategies, false
|
||||
>::apply(point, multipolygon, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename P1, typename P2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
P1, P2, Strategy, point_tag, point_tag,
|
||||
strategy_tag_distance_point_point, false
|
||||
> : detail::distance::point_to_point<P1, P2, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Linestring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Linestring, Strategy, point_tag, linestring_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Ring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Ring, Strategy, point_tag, ring_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_ring
|
||||
<
|
||||
Point, Ring, closure<Ring>::value, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Polygon, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Polygon, Strategy, point_tag, polygon_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_polygon
|
||||
<
|
||||
Point, Polygon, closure<Polygon>::value, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Segment, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Segment, Strategy, point_tag, segment_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_segment<Point, Segment, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Box, Strategy, point_tag, box_tag,
|
||||
strategy_tag_distance_point_box, false
|
||||
> : detail::distance::point_to_box<Point, Box, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename MultiPoint, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, MultiPoint, Strategy, point_tag, multi_point_tag,
|
||||
strategy_tag_distance_point_point, false
|
||||
> : detail::distance::point_to_multigeometry
|
||||
<
|
||||
Point, MultiPoint, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename MultiLinestring, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_multigeometry
|
||||
<
|
||||
Point, MultiLinestring, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template<typename Point, typename MultiPolygon, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_multigeometry
|
||||
<
|
||||
Point, MultiPolygon, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Linear, Strategy, point_tag, linear_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : distance
|
||||
<
|
||||
Point, Linear, Strategy,
|
||||
point_tag, typename tag<Linear>::type,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Areal, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Areal, Strategy, point_tag, areal_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : distance
|
||||
<
|
||||
Point, Areal, Strategy,
|
||||
point_tag, typename tag<Areal>::type,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
|
||||
Vendored
Executable
+117
@@ -0,0 +1,117 @@
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/geometry/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
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename PointOrSegmentIterator,
|
||||
typename Geometry,
|
||||
typename Strategies
|
||||
>
|
||||
class point_or_segment_range_to_geometry_rtree
|
||||
{
|
||||
private:
|
||||
typedef typename std::iterator_traits
|
||||
<
|
||||
PointOrSegmentIterator
|
||||
>::value_type point_or_segment_type;
|
||||
|
||||
typedef iterator_selector<Geometry const> selector_type;
|
||||
|
||||
typedef detail::closest_feature::range_to_range_rtree range_to_range;
|
||||
|
||||
typedef distance::strategy_t<point_or_segment_type, Geometry, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef distance::return_t<point_or_segment_type, Geometry, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(PointOrSegmentIterator first,
|
||||
PointOrSegmentIterator last,
|
||||
Geometry const& geometry,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( first != last );
|
||||
|
||||
if ( detail::has_one_element(first, last) )
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
point_or_segment_type, Geometry, Strategies
|
||||
>::apply(*first, geometry, strategies);
|
||||
}
|
||||
|
||||
distance::creturn_t<point_or_segment_type, Geometry, Strategies> cd_min;
|
||||
|
||||
std::pair
|
||||
<
|
||||
point_or_segment_type,
|
||||
typename selector_type::iterator_type
|
||||
> closest_features
|
||||
= range_to_range::apply(first,
|
||||
last,
|
||||
selector_type::begin(geometry),
|
||||
selector_type::end(geometry),
|
||||
strategies,
|
||||
cd_min);
|
||||
|
||||
return
|
||||
is_comparable<strategy_type>::value
|
||||
?
|
||||
cd_min
|
||||
:
|
||||
dispatch::distance
|
||||
<
|
||||
point_or_segment_type,
|
||||
typename std::iterator_traits
|
||||
<
|
||||
typename selector_type::iterator_type
|
||||
>::value_type,
|
||||
Strategies
|
||||
>::apply(closest_features.first,
|
||||
*closest_features.second,
|
||||
strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_RANGE_TO_GEOMETRY_RTREE_HPP
|
||||
+825
@@ -0,0 +1,825 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/numeric/conversion/cast.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>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/util/calculation_type.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/has_nan_coordinate.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
inline bool intersects_segment_box(Segment const& segment, Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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 Strategies,
|
||||
bool UsePointBoxStrategy = false // use only PointSegment strategy
|
||||
>
|
||||
class segment_to_box_2D_generic
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
typedef typename point_type<Box>::type box_point;
|
||||
|
||||
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
|
||||
> point_to_point_range;
|
||||
|
||||
public:
|
||||
// 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,
|
||||
Strategies const& strategies,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && intersects_segment_box(segment, box, strategies))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
// get segment points
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
// get box points
|
||||
std::vector<box_point> box_points(4);
|
||||
detail::assign_box_corners_oriented<true>(box, box_points);
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
std::pair
|
||||
<
|
||||
typename std::vector<box_point>::const_iterator,
|
||||
typename std::vector<box_point>::const_iterator
|
||||
> bit_min[2];
|
||||
|
||||
bit_min[0] = point_to_point_range::apply(p[0],
|
||||
box_points.begin(),
|
||||
box_points.end(),
|
||||
cstrategy,
|
||||
cd[4]);
|
||||
bit_min[1] = point_to_point_range::apply(p[1],
|
||||
box_points.begin(),
|
||||
box_points.end(),
|
||||
cstrategy,
|
||||
cd[5]);
|
||||
|
||||
unsigned int imin = 0;
|
||||
for (unsigned int i = 1; i < 6; ++i)
|
||||
{
|
||||
if (cd[i] < cd[imin])
|
||||
{
|
||||
imin = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<ps_strategy_type>::value))
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
return strategy.apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int bimin = imin - 4;
|
||||
return strategy.apply(p[bimin],
|
||||
*bit_min[bimin].first,
|
||||
*bit_min[bimin].second);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename Strategies
|
||||
>
|
||||
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 distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
|
||||
typedef distance::strategy_t<segment_point, Box, Strategies> pb_strategy_type;
|
||||
|
||||
public:
|
||||
// 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,
|
||||
Strategies const& strategies,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && intersects_segment_box(segment, box, strategies))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
|
||||
// get segment points
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
// get box points
|
||||
std::vector<box_point> box_points(4);
|
||||
detail::assign_box_corners_oriented<true>(box, box_points);
|
||||
|
||||
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] = ps_cstrategy.apply(box_points[i], p[0], p[1]);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
unsigned int imin = 0;
|
||||
for (unsigned int i = 1; i < 6; ++i)
|
||||
{
|
||||
if (cd[i] < cd[imin])
|
||||
{
|
||||
imin = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
if (is_comparable<ps_strategy_type>::value)
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
return ps_strategy.apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_comparable<pb_strategy_type>::value)
|
||||
{
|
||||
return cd[imin];
|
||||
}
|
||||
|
||||
return pb_strategy.apply(p[imin - 4], box);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename ReturnType,
|
||||
typename SegmentPoint,
|
||||
typename BoxPoint,
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box_2D
|
||||
{
|
||||
private:
|
||||
template <typename Result>
|
||||
struct cast_to_result
|
||||
{
|
||||
template <typename T>
|
||||
static inline Result apply(T const& t)
|
||||
{
|
||||
return boost::numeric_cast<Result>(t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, bool IsLess /* true */>
|
||||
struct compare_less_equal
|
||||
{
|
||||
typedef compare_less_equal<T, !IsLess> other;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator()(T1 const& t1, T2 const& t2) const
|
||||
{
|
||||
return std::less_equal<T>()(cast_to_result<T>::apply(t1),
|
||||
cast_to_result<T>::apply(t2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct compare_less_equal<T, false>
|
||||
{
|
||||
typedef compare_less_equal<T, true> other;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline bool operator()(T1 const& t1, T2 const& t2) const
|
||||
{
|
||||
return std::greater_equal<T>()(cast_to_result<T>::apply(t1),
|
||||
cast_to_result<T>::apply(t2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename LessEqual>
|
||||
struct other_compare
|
||||
{
|
||||
typedef typename LessEqual::other type;
|
||||
};
|
||||
|
||||
|
||||
// it is assumed here that p0 lies to the right of the box (so the
|
||||
// entire segment lies to the right of the box)
|
||||
template <typename LessEqual>
|
||||
struct right_of_box
|
||||
{
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& bottom_right,
|
||||
BoxPoint const& top_right,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
// the implementation below is written for non-negative slope
|
||||
// segments
|
||||
//
|
||||
// for negative slope segments swap the roles of bottom_right
|
||||
// and top_right and use greater_equal instead of less_equal.
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
|
||||
LessEqual less_equal;
|
||||
|
||||
auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
|
||||
if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
|
||||
{
|
||||
//if p0 is in box's band
|
||||
if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right)))
|
||||
{
|
||||
// segment & crosses band (TODO:merge with box-box dist)
|
||||
if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1)))
|
||||
{
|
||||
SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0;
|
||||
if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right)))
|
||||
{
|
||||
return cast::apply(ps_strategy.apply(high, bottom_right, top_right));
|
||||
}
|
||||
return cast::apply(ps_strategy.apply(top_right, p0, p1));
|
||||
}
|
||||
return cast::apply(ps_strategy.apply(p0, bottom_right, top_right));
|
||||
}
|
||||
// distance is realized between the top-right
|
||||
// corner of the box and the segment
|
||||
return cast::apply(ps_strategy.apply(top_right, p0, p1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// distance is realized between the bottom-right
|
||||
// corner of the box and the segment
|
||||
return cast::apply(ps_strategy.apply(bottom_right, p0, p1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// it is assumed here that p0 lies above the box (so the
|
||||
// entire segment lies above the box)
|
||||
|
||||
template <typename LessEqual>
|
||||
struct above_of_box
|
||||
{
|
||||
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
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,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
LessEqual less_equal;
|
||||
|
||||
// p0 is above the upper segment of the box (and inside its band)
|
||||
// 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 = 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
|
||||
<
|
||||
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(ps_strategy.apply(top_left, p0, p1));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename LessEqual>
|
||||
struct check_right_left_of_box
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
Strategies const& strategies,
|
||||
ReturnType& result)
|
||||
{
|
||||
// p0 lies to the right of the box
|
||||
if (geometry::get<0>(p0) >= geometry::get<0>(top_right))
|
||||
{
|
||||
result = right_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, bottom_right, top_right,
|
||||
strategies);
|
||||
return true;
|
||||
}
|
||||
|
||||
// p1 lies to the left of the box
|
||||
if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))
|
||||
{
|
||||
result = right_of_box
|
||||
<
|
||||
typename other_compare<LessEqual>::type
|
||||
>::apply(p1, p0, top_left, bottom_left,
|
||||
strategies);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename LessEqual>
|
||||
struct check_above_below_of_box
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
Strategies const& strategies,
|
||||
ReturnType& result)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> GreaterEqual;
|
||||
|
||||
// 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,
|
||||
strategies);
|
||||
return true;
|
||||
}
|
||||
|
||||
// the segment lies above the box
|
||||
if (geometry::get<1>(p0) > geometry::get<1>(top_right))
|
||||
{
|
||||
result = (std::min)(above_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, top_left, strategies),
|
||||
above_of_box
|
||||
<
|
||||
GreaterEqual
|
||||
>::apply(p1, p0, top_right, strategies));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct check_generic_position
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& corner1,
|
||||
BoxPoint const& corner2,
|
||||
Strategies const& strategies,
|
||||
ReturnType& result)
|
||||
{
|
||||
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));
|
||||
|
||||
int sign = diff1 < 0 ? -1 : 1;
|
||||
if (side_strategy.apply(p0, p1, corner1) * sign < 0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
|
||||
return true;
|
||||
}
|
||||
if (side_strategy.apply(p0, p1, corner2) * sign > 0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner2, p0, p1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static inline ReturnType
|
||||
non_negative_slope_segment(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, true> less_equal;
|
||||
|
||||
// assert that the segment has non-negative slope
|
||||
BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
|
||||
&& geometry::get<1>(p0) < geometry::get<1>(p1))
|
||||
||
|
||||
( geometry::get<0>(p0) < geometry::get<0>(p1)
|
||||
&& geometry::get<1>(p0) <= geometry::get<1>(p1) )
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1));
|
||||
|
||||
ReturnType result(0);
|
||||
|
||||
if (check_right_left_of_box
|
||||
<
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_above_below_of_box
|
||||
<
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
top_left, bottom_right,
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// in all other cases the box and segment intersect, so return 0
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline ReturnType
|
||||
negative_slope_segment(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> greater_equal;
|
||||
|
||||
// assert that the segment has negative slope
|
||||
BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1)
|
||||
&& geometry::get<1>(p0) > geometry::get<1>(p1) )
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1) );
|
||||
|
||||
ReturnType result(0);
|
||||
|
||||
if (check_right_left_of_box
|
||||
<
|
||||
greater_equal
|
||||
>::apply(p0, p1,
|
||||
bottom_left, bottom_right, top_left, top_right,
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_above_below_of_box
|
||||
<
|
||||
greater_equal
|
||||
>::apply(p1, p0,
|
||||
top_right, top_left, bottom_right, bottom_left,
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
bottom_left, top_right,
|
||||
strategies, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// in all other cases the box and segment intersect, so return 0
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, Strategies>()(p0, p1))
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
|| geometry::has_nan_coordinate(p1) );
|
||||
|
||||
if (geometry::get<0>(p0) < geometry::get<0>(p1)
|
||||
&& geometry::get<1>(p0) > geometry::get<1>(p1))
|
||||
{
|
||||
return negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
strategies);
|
||||
}
|
||||
|
||||
return non_negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
strategies);
|
||||
}
|
||||
|
||||
template <typename LessEqual>
|
||||
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
SegmentPoint const& p_max,
|
||||
BoxPoint const& top_left,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
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,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
return above_of_box<LessEqual>::apply(p0, p1, top_left, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename std::size_t Dimension,
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box
|
||||
: not_implemented<Segment, Box>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename Strategies
|
||||
>
|
||||
class segment_to_box<Segment, Box, 2, Strategies>
|
||||
{
|
||||
typedef distance::strategy_t<Segment, Box, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef distance::return_t<Segment, Box, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
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], strategies))
|
||||
{
|
||||
return dispatch::distance
|
||||
<
|
||||
segment_point,
|
||||
Box,
|
||||
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);
|
||||
|
||||
strategy_type::mirror(p[0], p[1],
|
||||
bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
|
||||
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,
|
||||
Strategies
|
||||
>::apply(p[0], p[1],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
strategies);
|
||||
}
|
||||
else
|
||||
{
|
||||
return segment_to_box_2D
|
||||
<
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
Strategies
|
||||
>::apply(p[1], p[0],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
strategies);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Segment, typename Box, typename Strategies>
|
||||
struct distance
|
||||
<
|
||||
Segment, Box, Strategies, segment_tag, box_tag,
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
{
|
||||
static inline auto apply(Segment const& segment, Box const& box,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
assert_dimension_equal<Segment, Box>();
|
||||
|
||||
return detail::distance::segment_to_box
|
||||
<
|
||||
Segment,
|
||||
Box,
|
||||
dimension<Segment>::value,
|
||||
Strategies
|
||||
>::apply(segment, box, strategies);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
|
||||
Vendored
Executable
+136
@@ -0,0 +1,136 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
|
||||
#include <boost/geometry/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/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 distance
|
||||
{
|
||||
|
||||
|
||||
|
||||
// compute segment-segment distance
|
||||
template<typename Segment1, typename Segment2, typename Strategies>
|
||||
class segment_to_segment
|
||||
{
|
||||
typedef distance::strategy_t<Segment1, Segment2, Strategies> strategy_type;
|
||||
|
||||
public:
|
||||
typedef distance::return_t<Segment1, Segment2, Strategies> return_type;
|
||||
|
||||
static inline return_type apply(Segment1 const& segment1, Segment2 const& segment2,
|
||||
Strategies const& strategies)
|
||||
{
|
||||
if (geometry::intersects(segment1, segment2, strategies))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
typename point_type<Segment1>::type p[2];
|
||||
detail::assign_point_from_index<0>(segment1, p[0]);
|
||||
detail::assign_point_from_index<1>(segment1, p[1]);
|
||||
|
||||
typename point_type<Segment2>::type q[2];
|
||||
detail::assign_point_from_index<0>(segment2, q[0]);
|
||||
detail::assign_point_from_index<1>(segment2, q[1]);
|
||||
|
||||
strategy_type const strategy = strategies.distance(segment1, segment2);
|
||||
|
||||
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]);
|
||||
d[3] = cstrategy.apply(p[1], q[0], q[1]);
|
||||
|
||||
std::size_t imin = std::distance(boost::addressof(d[0]),
|
||||
std::min_element(d, d + 4));
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(is_comparable<strategy_type>::value))
|
||||
{
|
||||
return d[imin];
|
||||
}
|
||||
|
||||
switch (imin)
|
||||
{
|
||||
case 0:
|
||||
return strategy.apply(q[0], p[0], p[1]);
|
||||
case 1:
|
||||
return strategy.apply(q[1], p[0], p[1]);
|
||||
case 2:
|
||||
return strategy.apply(p[0], q[0], q[1]);
|
||||
default:
|
||||
return strategy.apply(p[1], q[0], q[1]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
|
||||
// segment-segment
|
||||
template <typename Segment1, typename Segment2, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Segment1, Segment2, Strategy, segment_tag, segment_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
>
|
||||
: detail::distance::segment_to_segment<Segment1, Segment2, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
|
||||
+64
@@ -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
|
||||
+56
@@ -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
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
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>
|
||||
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
typename ring_return_type<Polygon const>::type ext_ring
|
||||
= exterior_ring(polygon);
|
||||
|
||||
if (geometry::is_empty(ext_ring))
|
||||
{
|
||||
// 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_hole
|
||||
>::template apply<strategy_t>(interior_rings(polygon), mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, consider only the exterior ring
|
||||
envelope_range::apply(ext_ring, mbr, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct envelope<Ring, ring_tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct envelope<Polygon, polygon_tag>
|
||||
: detail::envelope::envelope_polygon
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct envelope<MultiPolygon, multi_polygon_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-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
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
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& strategy)
|
||||
{
|
||||
using strategy_t = decltype(strategy.envelope(box_in, mbr));
|
||||
strategy_t::apply(box_in, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
Vendored
Executable
+62
@@ -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
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-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.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/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>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
|
||||
#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
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct initialize_loop
|
||||
{
|
||||
template <typename Box, typename CoordinateType>
|
||||
static inline void apply(Box& box,
|
||||
CoordinateType min_value,
|
||||
CoordinateType max_value)
|
||||
{
|
||||
geometry::set<min_corner, Dimension>(box, min_value);
|
||||
geometry::set<max_corner, Dimension>(box, max_value);
|
||||
|
||||
initialize_loop
|
||||
<
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(box, min_value, max_value);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct initialize_loop<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box, typename CoordinateType>
|
||||
static inline void apply(Box&, CoordinateType, CoordinateType)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Box,
|
||||
std::size_t Dimension = 0,
|
||||
std::size_t DimensionCount = dimension<Box>::value
|
||||
>
|
||||
struct initialize
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type coordinate_type;
|
||||
|
||||
static inline void apply(Box& box,
|
||||
coordinate_type min_value
|
||||
= boost::numeric::bounds<coordinate_type>::highest(),
|
||||
coordinate_type max_value
|
||||
= boost::numeric::bounds<coordinate_type>::lowest())
|
||||
{
|
||||
initialize_loop
|
||||
<
|
||||
Dimension, DimensionCount
|
||||
>::apply(box, min_value, max_value);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INITIALIZE_HPP
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-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.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/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/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
|
||||
{
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Strategy,
|
||||
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
|
||||
>
|
||||
struct envelope
|
||||
{
|
||||
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 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 strategies::envelope::services::default_strategy
|
||||
<
|
||||
Geometry, Box
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
namespace resolve_dynamic
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct envelope
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
concepts::check<Box>();
|
||||
|
||||
resolve_strategy::envelope<Strategy>::apply(geometry, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct envelope<Geometry, dynamic_geometry_tag>
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Box& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
traits::visit<Geometry>::apply([&](auto const& g)
|
||||
{
|
||||
envelope<util::remove_cref_t<decltype(g)>>::apply(g, box, strategy);
|
||||
}, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_dynamic
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope (with strategy)}
|
||||
\ingroup envelope
|
||||
\details \details_calc{envelope,\det_envelope}.
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Box \tparam_box
|
||||
\tparam Strategy \tparam_strategy{Envelope}
|
||||
\param geometry \param_geometry
|
||||
\param mbr \param_box \param_set{envelope}
|
||||
\param strategy \param_strategy{envelope}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[envelope] [envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Box, typename Strategy>
|
||||
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{envelope,\det_envelope}.
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Box \tparam_box
|
||||
\param geometry \param_geometry
|
||||
\param mbr \param_box \param_set{envelope}
|
||||
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[envelope] [envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Geometry, typename Box>
|
||||
inline void envelope(Geometry const& geometry, Box& mbr)
|
||||
{
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
|
||||
\tparam Box \tparam_box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Envelope}
|
||||
\param geometry \param_geometry
|
||||
\param strategy \param_strategy{envelope}
|
||||
\return \return_calc{envelope}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[return_envelope] [return_envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Box, typename Geometry, typename Strategy>
|
||||
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
Box mbr;
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
|
||||
return mbr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_calc{envelope}
|
||||
\ingroup envelope
|
||||
\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
|
||||
\tparam Box \tparam_box
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_calc{envelope}
|
||||
|
||||
\qbk{[include reference/algorithms/envelope.qbk]}
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[return_envelope] [return_envelope_output]
|
||||
}
|
||||
*/
|
||||
template<typename Box, typename Geometry>
|
||||
inline Box return_envelope(Geometry const& geometry)
|
||||
{
|
||||
Box mbr;
|
||||
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
|
||||
return mbr;
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
Vendored
Executable
+78
@@ -0,0 +1,78 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct intersects_antimeridian
|
||||
{
|
||||
template <typename Units, typename CoordinateType>
|
||||
static inline bool apply(CoordinateType const& lon1,
|
||||
CoordinateType const& lat1,
|
||||
CoordinateType const& lon2,
|
||||
CoordinateType const& lat2)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
CoordinateType, Units
|
||||
> constants;
|
||||
|
||||
return
|
||||
math::equals(math::abs(lat1), constants::max_latitude())
|
||||
||
|
||||
math::equals(math::abs(lat2), constants::max_latitude())
|
||||
||
|
||||
math::larger(math::abs(lon1 - lon2), constants::half_period());
|
||||
}
|
||||
|
||||
template <typename Segment>
|
||||
static inline bool apply(Segment const& segment)
|
||||
{
|
||||
return apply(detail::indexed_point_view<Segment, 0>(segment),
|
||||
detail::indexed_point_view<Segment, 1>(segment));
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
static inline bool apply(Point const& p1, Point const& p2)
|
||||
{
|
||||
Point p1_normalized = detail::return_normalized<Point>(p1);
|
||||
Point p2_normalized = detail::return_normalized<Point>(p2);
|
||||
|
||||
return apply
|
||||
<
|
||||
typename coordinate_system<Point>::type::units
|
||||
>(geometry::get<0>(p1_normalized),
|
||||
geometry::get<1>(p1_normalized),
|
||||
geometry::get<0>(p2_normalized),
|
||||
geometry::get<1>(p2_normalized));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERSECTS_ANTIMERIDIAN_HPP
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-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
|
||||
// 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_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linestring>
|
||||
struct envelope<Linestring, linestring_tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct envelope<MultiLinestring, multi_linestring_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_range
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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
|
||||
// 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_MULTIPOINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
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& strategy)
|
||||
{
|
||||
// strategy.envelope(multipoint, mbr).apply(multipoint, mbr);
|
||||
using strategy_t = decltype(strategy.envelope(multipoint, mbr));
|
||||
strategy_t::apply(multipoint, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-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
|
||||
// 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_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
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& strategy)
|
||||
{
|
||||
// strategy.envelope(point, mbr).apply(point, mbr);
|
||||
using strategy_t = decltype(strategy.envelope(point, mbr));
|
||||
strategy_t::apply(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag>
|
||||
: detail::envelope::envelope_point
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user