update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -5,9 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-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
@@ -23,7 +22,6 @@
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -38,45 +36,26 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/normalize.hpp>
namespace boost { namespace geometry
{
// TODO: dispatch only by SideStrategy instead of Geometry/CSTag?
// Since these vectors (though ray would be a better name) are used in the
// implementation of equals() for Areal geometries the internal representation
// should be consistent with the side strategy.
template
<
typename T,
typename Geometry,
typename SideStrategy,
typename CSTag = typename cs_tag<Geometry>::type
>
struct collected_vector
: nyi::not_implemented_tag
{};
// compatible with side_by_triangle cartesian strategy
template <typename T, typename Geometry, typename CT, typename CSTag>
struct collected_vector
<
T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
>
template <typename T>
struct collected_vector_cartesian
{
typedef T type;
inline collected_vector()
inline collected_vector_cartesian()
{}
inline collected_vector(T const& px, T const& py,
T const& pdx, T const& pdy)
inline collected_vector_cartesian(T const& px, T const& py,
T const& pdx, T const& pdy)
: x(px)
, y(py)
, dx(pdx)
@@ -86,7 +65,7 @@ struct collected_vector
{}
template <typename Point>
inline collected_vector(Point const& p1, Point const& p2)
inline collected_vector_cartesian(Point const& p1, Point const& p2)
: x(get<0>(p1))
, y(get<1>(p1))
, dx(get<0>(p2) - x)
@@ -97,8 +76,7 @@ struct collected_vector
bool normalize()
{
T magnitude = math::sqrt(
boost::numeric_cast<T>(dx * dx + dy * dy));
T magnitude = math::sqrt(boost::numeric_cast<T>(dx * dx + dy * dy));
// NOTE: shouldn't here math::equals() be called?
if (magnitude > 0)
@@ -112,7 +90,7 @@ struct collected_vector
}
// For sorting
inline bool operator<(collected_vector const& other) const
inline bool operator<(collected_vector_cartesian const& other) const
{
if (math::equals(x, other.x))
{
@@ -129,13 +107,13 @@ struct collected_vector
return x < other.x;
}
inline bool next_is_collinear(collected_vector const& other) const
inline bool next_is_collinear(collected_vector_cartesian const& other) const
{
return same_direction(other);
}
// For std::equals
inline bool operator==(collected_vector const& other) const
inline bool operator==(collected_vector_cartesian const& other) const
{
return math::equals(x, other.x)
&& math::equals(y, other.y)
@@ -143,12 +121,12 @@ struct collected_vector
}
private:
inline bool same_direction(collected_vector const& other) const
inline bool same_direction(collected_vector_cartesian const& other) const
{
// For high precision arithmetic, we have to be
// more relaxed then using ==
// Because 2/sqrt( (0,0)<->(2,2) ) == 1/sqrt( (0,0)<->(1,1) )
// is not always true (at least, it is not for ttmath)
// is not always true (at least, not for some user defined types)
return math::equals_with_epsilon(dx, other.dx)
&& math::equals_with_epsilon(dy, other.dy);
}
@@ -159,37 +137,34 @@ private:
};
// Compatible with spherical_side_formula which currently
// is the default spherical and geographical strategy
template <typename T, typename Geometry, typename CT, typename CSTag>
struct collected_vector
<
T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
>
// is the default spherical_equatorial and geographic strategy
// so CSTag is spherical_equatorial_tag or geographic_tag
template <typename T, typename Point>
struct collected_vector_spherical
{
typedef T type;
typedef typename coordinate_system<Geometry>::type cs_type;
typedef model::point<T, 2, cs_type> point_type;
typedef model::point<T, 3, cs::cartesian> vector_type;
collected_vector()
collected_vector_spherical()
{}
template <typename Point>
collected_vector(Point const& p1, Point const& p2)
collected_vector_spherical(Point const& p1, Point const& p2)
: origin(get<0>(p1), get<1>(p1))
{
origin = detail::return_normalized<point_type>(origin);
origin = detail::return_normalized<Point>(
origin,
strategy::normalize::spherical_point());
using namespace geometry::formula;
prev = sph_to_cart3d<vector_type>(p1);
next = sph_to_cart3d<vector_type>(p2);
direction = cross_product(prev, next);
cross = direction = cross_product(prev, next);
}
bool normalize()
{
T magnitude_sqr = dot_product(direction, direction);
T const magnitude_sqr = dot_product(direction, direction);
// NOTE: shouldn't here math::equals() be called?
if (magnitude_sqr > 0)
@@ -201,7 +176,7 @@ struct collected_vector
return false;
}
bool operator<(collected_vector const& other) const
bool operator<(collected_vector_spherical const& other) const
{
if (math::equals(get<0>(origin), get<0>(other.origin)))
{
@@ -225,13 +200,13 @@ struct collected_vector
// For consistency with side and intersection strategies used by relops
// IMPORTANT: this method should be called for previous vector
// and next vector should be passed as parameter
bool next_is_collinear(collected_vector const& other) const
bool next_is_collinear(collected_vector_spherical const& other) const
{
return formula::sph_side_value(direction, other.next) == 0;
return formula::sph_side_value(cross, other.next) == 0;
}
// For std::equals
bool operator==(collected_vector const& other) const
bool operator==(collected_vector_spherical const& other) const
{
return math::equals(get<0>(origin), get<0>(other.origin))
&& math::equals(get<1>(origin), get<1>(other.origin))
@@ -240,74 +215,58 @@ struct collected_vector
private:
// For consistency with side and intersection strategies used by relops
bool is_collinear(collected_vector const& other) const
// NOTE: alternative would be to equal-compare direction's coordinates
// or to check if dot product of directions is equal to 1.
bool is_collinear(collected_vector_spherical const& other) const
{
return formula::sph_side_value(direction, other.prev) == 0
&& formula::sph_side_value(direction, other.next) == 0;
return formula::sph_side_value(cross, other.prev) == 0
&& formula::sph_side_value(cross, other.next) == 0;
}
/*bool same_direction(collected_vector const& other) const
{
return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction))
&& math::equals_with_epsilon(get<1>(direction), get<1>(other.direction))
&& math::equals_with_epsilon(get<2>(direction), get<2>(other.direction));
}*/
point_type origin; // used for sorting and equality check
Point origin; // used for sorting and equality check
vector_type direction; // used for sorting, only in operator<
vector_type cross; // used for sorting, used for collinearity check
vector_type prev; // used for collinearity check, only in operator==
vector_type next; // used for collinearity check
};
// Specialization for spherical polar
template <typename T, typename Geometry, typename CT>
struct collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_polar_tag
>
: public collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_equatorial_tag
>
// Version for spherical polar
template <typename T, typename Point>
struct collected_vector_polar
: public collected_vector_spherical<T, Point>
{
typedef collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_equatorial_tag
> base_type;
using type = T;
using base_point_type
= model::point<T, 2, cs::spherical_equatorial<geometry::degree>>;
using base_type = collected_vector_spherical<T, base_point_type>;
collected_vector() {}
collected_vector_polar() {}
template <typename Point>
collected_vector(Point const& p1, Point const& p2)
collected_vector_polar(Point const& p1, Point const& p2)
: base_type(to_equatorial(p1), to_equatorial(p2))
{}
private:
template <typename Point>
Point polar_to_equatorial(Point const& p)
static base_point_type to_equatorial(Point const& p)
{
typedef typename coordinate_type<Point>::type coord_type;
typedef math::detail::constants_on_spheroid
using coord_type = typename coordinate_type<Point>::type;
using constants = math::detail::constants_on_spheroid
<
coord_type,
typename coordinate_system<Point>::type::units
> constants;
> ;
coord_type const pi_2 = constants::half_period() / 2;
constexpr coord_type pi_2 = constants::half_period() / 2;
Point res = p;
base_point_type res;
set<0>(res, get<0>(p));
set<1>(res, pi_2 - get<1>(p));
return res;
}
};
// TODO: implement collected_vector type for geographic
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace collect_vectors
@@ -322,34 +281,24 @@ struct range_collect_vectors
static inline void apply(Collection& collection, Range const& range)
{
typedef geometry::detail::normalized_view
<
Range const
> normalized_range_type;
apply_impl(collection, normalized_range_type(range));
apply_impl(collection,
detail::closed_clockwise_view<Range const>(range));
}
private:
template <typename NormalizedRange>
static inline void apply_impl(Collection& collection, NormalizedRange const& range)
template <typename ClosedClockwiseRange>
static inline void apply_impl(Collection& collection, ClosedClockwiseRange const& range)
{
if (boost::size(range) < 2)
{
return;
}
typedef typename boost::range_size<Collection>::type collection_size_t;
collection_size_t c_old_size = boost::size(collection);
typedef typename boost::range_iterator<NormalizedRange const>::type iterator;
auto c_old_size = boost::size(collection);
bool is_first = true;
iterator it = boost::begin(range);
auto it = boost::begin(range);
for (iterator prev = it++;
it != boost::end(range);
prev = it++)
for (auto prev = it++; it != boost::end(range); prev = it++)
{
typename boost::range_value<Collection>::type v(*prev, *it);
@@ -368,13 +317,10 @@ private:
}
// If first one has same direction as last one, remove first one
collection_size_t collected_count = boost::size(collection) - c_old_size;
if ( collected_count > 1 )
if (boost::size(collection) > c_old_size + 1)
{
typedef typename boost::range_iterator<Collection>::type c_iterator;
c_iterator first = range::pos(collection, c_old_size);
if (collection.back().next_is_collinear(*first) )
auto first = range::pos(collection, c_old_size);
if (collection.back().next_is_collinear(*first))
{
//collection.erase(first);
// O(1) instead of O(N)
@@ -453,10 +399,8 @@ struct polygon_collect_vectors
typedef range_collect_vectors<ring_type, Collection> per_range;
per_range::apply(collection, exterior_ring(polygon));
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
auto const& rings = interior_rings(polygon);
for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_range::apply(collection, *it);
}
@@ -469,10 +413,7 @@ struct multi_collect_vectors
{
static inline void apply(Collection& collection, MultiGeometry const& multi)
{
for (typename boost::range_iterator<MultiGeometry const>::type
it = boost::begin(multi);
it != boost::end(multi);
++it)
for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
SinglePolicy::apply(collection, *it);
}

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2022.
// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -23,28 +23,30 @@
#include <cstddef>
#include <type_traits>
#include <vector>
#include <boost/range.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/range/size.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
// For trivial checks
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/length.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.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/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
@@ -64,9 +66,11 @@ template
struct point_point
{
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
static inline bool apply(Point1 const& point1, Point2 const& point2,
Strategy const& strategy)
{
return Strategy::apply(point1, point2);
typedef decltype(strategy.relate(point1, point2)) strategy_type;
return strategy_type::apply(point1, point2);
}
};
@@ -107,25 +111,22 @@ struct segment_segment
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
Strategy const& strategy)
{
typename Strategy::point_in_point_strategy_type const&
pt_pt_strategy = strategy.get_point_in_point_strategy();
return equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 0>(segment2),
pt_pt_strategy)
strategy)
? equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 1>(segment2),
pt_pt_strategy)
strategy)
: ( equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 1>(segment2),
pt_pt_strategy)
strategy)
&& equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 0>(segment2),
pt_pt_strategy)
strategy)
);
}
};
@@ -138,15 +139,13 @@ struct area_check
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::area(geometry1,
strategy.template get_area_strategy<Geometry1>()),
geometry::area(geometry2,
strategy.template get_area_strategy<Geometry2>()));
return geometry::math::equals(geometry::area(geometry1, strategy),
geometry::area(geometry2, strategy));
}
};
/*
struct length_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
@@ -154,35 +153,39 @@ struct length_check
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::length(geometry1,
strategy.template get_distance_strategy<Geometry1>()),
geometry::length(geometry2,
strategy.template get_distance_strategy<Geometry2>()));
return geometry::math::equals(geometry::length(geometry1, strategy),
geometry::length(geometry2, strategy));
}
};
*/
template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
struct collected_vector
// Small helper structure do decide to use collect_vectors, or not
template <typename Strategy, typename CsTag>
struct use_collect_vectors
{
typedef typename geometry::select_most_precise
<
typename select_coordinate_type
<
Geometry1, Geometry2
>::type,
double
>::type calculation_type;
typedef geometry::collected_vector
<
calculation_type,
Geometry1,
typename IntersectionStrategy::side_strategy_type
> type;
static constexpr bool value = false;
};
template <typename Strategy>
struct use_collect_vectors<Strategy, cartesian_tag>
{
static constexpr bool value = true;
template <typename T, typename Point>
using type = collected_vector_cartesian<T>;
};
template <typename CV>
struct use_collect_vectors<strategy::side::spherical_side_formula<CV>, spherical_tag>
{
static constexpr bool value = true;
template <typename T, typename Point>
using type = collected_vector_spherical<T, Point>;
};
template <typename TrivialCheck>
struct equals_by_collection
{
@@ -196,10 +199,24 @@ struct equals_by_collection
return false;
}
typedef typename collected_vector
using calculation_type = typename geometry::select_most_precise
<
Geometry1, Geometry2, Strategy
>::type collected_vector_type;
typename select_coordinate_type
<
Geometry1, Geometry2
>::type,
double
>::type;
using collected_vector_type = typename use_collect_vectors
<
decltype(std::declval<Strategy>().side()),
typename Strategy::cs_tag
>::template type
<
calculation_type,
typename geometry::point_type<Geometry1>::type
>;
std::vector<collected_vector_type> c1, c2;
@@ -214,7 +231,7 @@ struct equals_by_collection
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
// Just check if these vectors are equal.
// Check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin());
}
};
@@ -229,52 +246,54 @@ struct equals_by_relate
>
{};
// If collect_vectors which is a SideStrategy-dispatched optimization
// is implemented in a way consistent with the Intersection/Side Strategy
// then collect_vectors is used, otherwise relate is used.
// Use either collect_vectors or relate
// NOTE: the result could be conceptually different for invalid
// geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently.
template<typename TrivialCheck>
struct equals_by_collection_or_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
template <typename Strategy>
using use_vectors = use_collect_vectors
<
decltype(std::declval<Strategy>().side()),
typename Strategy::cs_tag
>;
template
<
typename Geometry1, typename Geometry2, typename Strategy,
std::enable_if_t<use_vectors<Strategy>::value, int> = 0
>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
typedef typename boost::is_base_of
<
nyi::not_implemented_tag,
typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type
>::type enable_relate_type;
return apply(geometry1, geometry2, strategy, enable_relate_type());
}
private:
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::false_type /*enable_relate*/)
{
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2, typename Strategy>
template
<
typename Geometry1, typename Geometry2, typename Strategy,
std::enable_if_t<! use_vectors<Strategy>::value, int> = 0
>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::true_type /*enable_relate*/)
Strategy const& strategy)
{
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
};
struct equals_always_false
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const& )
{
return false;
}
};
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
@@ -285,81 +304,92 @@ namespace dispatch
{
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
struct equals<P1, P2, point_tag, point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
: detail::equals::point_point<0, DimensionCount>
{};
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
{};
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<Point, MultiPoint>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
struct equals<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, DimensionCount, Reverse>
: detail::equals::box_box<0, DimensionCount>
{};
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Ring, typename Box, bool Reverse>
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
struct equals<Ring, Box, ring_tag, box_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon, typename Box, bool Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, linear_tag, linear_tag, DimensionCount, Reverse>
: detail::equals::segment_segment
{};
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
template <typename LineString, typename MultiLineString, bool Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, MultiLineString>
{};
template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
{};
template <typename LineString, typename Segment, bool Reverse>
struct equals<LineString, Segment, linestring_tag, segment_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, Segment>
{};
template <typename MultiLineString, typename Segment, bool Reverse>
struct equals<MultiLineString, Segment, multi_linestring_tag, segment_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString, Segment>
{};
template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
areal_tag, areal_tag,
2,
Reverse
>
@@ -372,6 +402,7 @@ struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
areal_tag, areal_tag,
2,
Reverse
>
@@ -383,6 +414,7 @@ struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
areal_tag, areal_tag,
2,
Reverse
>
@@ -390,6 +422,42 @@ struct equals
{};
// NOTE: degenerated linear geometries, e.g. segment or linestring containing
// 2 equal points, are considered to be invalid. Though theoretically
// degenerated segments and linestrings could be treated as points and
// multi-linestrings as multi-points.
// This reasoning could also be applied to boxes.
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, linear_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, linear_tag, pointlike_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, areal_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, areal_tag, pointlike_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, linear_tag, areal_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, areal_tag, linear_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -0,0 +1,114 @@
// 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_EQUALS_IMPLEMENTATION_GC_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP
#include <boost/geometry/algorithms/detail/equals/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, std::size_t DimensionCount>
struct equals
<
Geometry1, Geometry2,
geometry_collection_tag, geometry_collection_tag,
geometry_collection_tag, geometry_collection_tag,
DimensionCount, false
>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return detail::relate::relate_impl
<
detail::de9im::static_mask_equals_type,
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy);
}
};
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename CastedTag1,
std::size_t DimensionCount
>
struct equals
<
Geometry1, Geometry2,
Tag1, geometry_collection_tag,
CastedTag1, geometry_collection_tag,
DimensionCount, false
>
{
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 equals
<
gc1_view_t, Geometry2
>::apply(gc1_view_t(geometry1), geometry2, strategy);
}
};
template
<
typename Geometry1, typename Geometry2,
typename Tag2, typename CastedTag2,
std::size_t DimensionCount
>
struct equals
<
Geometry1, Geometry2,
geometry_collection_tag, Tag2,
geometry_collection_tag, CastedTag2,
DimensionCount, false
>
{
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 equals
<
Geometry1, gc2_view_t
>::apply(geometry1, gc2_view_t(geometry2), strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP

View File

@@ -5,9 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2022.
// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -24,19 +23,19 @@
#include <cstddef>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
namespace boost { namespace geometry
@@ -52,6 +51,8 @@ template
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
@@ -64,10 +65,11 @@ template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
typename CastedTag1, typename CastedTag2,
std::size_t DimensionCount
>
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
struct equals<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, DimensionCount, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
@@ -76,6 +78,7 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
<
Geometry2, Geometry1,
Tag2, Tag1,
CastedTag2, CastedTag1,
DimensionCount,
false
>::apply(g2, g1, strategy);
@@ -90,9 +93,14 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
namespace resolve_strategy
{
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct equals
{
template <typename Geometry1, typename Geometry2, typename Strategy>
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
@@ -102,13 +110,35 @@ struct equals
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
};
template <typename Strategy>
struct equals<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::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2,
strategy_converter<Strategy>::get(strategy));
}
};
template <>
struct equals<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
typedef typename strategies::relate::services::default_strategy
<
Geometry1,
Geometry2
@@ -124,9 +154,14 @@ struct equals
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry1, typename Geometry2>
template
<
typename Geometry1, typename Geometry2,
typename Tag1 = typename geometry::tag<Geometry1>::type,
typename Tag2 = typename geometry::tag<Geometry2>::type
>
struct equals
{
template <typename Strategy>
@@ -141,118 +176,73 @@ struct equals
>();
return resolve_strategy::equals
::apply(geometry1, geometry2, strategy);
<
Strategy
>::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
template <typename Geometry1, typename Geometry2, typename Tag2>
struct equals<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
inline bool operator()(Geometry1 const& geometry1) const
bool result = false;
traits::visit<Geometry1>::apply([&](auto const& g1)
{
return equals<Geometry1, Geometry2>
::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
result = equals
<
util::remove_cref_t<decltype(g1)>,
Geometry2
>::apply(g1, geometry2, strategy);
}, geometry1);
return result;
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry1, typename Geometry2, typename Tag1>
struct equals<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
inline bool operator()(Geometry2 const& geometry2) const
bool result = false;
traits::visit<Geometry2>::apply([&](auto const& g2)
{
return equals<Geometry1, Geometry2>
::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
result = equals
<
Geometry1,
util::remove_cref_t<decltype(g2)>
>::apply(geometry1, g2, strategy);
}, geometry2);
return result;
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct equals<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
template <typename Geometry1, typename Geometry2>
struct equals<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
inline bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
bool result = false;
traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
return equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
result = equals
<
util::remove_cref_t<decltype(g1)>,
util::remove_cref_t<decltype(g2)>
>::apply(g1, g2, strategy);
}, geometry1, geometry2);
return result;
}
};
} // namespace resolve_variant
} // namespace resolve_dynamic
/*!
@@ -279,10 +269,10 @@ inline bool equals(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
return resolve_dynamic::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
@@ -305,8 +295,10 @@ inline bool equals(Geometry1 const& geometry1,
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, default_strategy());
return resolve_dynamic::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -22,6 +22,11 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
#include <type_traits>
#include <boost/geometry/strategies/detail.hpp>
namespace boost { namespace geometry
{
@@ -33,7 +38,23 @@ namespace detail { namespace equals
\brief Internal utility function to detect of points are disjoint
\note To avoid circular references
*/
template <typename Point1, typename Point2, typename Strategy>
template
<
typename Point1, typename Point2, typename Strategy,
std::enable_if_t<strategies::detail::is_umbrella_strategy<Strategy>::value, int> = 0
>
inline bool equals_point_point(Point1 const& point1, Point2 const& point2,
Strategy const& strategy)
{
typedef decltype(strategy.relate(point1, point2)) strategy_type;
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 equals_point_point(Point1 const& point1, Point2 const& point2,
Strategy const& )
{