mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
[util] Add for_each_dimension and use it in several places.
This commit is contained in:
parent
8b6929193d
commit
d2c79d97a9
@ -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
|
||||
{
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -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*/)
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
409
include/boost/geometry/util/for_each_dimension.hpp
Normal file
409
include/boost/geometry/util/for_each_dimension.hpp
Normal 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
|
@ -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 ]
|
||||
|
105
test/util/for_each_dimension.cpp
Normal file
105
test/util/for_each_dimension.cpp
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user