[util] Add for_each_dimension and use it in several places.

This commit is contained in:
Adam Wulkiewicz 2021-03-13 18:16:06 +01:00
parent 8b6929193d
commit d2c79d97a9
16 changed files with 737 additions and 438 deletions

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020-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
@ -45,8 +45,6 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
namespace boost { namespace geometry
{

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@ -54,7 +54,7 @@
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
@ -116,56 +116,24 @@ struct centroid_point
}
};
template
<
typename Indexed,
typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = dimension<Indexed>::type::value
>
struct centroid_indexed_calculator
{
typedef typename select_coordinate_type
<
Indexed, Point
>::type coordinate_type;
static inline void apply(Indexed const& indexed, Point& centroid)
{
coordinate_type const c1 = get<min_corner, Dimension>(indexed);
coordinate_type const c2 = get<max_corner, Dimension>(indexed);
coordinate_type m = c1 + c2;
coordinate_type const two = 2;
m /= two;
set<Dimension>(centroid, m);
centroid_indexed_calculator
<
Indexed, Point, Dimension + 1
>::apply(indexed, centroid);
}
};
template<typename Indexed, typename Point, std::size_t DimensionCount>
struct centroid_indexed_calculator<Indexed, Point, DimensionCount, DimensionCount>
{
static inline void apply(Indexed const& , Point& )
{
}
};
struct centroid_indexed
{
template<typename Indexed, typename Point, typename Strategy>
static inline void apply(Indexed const& indexed, Point& centroid,
Strategy const&)
{
centroid_indexed_calculator
typedef typename select_coordinate_type
<
Indexed, Point
>::apply(indexed, centroid);
>::type coordinate_type;
detail::for_each_dimension<Indexed>([&](auto dimension)
{
coordinate_type const c1 = get<min_corner, dimension>(indexed);
coordinate_type const c2 = get<max_corner, dimension>(indexed);
coordinate_type const two = 2;
set<dimension>(centroid, (c1 + c2) / two);
});
}
};

View File

@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -17,8 +21,12 @@
#include <cstddef>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
namespace boost { namespace geometry
@ -49,10 +57,13 @@ inline void assign_point_to_index(Point const& point, Geometry& geometry)
concepts::check<Point const>();
concepts::check<Geometry>();
detail::assign::assign_point_to_index
<
Geometry, Point, Index, 0, dimension<Geometry>::type::value
>::apply(point, geometry);
detail::for_each_dimension<Geometry>([&](auto dimension){
geometry::set<Index, dimension>(geometry,
boost::numeric_cast
<
typename coordinate_type<Geometry>::type
>(geometry::get<dimension>(point)));
});
}
@ -77,10 +88,13 @@ inline void assign_point_from_index(Geometry const& geometry, Point& point)
concepts::check<Geometry const>();
concepts::check<Point>();
detail::assign::assign_point_from_index
<
Geometry, Point, Index, 0, dimension<Geometry>::type::value
>::apply(geometry, point);
detail::for_each_dimension<Geometry>([&](auto dimension){
geometry::set<dimension>(point,
boost::numeric_cast
<
typename coordinate_type<Point>::type
>(geometry::get<Index, dimension>(geometry)));
});
}

View File

@ -7,8 +7,8 @@
// 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-2020.
// Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
// This file was modified by Oracle on 2018-2021.
// Modifications copyright (c) 2018-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -29,7 +29,6 @@
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/algorithms/append.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/core/access.hpp>
@ -39,8 +38,8 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
namespace boost { namespace geometry
@ -51,33 +50,18 @@ namespace detail { namespace assign
{
template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>
struct initialize
{
template <typename Box>
static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)
{
geometry::set<Index, Dimension>(box, value);
initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);
}
};
template <std::size_t Index, std::size_t DimensionCount>
struct initialize<Index, DimensionCount, DimensionCount>
{
template <typename Box>
static inline void apply(Box&, typename coordinate_type<Box>::type const&)
{}
};
struct assign_zero_point
{
template <typename Point>
static inline void apply(Point& point)
{
geometry::assign_value(point, 0);
typedef typename coordinate_type<Point>::type coordinate_type;
coordinate_type const zero = 0;
detail::for_each_dimension<Point>([&](auto dimension)
{
set<dimension>(point, zero);
});
}
};
@ -88,15 +72,15 @@ struct assign_inverse_box_or_segment
template <typename BoxOrSegment>
static inline void apply(BoxOrSegment& geometry)
{
typedef typename point_type<BoxOrSegment>::type point_type;
typedef typename coordinate_type<point_type>::type bound_type;
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, geometry::bounds<bound_type>::highest()
);
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, geometry::bounds<bound_type>::lowest()
);
coordinate_type const highest = geometry::bounds<coordinate_type>::highest();
coordinate_type const lowest = geometry::bounds<coordinate_type>::lowest();
detail::for_each_dimension<BoxOrSegment>([&](auto dimension)
{
set<0, dimension>(geometry, highest);
set<1, dimension>(geometry, lowest);
});
}
};
@ -109,12 +93,12 @@ struct assign_zero_box_or_segment
{
typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, coordinate_type()
);
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
geometry, coordinate_type()
);
coordinate_type const zero = 0;
detail::for_each_dimension<BoxOrSegment>([&](auto dimension)
{
set<0, dimension>(geometry, zero);
set<1, dimension>(geometry, zero);
});
}
};
@ -139,90 +123,6 @@ inline void assign_box_2d_corner(Box const& box, Point& point)
template
<
typename Geometry, typename Point,
std::size_t Index,
std::size_t Dimension, std::size_t DimensionCount
>
struct assign_point_to_index
{
static inline void apply(Point const& point, Geometry& geometry)
{
geometry::set<Index, Dimension>(geometry, boost::numeric_cast
<
typename coordinate_type<Geometry>::type
>(geometry::get<Dimension>(point)));
assign_point_to_index
<
Geometry, Point, Index, Dimension + 1, DimensionCount
>::apply(point, geometry);
}
};
template
<
typename Geometry, typename Point,
std::size_t Index,
std::size_t DimensionCount
>
struct assign_point_to_index
<
Geometry, Point,
Index,
DimensionCount, DimensionCount
>
{
static inline void apply(Point const& , Geometry& )
{
}
};
template
<
typename Geometry, typename Point,
std::size_t Index,
std::size_t Dimension, std::size_t DimensionCount
>
struct assign_point_from_index
{
static inline void apply(Geometry const& geometry, Point& point)
{
geometry::set<Dimension>( point, boost::numeric_cast
<
typename coordinate_type<Point>::type
>(geometry::get<Index, Dimension>(geometry)));
assign_point_from_index
<
Geometry, Point, Index, Dimension + 1, DimensionCount
>::apply(geometry, point);
}
};
template
<
typename Geometry, typename Point,
std::size_t Index,
std::size_t DimensionCount
>
struct assign_point_from_index
<
Geometry, Point,
Index,
DimensionCount, DimensionCount
>
{
static inline void apply(Geometry const&, Point&)
{
}
};
template <typename Geometry>
struct assign_2d_box_or_segment
{

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020 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
@ -25,8 +25,11 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/point_type.hpp>
@ -36,8 +39,6 @@
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/math.hpp>

View File

@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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.
@ -21,8 +25,8 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
@ -43,88 +47,6 @@ struct param
};
template <typename Value, template <typename> class Function>
struct value_operation
{
Value m_value;
inline value_operation(Value const &value)
: m_value(value)
{}
template <typename PointDst, std::size_t Index>
inline void apply(PointDst& point_dst) const
{
set<Index>(point_dst,
Function
<
typename geometry::select_most_precise
<
Value,
typename geometry::coordinate_type<PointDst>::type
>::type
>()(get<Index>(point_dst), m_value));
}
};
template <typename PointSrc, template <typename> class Function>
struct point_operation
{
PointSrc const& m_point_src;
inline point_operation(PointSrc const& point)
: m_point_src(point)
{}
template <typename PointDst, std::size_t Index>
inline void apply(PointDst& point_dst) const
{
set<Index>(point_dst,
Function
<
typename geometry::select_most_precise
<
typename geometry::coordinate_type<PointSrc>::type,
typename geometry::coordinate_type<PointDst>::type
>::type
>()(get<Index>(point_dst), get<Index>(m_point_src)));
}
};
template <typename Value>
struct value_assignment
{
Value m_value;
inline value_assignment(Value const &value)
: m_value(value)
{}
template <typename PointDst, std::size_t Index>
inline void apply(PointDst& point_dst) const
{
set<Index>(point_dst, m_value);
}
};
template <typename PointSrc>
struct point_assignment
{
PointSrc const& m_point_src;
inline point_assignment(PointSrc const& point)
: m_point_src(point)
{}
template <typename PointDst, std::size_t Index>
inline void apply(PointDst& point_dst) const
{
set<Index>(point_dst, get<Index>(m_point_src));
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
@ -141,12 +63,10 @@ inline void add_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
for_each_coordinate(p,
detail::value_operation
<
typename coordinate_type<Point>::type,
std::plus
>(value));
detail::for_each_dimension<Point>([&](auto index)
{
set<index>(p, get<index>(p) + value);
});
}
/*!
@ -165,7 +85,11 @@ inline void add_point(Point1& p1, Point2 const& p2)
BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2));
detail::for_each_dimension<Point1>([&](auto index)
{
using calc_t = typename select_coordinate_type<Point1, Point2>::type;
set<index>(p1, calc_t(get<index>(p1)) + calc_t(get<index>(p2)));
});
}
/*!
@ -181,12 +105,10 @@ inline void subtract_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
for_each_coordinate(p,
detail::value_operation
<
typename coordinate_type<Point>::type,
std::minus
>(value));
detail::for_each_dimension<Point>([&](auto index)
{
set<index>(p, get<index>(p) - value);
});
}
/*!
@ -205,7 +127,11 @@ inline void subtract_point(Point1& p1, Point2 const& p2)
BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2));
detail::for_each_dimension<Point1>([&](auto index)
{
using calc_t = typename select_coordinate_type<Point1, Point2>::type;
set<index>(p1, calc_t(get<index>(p1)) - calc_t(get<index>(p2)));
});
}
/*!
@ -221,12 +147,10 @@ inline void multiply_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
for_each_coordinate(p,
detail::value_operation
<
typename coordinate_type<Point>::type,
std::multiplies
>(value));
detail::for_each_dimension<Point>([&](auto index)
{
set<index>(p, get<index>(p) * value);
});
}
/*!
@ -246,7 +170,11 @@ inline void multiply_point(Point1& p1, Point2 const& p2)
BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2));
detail::for_each_dimension<Point1>([&](auto index)
{
using calc_t = typename select_coordinate_type<Point1, Point2>::type;
set<index>(p1, calc_t(get<index>(p1)) * calc_t(get<index>(p2)));
});
}
/*!
@ -262,12 +190,10 @@ inline void divide_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
for_each_coordinate(p,
detail::value_operation
<
typename coordinate_type<Point>::type,
std::divides
>(value));
detail::for_each_dimension<Point>([&](auto index)
{
set<index>(p, get<index>(p) / value);
});
}
/*!
@ -286,7 +212,11 @@ inline void divide_point(Point1& p1, Point2 const& p2)
BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2));
detail::for_each_dimension<Point1>([&](auto index)
{
using calc_t = typename select_coordinate_type<Point1, Point2>::type;
set<index>(p1, calc_t(get<index>(p1)) / calc_t(get<index>(p2)));
});
}
/*!
@ -302,11 +232,10 @@ inline void assign_value(Point& p, typename detail::param<Point>::type value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
for_each_coordinate(p,
detail::value_assignment
<
typename coordinate_type<Point>::type
>(value));
detail::for_each_dimension<Point>([&](auto index)
{
set<index>(p, value);
});
}
/*!
@ -325,7 +254,10 @@ inline void assign_point(Point1& p1, Point2 const& p2)
BOOST_CONCEPT_ASSERT( (concepts::Point<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
for_each_coordinate(p1, detail::point_assignment<Point2>(p2));
detail::for_each_dimension<Point1>([&](auto index)
{
set<index>(p1, get<index>(p2));
});
}

View File

@ -2,8 +2,8 @@
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2018-2021.
// Modifications copyright (c) 2018-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@ -88,7 +88,7 @@ struct transform_geometrically<Point, Vector, point_tag, vector_tag>
static inline void apply(Point & point, Vector const& vector, std::true_type /*is_cartesian*/)
{
for_each_coordinate(point, detail::point_operation<Vector, std::plus>(vector));
geometry::add_point(point, vector);
}
static inline void apply(Point & point, Vector const& vector, std::false_type /*is_cartesian*/)

View File

@ -2,8 +2,8 @@
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018 Oracle and/or its affiliates.
// This file was modified by Oracle on 2018-2021.
// Modifications copyright (c) 2018-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@ -17,7 +17,6 @@
#include <boost/geometry/extensions/algebra/geometries/concepts/vector_concept.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
//#include <boost/geometry/geometries/concepts/point_concept.hpp>
//#include <boost/geometry/util/for_each_coordinate.hpp>
namespace boost { namespace geometry
{
@ -31,8 +30,10 @@ inline void translation(Point1 const& p1, Point2 const& p2, Vector & v)
// TODO - replace the following by check_equal_dimensions
concepts::check_concepts_and_equal_dimensions<Point1 const, Vector>();
for_each_coordinate(v, detail::point_assignment<Point2>(p2));
for_each_coordinate(v, detail::point_operation<Point1, std::minus>(p1));
detail::for_each_dimension<Point1>([&](auto index)
{
set<index>(v, get<index>(p2) - get<index>(p1));
});
}
template <typename Vector, typename Point1, typename Point2>

View File

@ -1,6 +1,6 @@
// Boost.Geometry
// Copyright (c) 2016-2017, Oracle and/or its affiliates.
// Copyright (c) 2016-2021, 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,
@ -202,7 +202,9 @@ inline Point3d projected_to_surface(Point3d const& direction, Spheroid const& sp
}
template <typename Point3d, typename Spheroid>
inline bool projected_to_surface(Point3d const& origin, Point3d const& direction, Point3d & result1, Point3d & result2, Spheroid const& spheroid)
inline bool projected_to_surface(Point3d const& origin, Point3d const& direction,
Point3d & result1, Point3d & result2,
Spheroid const& spheroid)
{
typedef typename coordinate_type<Point3d>::type coord_t;
@ -247,14 +249,12 @@ inline bool projected_to_surface(Point3d const& origin, Point3d const& direction
coord_t const two_a = c2 * param_a;
coord_t const t1 = (-param_b + sqrt_delta) / two_a;
result1 = direction;
multiply_value(result1, t1);
add_point(result1, origin);
coord_t const t2 = (-param_b - sqrt_delta) / two_a;
result2 = direction;
multiply_value(result2, t2);
add_point(result2, origin);
geometry::detail::for_each_dimension<Point3d>([&](auto index)
{
set<index>(result1, get<index>(origin) + get<index>(direction) * t1);
set<index>(result2, get<index>(origin) + get<index>(direction) * t2);
});
return true;
}
@ -360,12 +360,11 @@ inline bool planes_spheroid_intersection(Point3d const& o1, Point3d const& n1,
coord_t C2 = (h2 - h1 * dot_n1_n2) / denom;
// C1 * n1 + C2 * n2
Point3d C1_n1 = n1;
multiply_value(C1_n1, C1);
Point3d C2_n2 = n2;
multiply_value(C2_n2, C2);
Point3d io = C1_n1;
add_point(io, C2_n2);
Point3d io;
geometry::detail::for_each_dimension<Point3d>([&](auto index)
{
set<index>(io, C1 * get<index>(n1) + C2 * get<index>(n2));
});
if (! projected_to_surface(io, id, ip1, ip2, spheroid))
{
@ -388,16 +387,16 @@ inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
Point3d xy2 = projected_to_xy(p2, spheroid);
// origin = (xy1 + xy2) / 2
origin = xy1;
add_point(origin, xy2);
multiply_value(origin, coord_t(0.5));
// v1 = p1 - origin
v1 = p1;
subtract_point(v1, origin);
// v2 = p2 - origin
v2 = p2;
subtract_point(v2, origin);
coord_t const half = coord_t(0.5);
geometry::detail::for_each_dimension<Point3d>([&](auto index)
{
coord_t const o = (get<index>(xy1) + get<index>(xy2)) * half;
set<index>(origin, o);
set<index>(v1, get<index>(p1) - o);
set<index>(v2, get<index>(p1) - o);
});
normal = cross_product(v1, v2);
}

View File

@ -3,8 +3,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -24,7 +24,7 @@
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/util/for_each_coordinate.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/centroid.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
@ -80,7 +80,7 @@ public :
typedef detail::weighted_length_sums
<
distance_type,
geometry::dimension<Point>::type::value
geometry::dimension<Point>::value
> state_type;
static inline void apply(PointOfSegment const& p1,
@ -89,12 +89,14 @@ public :
distance_type const d = geometry::distance(p1, p2);
state.length += d;
typename state_type::work_point weighted_median;
geometry::assign_zero(weighted_median);
geometry::add_point(weighted_median, p1);
geometry::add_point(weighted_median, p2);
geometry::multiply_value(weighted_median, d/2);
geometry::add_point(state.average_sum, weighted_median);
distance_type const d_half = d / distance_type(2);
geometry::detail::for_each_dimension<Point>([&](auto dimension)
{
distance_type const coord1 = get<dimension>(p1);
distance_type const coord2 = get<dimension>(p2);
distance_type const wm = (coord1 + coord2) * d_half; // weighted median
set<dimension>(state.average_sum, get<dimension>(state.average_sum) + wm);
});
}
static inline bool result(state_type const& state, Point& centroid)
@ -106,31 +108,21 @@ public :
// NOTE: above distance_type is checked, not the centroid coordinate_type
// which means that the centroid can still be filled with INF
// if e.g. distance_type is double and centroid contains floats
geometry::for_each_coordinate(centroid, set_sum_div_length(state));
geometry::detail::for_each_dimension<Point>([&](auto dimension)
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
geometry::set<dimension>(
centroid,
boost::numeric_cast<coordinate_type>(
geometry::get<dimension>(state.average_sum) / state.length
)
);
});
return true;
}
return false;
}
struct set_sum_div_length
{
state_type const& m_state;
set_sum_div_length(state_type const& state)
: m_state(state)
{}
template <typename Pt, std::size_t Dimension>
void apply(Pt & centroid) const
{
typedef typename geometry::coordinate_type<Pt>::type coordinate_type;
geometry::set<Dimension>(
centroid,
boost::numeric_cast<coordinate_type>(
geometry::get<Dimension>(m_state.average_sum) / m_state.length
)
);
}
};
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS

View File

@ -1,6 +1,6 @@
// Boost.Geometry
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
// Copyright (c) 2017-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -20,6 +20,7 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
@ -52,60 +53,53 @@ public:
static inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold)
{
typedef typename AssignPolicy::point_type out_point_t;
typedef typename coordinate_type<out_point_t>::type out_coord_t;
typedef typename select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<out_point_t>::type,
typename coordinate_type<Point>::type, out_coord_t,
CalculationType
>::type calc_t;
typedef model::point<calc_t, geometry::dimension<Point>::value, cs::cartesian> calc_point_t;
calc_point_t cp0, cp1;
geometry::detail::conversion::convert_point_to_point(p0, cp0);
geometry::detail::conversion::convert_point_to_point(p1, cp1);
assert_dimension_equal<calc_point_t, out_point_t>();
calc_point_t cp0, dir01;
// dir01 = p1 - p0
geometry::detail::for_each_dimension<calc_point_t>([&](auto index)
{
calc_t const coord0 = boost::numeric_cast<calc_t>(get<index>(p0));
calc_t const coord1 = boost::numeric_cast<calc_t>(get<index>(p1));
set<index>(cp0, coord0);
set<index>(dir01, coord1 - coord0);
});
// dir01 = xy1 - xy0
calc_point_t dir01 = cp1;
geometry::subtract_point(dir01, cp0);
calc_t const dot01 = geometry::dot_product(dir01, dir01);
calc_t const len = math::sqrt(dot01);
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
signed_size_type n = signed_size_type(len / length_threshold);
signed_size_type const n = signed_size_type(len / length_threshold);
if (n <= 0)
{
return;
}
// NOTE: Normalization will not work for integral coordinates
// normalize
//geometry::divide_value(dir01, len);
calc_t step = len / (n + 1);
calc_t d = step;
for (signed_size_type i = 0 ; i < n ; ++i, d += step)
calc_t const den = calc_t(n + 1);
for (signed_size_type i = 0 ; i < n ; ++i)
{
// pd = xy0 + d * dir01
calc_point_t pd = dir01;
// without normalization
geometry::multiply_value(pd, calc_t(i + 1));
geometry::divide_value(pd, calc_t(n + 1));
// with normalization
//geometry::multiply_value(pd, d);
out_point_t out;
geometry::add_point(pd, cp0);
calc_t const num = calc_t(i + 1);
geometry::detail::for_each_dimension<out_point_t>([&](auto index)
{
// out = p0 + d * dir01
calc_t const coord = get<index>(cp0) + get<index>(dir01) * num / den;
// NOTE: Only needed if types calc_point_t and out_point_t are different
// otherwise pd could simply be passed into policy
out_point_t p;
assert_dimension_equal<calc_point_t, out_point_t>();
geometry::detail::conversion::convert_point_to_point(pd, p);
policy.apply(p);
set<index>(out, boost::numeric_cast<out_coord_t>(coord));
});
policy.apply(out);
}
}
};

View File

@ -1,8 +1,9 @@
// Boost.Geometry
// Copyright (c) 2018, Oracle and/or its affiliates.
// Copyright (c) 2018-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@ -15,6 +16,7 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/line_interpolate.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
@ -67,41 +69,22 @@ public:
{
typedef typename select_calculation_type_alt
<
CalculationType,
Point
CalculationType, Point
>::type calc_t;
typedef model::point
<
calc_t,
geometry::dimension<Point>::value,
cs::cartesian
> calc_point_t;
calc_point_t cp0, cp1;
geometry::detail::conversion::convert_point_to_point(p0, cp0);
geometry::detail::conversion::convert_point_to_point(p1, cp1);
typedef typename coordinate_type<Point>::type coord_t;
//segment convex combination: p0*fraction + p1*(1-fraction)
Fraction const one_minus_fraction = 1-fraction;
for_each_coordinate(cp1, detail::value_operation
<
Fraction,
std::multiplies
>(fraction));
for_each_coordinate(cp0, detail::value_operation
<
Fraction,
std::multiplies
>(one_minus_fraction));
for_each_coordinate(cp1, detail::point_operation
<
calc_point_t,
std::plus
>(cp0));
assert_dimension_equal<calc_point_t, Point>();
geometry::detail::conversion::convert_point_to_point(cp1, p);
geometry::detail::for_each_dimension<Point>([&](auto dimension)
{
// NOTE: numeric_cast is a leftover from convert, it could probably be ommited.
// NOTE: the order of points is different than in the formula above
// this is also a leftover from the previous implementation
calc_t coord0 = boost::numeric_cast<calc_t>(get<dimension>(p0));
calc_t coord1 = boost::numeric_cast<calc_t>(get<dimension>(p1));
calc_t result = calc_t(coord1 * fraction) + calc_t(coord0 * one_minus_fraction);
set<dimension>(p, boost::numeric_cast<coord_t>(result));
});
}
};

View File

@ -2,7 +2,7 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2016-2020, Oracle and/or its affiliates.
// Copyright (c) 2016-2021, 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,
@ -953,10 +953,12 @@ struct spherical_segments_calc_policy
// not checked before this function is called the length
// should be checked here (math::equals(len, c0))
coord_t const len = math::sqrt(dot_product(ip1, ip1));
divide_value(ip1, len); // normalize i1
ip2 = ip1;
multiply_value(ip2, coord_t(-1));
geometry::detail::for_each_dimension<Point3d>([&](auto index)
{
coord_t const coord = get<index>(ip1) / len; // normalize
set<index>(ip1, coord);
set<index>(ip2, -coord);
});
return true;
}

View File

@ -0,0 +1,409 @@
// 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_UTIL_FOR_EACH_DIMENSION_HPP
#define BOOST_GEOMETRY_UTIL_FOR_EACH_DIMENSION_HPP
#include <boost/config.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// NOTE: Out of curiosity I tested the compilation times of various implementations.
// Compilation times were tested for point and dimension 1000 with g++-6.3.0 and msvc-14.1.
// Each coordinate of a point was set to the dimension value.
// In general we deal with small dimensions so the simplest O(N) should be the fastest
// one anyway.
// It seems that simple O(N) version is faster to compile than O(logN) version based on
// intervals even for a big value such as 1000. Which is wierd and may indicate that I
// missed something.
// The simple version generates deeper recursion but this is not a problem since in general we
// deal with small number of dimensions.
// A third version I tested using C++17 fold expression was faster in some cases.
// It depended on optimization level.
// This utility was also slightly faster than for_each_coordinate so I assume the compilation
// time is at least similar which makes it a viable replacement.
// O(N) version
template <std::size_t I, std::size_t N>
struct for_each_index_impl
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<I>());
for_each_index_impl<I + 1, N>::apply(predicate);
}
};
template <std::size_t N>
struct for_each_index_impl<N, N>
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& )
{}
};
template <>
struct for_each_index_impl<0, 1>
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<0>());
}
};
template <>
struct for_each_index_impl<0, 2>
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<0>());
predicate(util::index_constant<1>());
}
};
template <>
struct for_each_index_impl<0, 3>
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<0>());
predicate(util::index_constant<1>());
predicate(util::index_constant<2>());
}
};
// for_each_index_impl<0, N>
// for_each_index_impl<0, 0>
// O(logN) version 1
template <std::size_t F, std::size_t S, std::size_t L>
struct for_each_index_impl1
{
static const std::size_t M = F + (L - F) / 2;
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
for_each_index_impl1<F, F+1, M>::apply(predicate);
for_each_index_impl1<M, M+1, L>::apply(predicate);
}
};
template <std::size_t F, std::size_t S>
struct for_each_index_impl1<F, S, S>
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<F>());
}
};
template <std::size_t F, std::size_t S>
struct for_each_index_impl1<F, S, F>
{
template <typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& )
{}
};
// O(logN) version 2
template <std::size_t N>
struct for_each_index_impl2
{
static const std::size_t N1 = N / 2;
static const std::size_t N2 = N - N1;
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
for_each_index_impl2<N1>::template apply<Offset>(predicate);
for_each_index_impl2<N2>::template apply<Offset + N1>(predicate);
}
};
template <>
struct for_each_index_impl2<3>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<Offset>());
predicate(util::index_constant<Offset + 1>());
predicate(util::index_constant<Offset + 2>());
}
};
template <>
struct for_each_index_impl2<2>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<Offset>());
predicate(util::index_constant<Offset + 1>());
}
};
template <>
struct for_each_index_impl2<1>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& predicate)
{
predicate(util::index_constant<Offset>());
}
};
template <>
struct for_each_index_impl2<0>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline void apply(UnaryPredicate& )
{}
};
// C++17 fold expression
#ifndef BOOST_NO_CXX17_FOLD_EXPRESSIONS
template <typename UnaryPredicate, std::size_t ...Is>
constexpr inline UnaryPredicate for_each_dimension_impl(UnaryPredicate& predicate,
std::index_sequence<Is...>)
{
(predicate(util::index_constant<Is>()), ...);
return predicate;
}
#endif
// Interface
template <std::size_t N, typename UnaryPredicate>
constexpr inline UnaryPredicate for_each_index(UnaryPredicate predicate)
{
for_each_index_impl
<
0, N
>::apply(predicate);
return predicate;
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline UnaryPredicate for_each_dimension(UnaryPredicate predicate)
{
//#ifndef BOOST_NO_CXX17_FOLD_EXPRESSIONS
// for_each_dimension_impl(predicate,
// std::make_index_sequence<geometry::dimension<Geometry>::value>());
//#else
for_each_index_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
//#endif
return predicate;
}
// ----------------------------------------------------------------------------
// O(logN) version 2
template <std::size_t N>
struct all_indexes_of_impl2
{
static const std::size_t N1 = N / 2;
static const std::size_t N2 = N - N1;
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return all_indexes_of_impl2<N1>::template apply<Offset>(predicate)
&& all_indexes_of_impl2<N2>::template apply<Offset + N1>(predicate);
}
};
template <>
struct all_indexes_of_impl2<3>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
&& predicate(util::index_constant<Offset + 1>())
&& predicate(util::index_constant<Offset + 2>());
}
};
template <>
struct all_indexes_of_impl2<2>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
&& predicate(util::index_constant<Offset + 1>());
}
};
template <>
struct all_indexes_of_impl2<1>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>());
}
};
template <>
struct all_indexes_of_impl2<0>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& )
{
return true;
}
};
// Interface
template <std::size_t N, typename UnaryPredicate>
constexpr inline bool all_indexes_of(UnaryPredicate predicate)
{
return all_indexes_of_impl2<N>::template apply<0>(predicate);
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline bool all_dimensions_of(UnaryPredicate predicate)
{
return all_indexes_of_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
}
// ----------------------------------------------------------------------------
// O(logN) version 2
template <std::size_t N>
struct any_index_of_impl2
{
static const std::size_t N1 = N / 2;
static const std::size_t N2 = N - N1;
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return any_index_of_impl2<N1>::template apply<Offset>(predicate)
|| any_index_of_impl2<N2>::template apply<Offset + N1>(predicate);
}
};
template <>
struct any_index_of_impl2<3>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
|| predicate(util::index_constant<Offset + 1>())
|| predicate(util::index_constant<Offset + 2>());
}
};
template <>
struct any_index_of_impl2<2>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
|| predicate(util::index_constant<Offset + 1>());
}
};
template <>
struct any_index_of_impl2<1>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>());
}
};
template <>
struct any_index_of_impl2<0>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& )
{
return false;
}
};
// Interface
template <std::size_t N, typename UnaryPredicate>
constexpr inline bool any_index_of(UnaryPredicate predicate)
{
return any_index_of_impl2<N>::template apply<0>(predicate);
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline bool any_dimension_of(UnaryPredicate predicate)
{
return any_index_of_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
}
template <std::size_t N, typename UnaryPredicate>
constexpr inline bool none_index_of(UnaryPredicate predicate)
{
return ! any_index_of_impl2<N>::template apply<0>(predicate);
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline bool none_dimension_of(UnaryPredicate predicate)
{
return ! any_index_of_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
}
// ----------------------------------------------------------------------------
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_DIMENSION_HPP

View File

@ -4,8 +4,8 @@
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
#
# This file was modified by Oracle on 2014, 2015, 2019.
# Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
# This file was modified by Oracle on 2014-2021.
# Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
#
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -18,6 +18,7 @@ test-suite boost-geometry-util
:
[ run calculation_type.cpp : : : : util_calculation_type ]
[ run for_each_coordinate.cpp : : : : util_for_each_coordinate ]
[ run for_each_coordinate.cpp : : : : util_for_each_dimension ]
[ run math_abs.cpp : : : : util_math_abs ]
[ run math_equals.cpp : : : : util_math_equals ]
[ run math_sqrt.cpp : : : : util_math_sqrt ]

View File

@ -0,0 +1,105 @@
// 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
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/util/for_each_dimension.hpp>
void test_dimension(bg::util::index_constant<0> index)
{
bool called = false;
bg::detail::for_each_index<0>([&](auto index) { called = true; });
BOOST_CHECK(!called);
BOOST_CHECK(bg::detail::all_indexes_of<0>([&](auto index) { return true; }) == true);
BOOST_CHECK(bg::detail::all_indexes_of<0>([&](auto index) { return false; }) == true);
BOOST_CHECK(bg::detail::any_index_of<0>([&](auto index) { return true; }) == false);
BOOST_CHECK(bg::detail::any_index_of<0>([&](auto index) { return false; }) == false);
BOOST_CHECK(bg::detail::none_index_of<0>([&](auto index) { return true; }) == true);
BOOST_CHECK(bg::detail::none_index_of<0>([&](auto index) { return false; }) == true);
}
template <std::size_t I>
void test_dimension(bg::util::index_constant<I>)
{
using point = bg::model::point<double, I, bg::cs::cartesian>;
point p;
bg::assign_value(p, 10.0);
bg::detail::for_each_index<I>([&](auto index)
{
BOOST_CHECK(bg::get<index>(p) == 10.0);
bg::set<index>(p, double(index));
});
bg::detail::for_each_dimension<point>([&](auto index)
{
BOOST_CHECK(bg::get<index>(p) == double(index));
});
BOOST_CHECK(
bg::detail::all_indexes_of<0>([&](auto index)
{
return bg::get<index>(p) == double(index);
}) == true);
BOOST_CHECK(
bg::detail::all_dimensions_of<point>([&](auto index)
{
return bg::get<index>(p) == 10;
}) == false);
BOOST_CHECK(
bg::detail::any_index_of<0>([&](auto index)
{
return false;
}) == false);
BOOST_CHECK(
bg::detail::any_dimension_of<point>([&](auto index)
{
return bg::get<index>(p) == double(I - 1);
}) == true);
BOOST_CHECK(
bg::detail::none_index_of<0>([&](auto index)
{
return false;
}) == true);
BOOST_CHECK(
bg::detail::none_dimension_of<point>([&](auto index)
{
return bg::get<index>(p) == double(0);
}) == false);
}
template <std::size_t I, std::size_t N>
struct test_dimensions
{
static void apply()
{
test_dimension(bg::util::index_constant<I>());
test_dimensions<I + 1, N>::apply();
}
};
template <std::size_t N>
struct test_dimensions<N, N>
{
static void apply() {}
};
int test_main(int, char* [])
{
test_dimensions<0, 5>::apply();
return 0;
}