feat():initial version

This commit is contained in:
2026-06-09 20:16:47 +08:00
commit 85fbb3188c
14809 changed files with 3044607 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
#define BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED("<boost/geometry/util/type_traits.hpp>")
#include <boost/geometry/util/type_traits.hpp>
#endif // BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP

View File

@@ -0,0 +1,25 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2012 Bruno Lalande, Paris, France.
// Copyright (c) 2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED("<boost/geometry/util/type_traits.hpp>")
#include <boost/geometry/util/type_traits.hpp>
#endif // BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP

View File

@@ -0,0 +1,176 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2012 Bruno Lalande, Paris, France.
// Copyright (c) 2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
#include <boost/static_assert.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace util
{
namespace detail
{
struct default_integral
{
typedef long long type;
};
/*!
\details Selects the most appropriate:
- if calculation type is specified (not void), that one is used
- else if type is non-fundamental (user defined e.g. Boost.Multiprecision), that one
- else if type is floating point, the specified default FP is used
- else it is integral and the specified default integral is used
*/
template
<
typename Type,
typename CalculationType,
typename DefaultFloatingPointCalculationType,
typename DefaultIntegralCalculationType
>
struct calculation_type
{
BOOST_STATIC_ASSERT((
std::is_fundamental
<
DefaultFloatingPointCalculationType
>::value
));
BOOST_STATIC_ASSERT((
std::is_fundamental
<
DefaultIntegralCalculationType
>::value
));
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
std::conditional_t
<
std::is_floating_point<Type>::value,
typename select_most_precise
<
DefaultFloatingPointCalculationType,
Type
>::type,
typename select_most_precise
<
DefaultIntegralCalculationType,
Type
>::type
>,
CalculationType
> type;
};
} // namespace detail
namespace calculation_type
{
namespace geometric
{
template
<
typename Geometry,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct unary
{
typedef typename detail::calculation_type
<
typename geometry::coordinate_type<Geometry>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
template
<
typename Geometry1,
typename Geometry2,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct binary
{
typedef typename detail::calculation_type
<
typename select_coordinate_type<Geometry1, Geometry2>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
/*!
\brief calculation type (ternary, for three geometry types)
*/
template
<
typename Geometry1,
typename Geometry2,
typename Geometry3,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct ternary
{
typedef typename detail::calculation_type
<
typename select_most_precise
<
typename coordinate_type<Geometry1>::type,
typename select_coordinate_type
<
Geometry2,
Geometry3
>::type
>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
}} // namespace calculation_type::geometric
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP

View File

@@ -0,0 +1,46 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
#define BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
#include <boost/geometry/core/closure.hpp>
namespace boost { namespace geometry
{
template<closure_selector Closure>
struct closure_as_bool
{};
template<>
struct closure_as_bool<closed>
{
static const bool value = true;
};
template<>
struct closure_as_bool<open>
{
static const bool value = false;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP

View File

@@ -0,0 +1,98 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP
#define BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE("This header is deprecated.")
#endif
#include <boost/mpl/bind.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/set.hpp>
namespace boost { namespace geometry
{
namespace util
{
/*!
\brief Meta-function to generate all the combination of pairs of types
from a given sequence Sequence except those that does not satisfy the
predicate Pred
\ingroup utility
\par Example
\code
typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<1> > types;
typedef combine_if<types, types, always<true_> >::type combinations;
typedef boost::mpl::vector<
pair<boost::mpl::int_<1>, boost::mpl::int_<1> >,
pair<boost::mpl::int_<1>, boost::mpl::int_<0> >,
pair<boost::mpl::int_<0>, boost::mpl::int_<1> >,
pair<boost::mpl::int_<0>, boost::mpl::int_<0> >
> result_types;
BOOST_MPL_ASSERT(( boost::mpl::equal<combinations, result_types> ));
\endcode
*/
template <typename Sequence1, typename Sequence2, typename Pred>
struct combine_if
{
struct combine
{
template <typename Result, typename T>
struct apply
{
typedef typename boost::mpl::fold<Sequence2, Result,
boost::mpl::if_
<
boost::mpl::bind
<
typename boost::mpl::lambda<Pred>::type,
T,
boost::mpl::_2
>,
boost::mpl::insert
<
boost::mpl::_1, boost::mpl::pair<T, boost::mpl::_2>
>,
boost::mpl::_1
>
>::type type;
};
};
typedef typename boost::mpl::fold
<
Sequence1, boost::mpl::set0<>, combine
>::type type;
};
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP

View File

@@ -0,0 +1,111 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP
#define BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE("This header is deprecated.")
#endif
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/set.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/variant/variant_fwd.hpp>
namespace boost { namespace geometry
{
namespace detail
{
template <typename Variant>
struct unique_types:
boost::mpl::fold<
typename boost::mpl::reverse_fold<
typename Variant::types,
boost::mpl::set<>,
boost::mpl::insert<
boost::mpl::placeholders::_1,
boost::mpl::placeholders::_2
>
>::type,
boost::mpl::vector<>,
boost::mpl::push_back
<
boost::mpl::placeholders::_1, boost::mpl::placeholders::_2
>
>
{};
template <typename Types>
struct variant_or_single:
boost::mpl::if_<
boost::mpl::equal_to<
boost::mpl::size<Types>,
boost::mpl::int_<1>
>,
typename boost::mpl::front<Types>::type,
typename make_variant_over<Types>::type
>
{};
} // namespace detail
/*!
\brief Meta-function that takes a boost::variant type and tries to minimize
it by doing the following:
- if there's any duplicate types, remove them
- if the result is a variant of one type, turn it into just that type
\ingroup utility
\par Example
\code
typedef variant<int, float, int, long> variant_type;
typedef compress_variant<variant_type>::type compressed;
typedef boost::mpl::vector<int, float, long> result_types;
BOOST_MPL_ASSERT(( boost::mpl::equal<compressed::types, result_types> ));
typedef variant<int, int, int> one_type_variant_type;
typedef compress_variant<one_type_variant_type>::type single_type;
BOOST_MPL_ASSERT(( boost::equals<single_type, int> ));
\endcode
*/
template <typename Variant>
struct compress_variant:
detail::variant_or_single<
typename detail::unique_types<Variant>::type
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP

View File

@@ -0,0 +1,44 @@
// Boost.Geometry
// Copyright (c) 2015 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CONDITION_HPP
#define BOOST_GEOMETRY_UTIL_CONDITION_HPP
#include <boost/config.hpp>
// The macro defined in this file allows to suppress the MSVC
// compiler warning C4127: conditional expression is constant
#ifdef BOOST_MSVC
// NOTE: The code commented out below contains an alternative implementation
// of a macro using a free function. It was left here in case if in the future
// version of MSVC for the code currently used in the macro implementation
// the warning was generated.
//#ifndef DOXYGEN_NO_DETAIL
//namespace boost { namespace geometry { namespace detail {
//BOOST_FORCEINLINE bool condition(bool const b) { return b; }
//}}} // boost::geometry::detail
//#endif // DOXYGEN_NO_DETAIL
//#define BOOST_GEOMETRY_CONDITION(CONDITION) boost::geometry::detail::condition(CONDITION)
#define BOOST_GEOMETRY_CONDITION(CONDITION) ((void)0, (CONDITION))
#else
#define BOOST_GEOMETRY_CONDITION(CONDITION) (CONDITION)
#endif
#endif // BOOST_GEOMETRY_UTIL_CONDITION_HPP

View File

@@ -0,0 +1,54 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
#define BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
#include <cstdlib>
#include <string>
#include <boost/lexical_cast.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/*!
\brief cast coordinates from a string to a coordinate type
\detail By default it uses lexical_cast. However, lexical_cast seems not to support
See also "define_pi" where the same issue is solved
*/
template <typename CoordinateType>
struct coordinate_cast
{
static inline CoordinateType apply(std::string const& source)
{
#if defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
return atof(source.c_str());
#else
return boost::lexical_cast<CoordinateType>(source);
#endif
}
};
} // namespace detail
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP

View File

@@ -0,0 +1,82 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
#include <boost/concept/requires.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Point,
int Dimension = 0,
int DimensionCount = dimension<Point>::value
>
struct coordinates_scanner
{
template <typename Op>
static inline Op apply(Point& point, Op operation)
{
operation.template apply<Point, Dimension>(point);
return coordinates_scanner
<
Point,
Dimension + 1
>::apply(point, operation);
}
};
template <typename Point, int DimensionCount>
struct coordinates_scanner<Point, DimensionCount, DimensionCount>
{
template <typename Op>
static inline Op apply(Point& , Op operation)
{
return operation;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point, typename Op>
inline void for_each_coordinate(Point& point, Op operation)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
detail::coordinates_scanner<Point>::apply(point, operation);
}
template <typename Point, typename Op>
inline Op for_each_coordinate(Point const& point, Op operation)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point>) );
return detail::coordinates_scanner<Point const>::apply(point, operation);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP

View File

@@ -0,0 +1,56 @@
// Boost.Geometry
// Copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP
#include <type_traits>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct isinf
{
template <typename T>
static inline bool apply(T const& t)
{
return boost::math::isinf(t);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point>
bool has_infinite_coordinate(Point const& point)
{
return detail::has_coordinate_with_property
<
Point,
detail::isinf,
std::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>::apply(point);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP

View File

@@ -0,0 +1,98 @@
// Boost.Geometry
// Copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP
#include <cstddef>
#include <type_traits>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct isnan
{
template <typename T>
static inline bool apply(T const& t)
{
return boost::math::isnan(t);
}
};
template
<
typename Point,
typename Predicate,
bool Enable,
std::size_t I = 0,
std::size_t N = geometry::dimension<Point>::value
>
struct has_coordinate_with_property
{
static bool apply(Point const& point)
{
return Predicate::apply(geometry::get<I>(point))
|| has_coordinate_with_property
<
Point, Predicate, Enable, I+1, N
>::apply(point);
}
};
template <typename Point, typename Predicate, std::size_t I, std::size_t N>
struct has_coordinate_with_property<Point, Predicate, false, I, N>
{
static inline bool apply(Point const&)
{
return false;
}
};
template <typename Point, typename Predicate, std::size_t N>
struct has_coordinate_with_property<Point, Predicate, true, N, N>
{
static bool apply(Point const& )
{
return false;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point>
bool has_nan_coordinate(Point const& point)
{
return detail::has_coordinate_with_property
<
Point,
detail::isnan,
std::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>::apply(point);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP

View File

@@ -0,0 +1,56 @@
// Boost.Geometry
// Copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP
#include <type_traits>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct is_not_finite
{
template <typename T>
static inline bool apply(T const& t)
{
return ! boost::math::isfinite(t);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point>
bool has_non_finite_coordinate(Point const& point)
{
return detail::has_coordinate_with_property
<
Point,
detail::is_not_finite,
std::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>::apply(point);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP

View File

@@ -0,0 +1,48 @@
// Boost.Geometry
// Copyright (c) 2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP
#define BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
template<class CT>
struct bounds
{
static CT lowest () { return boost::numeric::bounds<CT>::lowest(); }
static CT highest () { return boost::numeric::bounds<CT>::highest(); }
};
template <typename Box>
bool is_inverse_spheroidal_coordinates(Box const& box)
{
typedef typename point_type<Box>::type point_type;
typedef typename coordinate_type<point_type>::type bound_type;
bound_type high = bounds<bound_type>::highest();
bound_type low = bounds<bound_type>::lowest();
return (geometry::get<0, 0>(box) == high) &&
(geometry::get<0, 1>(box) == high) &&
(geometry::get<1, 0>(box) == low) &&
(geometry::get<1, 1>(box) == low);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP

View File

@@ -0,0 +1,925 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
#define BOOST_GEOMETRY_UTIL_MATH_HPP
#include <cmath>
#include <limits>
#include <type_traits>
#include <boost/core/ignore_unused.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
//#include <boost/math/special_functions/round.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace math
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename T>
inline T const& greatest(T const& v1, T const& v2)
{
return (std::max)(v1, v2);
}
template <typename T>
inline T const& greatest(T const& v1, T const& v2, T const& v3)
{
return (std::max)(greatest(v1, v2), v3);
}
template <typename T>
inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
{
return (std::max)(greatest(v1, v2, v3), v4);
}
template <typename T>
inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
{
return (std::max)(greatest(v1, v2, v3, v4), v5);
}
template <typename T>
inline T bounded(T const& v, T const& lower, T const& upper)
{
return (std::min)((std::max)(v, lower), upper);
}
template <typename T>
inline T bounded(T const& v, T const& lower)
{
return (std::max)(v, lower);
}
template <typename T,
bool IsFloatingPoint = std::is_floating_point<T>::value>
struct abs
{
static inline T apply(T const& value)
{
T const zero = T();
return value < zero ? -value : value;
}
};
template <typename T>
struct abs<T, true>
{
static inline T apply(T const& value)
{
using ::fabs;
using std::fabs; // for long double
return fabs(value);
}
};
struct equals_default_policy
{
template <typename T>
static inline T apply(T const& a, T const& b)
{
// See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
}
};
template <typename T,
bool IsFloatingPoint = std::is_floating_point<T>::value>
struct equals_factor_policy
{
equals_factor_policy()
: factor(1) {}
explicit equals_factor_policy(T const& v)
: factor(greatest(abs<T>::apply(v), T(1)))
{}
equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
: factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
abs<T>::apply(v2), abs<T>::apply(v3),
T(1)))
{}
T const& apply(T const&, T const&) const
{
return factor;
}
T factor;
};
template <typename T>
struct equals_factor_policy<T, false>
{
equals_factor_policy() {}
explicit equals_factor_policy(T const&) {}
equals_factor_policy(T const& , T const& , T const& , T const& ) {}
static inline T apply(T const&, T const&)
{
return T(1);
}
};
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct equals
{
template <typename Policy>
static inline bool apply(Type const& a, Type const& b, Policy const&)
{
return a == b;
}
};
template <typename Type>
struct equals<Type, true>
{
template <typename Policy>
static inline bool apply(Type const& a, Type const& b, Policy const& policy)
{
boost::ignore_unused(policy);
if (a == b)
{
return true;
}
if (boost::math::isfinite(a) && boost::math::isfinite(b))
{
// If a is INF and b is e.g. 0, the expression below returns true
// but the values are obviously not equal, hence the condition
return abs<Type>::apply(a - b)
<= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
}
else
{
return a == b;
}
}
};
template <typename T1, typename T2, typename Policy>
inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
{
return detail::equals
<
typename select_most_precise<T1, T2>::type
>::apply(a, b, policy);
}
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct smaller
{
static inline bool apply(Type const& a, Type const& b)
{
return a < b;
}
};
template <typename Type>
struct smaller<Type, true>
{
static inline bool apply(Type const& a, Type const& b)
{
if (!(a < b)) // a >= b
{
return false;
}
return ! equals<Type, true>::apply(b, a, equals_default_policy());
}
};
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct smaller_or_equals
{
static inline bool apply(Type const& a, Type const& b)
{
return a <= b;
}
};
template <typename Type>
struct smaller_or_equals<Type, true>
{
static inline bool apply(Type const& a, Type const& b)
{
if (a <= b)
{
return true;
}
return equals<Type, true>::apply(a, b, equals_default_policy());
}
};
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct equals_with_epsilon
: public equals<Type, IsFloatingPoint>
{};
template
<
typename T,
bool IsFundemantal = std::is_fundamental<T>::value /* false */
>
struct square_root
{
typedef T return_type;
static inline T apply(T const& value)
{
// for non-fundamental number types assume that sqrt is
// defined either:
// 1) at T's scope, or
// 2) at global scope, or
// 3) in namespace std
using ::sqrt;
using std::sqrt;
return sqrt(value);
}
};
template <typename FundamentalFP>
struct square_root_for_fundamental_fp
{
typedef FundamentalFP return_type;
static inline FundamentalFP apply(FundamentalFP const& value)
{
#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
// This is a workaround for some 32-bit platforms.
// For some of those platforms it has been reported that
// std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
// For those platforms we need to define the macro
// BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
// to std::sqrt is checked appropriately before passed to std::sqrt
if (boost::math::isfinite(value))
{
return std::sqrt(value);
}
else if (boost::math::isinf(value) && value < 0)
{
return -std::numeric_limits<FundamentalFP>::quiet_NaN();
}
return value;
#else
// for fundamental floating point numbers use std::sqrt
return std::sqrt(value);
#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
}
};
template <>
struct square_root<float, true>
: square_root_for_fundamental_fp<float>
{
};
template <>
struct square_root<double, true>
: square_root_for_fundamental_fp<double>
{
};
template <>
struct square_root<long double, true>
: square_root_for_fundamental_fp<long double>
{
};
template <typename T>
struct square_root<T, true>
{
typedef double return_type;
static inline double apply(T const& value)
{
// for all other fundamental number types use also std::sqrt
//
// Note: in C++98 the only other possibility is double;
// in C++11 there are also overloads for integral types;
// this specialization works for those as well.
return square_root_for_fundamental_fp
<
double
>::apply(boost::numeric_cast<double>(value));
}
};
template
<
typename T,
bool IsFundemantal = std::is_fundamental<T>::value /* false */
>
struct modulo
{
typedef T return_type;
static inline T apply(T const& value1, T const& value2)
{
// for non-fundamental number types assume that a free
// function mod() is defined either:
// 1) at T's scope, or
// 2) at global scope
return mod(value1, value2);
}
};
template
<
typename Fundamental,
bool IsIntegral = std::is_integral<Fundamental>::value
>
struct modulo_for_fundamental
{
typedef Fundamental return_type;
static inline Fundamental apply(Fundamental const& value1,
Fundamental const& value2)
{
return value1 % value2;
}
};
// specialization for floating-point numbers
template <typename Fundamental>
struct modulo_for_fundamental<Fundamental, false>
{
typedef Fundamental return_type;
static inline Fundamental apply(Fundamental const& value1,
Fundamental const& value2)
{
return std::fmod(value1, value2);
}
};
// specialization for fundamental number type
template <typename Fundamental>
struct modulo<Fundamental, true>
: modulo_for_fundamental<Fundamental>
{};
/*!
\brief Short constructs to enable partial specialization for PI, 2*PI
and PI/2, currently not possible in Math.
*/
template <typename T>
struct define_pi
{
static inline T apply()
{
// Default calls Boost.Math
return boost::math::constants::pi<T>();
}
};
template <typename T>
struct define_two_pi
{
static inline T apply()
{
// Default calls Boost.Math
return boost::math::constants::two_pi<T>();
}
};
template <typename T>
struct define_half_pi
{
static inline T apply()
{
// Default calls Boost.Math
return boost::math::constants::half_pi<T>();
}
};
template <typename T>
struct relaxed_epsilon
{
static inline T apply(const T& factor)
{
return factor * std::numeric_limits<T>::epsilon();
}
};
// This must be consistent with math::equals.
// By default math::equals() scales the error by epsilon using the greater of
// compared values but here is only one value, though it should work the same way.
// (a-a) <= max(a, a) * EPS -> 0 <= a*EPS
// (a+da-a) <= max(a+da, a) * EPS -> da <= (a+da)*EPS
template <typename T, bool IsIntegral = std::is_integral<T>::value>
struct scaled_epsilon
{
static inline T apply(T const& val)
{
return (std::max)(abs<T>::apply(val), T(1))
* std::numeric_limits<T>::epsilon();
}
static inline T apply(T const& val, T const& eps)
{
return (std::max)(abs<T>::apply(val), T(1))
* eps;
}
};
template <typename T>
struct scaled_epsilon<T, true>
{
static inline T apply(T const&)
{
return T(0);
}
static inline T apply(T const&, T const&)
{
return T(0);
}
};
// ItoF ItoI FtoF
template <typename Result, typename Source,
bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
struct rounding_cast
{
static inline Result apply(Source const& v)
{
return boost::numeric_cast<Result>(v);
}
};
// TtoT
template <typename Source, bool ResultIsInteger, bool SourceIsInteger>
struct rounding_cast<Source, Source, ResultIsInteger, SourceIsInteger>
{
static inline Source apply(Source const& v)
{
return v;
}
};
// FtoI
template <typename Result, typename Source>
struct rounding_cast<Result, Source, true, false>
{
static inline Result apply(Source const& v)
{
return boost::numeric_cast<Result>(v < Source(0) ?
v - Source(0.5) :
v + Source(0.5));
}
};
} // namespace detail
#endif
template <typename T>
inline T pi() { return detail::define_pi<T>::apply(); }
template <typename T>
inline T two_pi() { return detail::define_two_pi<T>::apply(); }
template <typename T>
inline T half_pi() { return detail::define_half_pi<T>::apply(); }
template <typename T>
inline T relaxed_epsilon(T const& factor)
{
return detail::relaxed_epsilon<T>::apply(factor);
}
template <typename T>
inline T scaled_epsilon(T const& value)
{
return detail::scaled_epsilon<T>::apply(value);
}
template <typename T>
inline T scaled_epsilon(T const& value, T const& eps)
{
return detail::scaled_epsilon<T>::apply(value, eps);
}
// Maybe replace this by boost equals or so
/*!
\brief returns true if both arguments are equal.
\ingroup utility
\param a first argument
\param b second argument
\return true if a == b
\note If both a and b are of an integral type, comparison is done by ==.
If one of the types is floating point, comparison is done by abs and
comparing with epsilon. If one of the types is non-fundamental, it might
be a high-precision number and comparison is done using the == operator
of that class.
*/
template <typename T1, typename T2>
inline bool equals(T1 const& a, T2 const& b)
{
return detail::equals
<
typename select_most_precise<T1, T2>::type
>::apply(a, b, detail::equals_default_policy());
}
template <typename T1, typename T2>
inline bool equals_with_epsilon(T1 const& a, T2 const& b)
{
return detail::equals_with_epsilon
<
typename select_most_precise<T1, T2>::type
>::apply(a, b, detail::equals_default_policy());
}
template <typename T1, typename T2>
inline bool smaller(T1 const& a, T2 const& b)
{
return detail::smaller
<
typename select_most_precise<T1, T2>::type
>::apply(a, b);
}
template <typename T1, typename T2>
inline bool larger(T1 const& a, T2 const& b)
{
return detail::smaller
<
typename select_most_precise<T1, T2>::type
>::apply(b, a);
}
template <typename T1, typename T2>
inline bool smaller_or_equals(T1 const& a, T2 const& b)
{
return detail::smaller_or_equals
<
typename select_most_precise<T1, T2>::type
>::apply(a, b);
}
template <typename T1, typename T2>
inline bool larger_or_equals(T1 const& a, T2 const& b)
{
return detail::smaller_or_equals
<
typename select_most_precise<T1, T2>::type
>::apply(b, a);
}
template <typename T>
inline T d2r()
{
static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);
return conversion_coefficient;
}
template <typename T>
inline T r2d()
{
static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();
return conversion_coefficient;
}
#ifndef DOXYGEN_NO_DETAIL
namespace detail {
template <typename DegreeOrRadian>
struct as_radian
{
template <typename T>
static inline T apply(T const& value)
{
return value;
}
};
template <>
struct as_radian<degree>
{
template <typename T>
static inline T apply(T const& value)
{
return value * d2r<T>();
}
};
template <typename DegreeOrRadian>
struct from_radian
{
template <typename T>
static inline T apply(T const& value)
{
return value;
}
};
template <>
struct from_radian<degree>
{
template <typename T>
static inline T apply(T const& value)
{
return value * r2d<T>();
}
};
} // namespace detail
#endif
template <typename DegreeOrRadian, typename T>
inline T as_radian(T const& value)
{
return detail::as_radian<DegreeOrRadian>::apply(value);
}
template <typename DegreeOrRadian, typename T>
inline T from_radian(T const& value)
{
return detail::from_radian<DegreeOrRadian>::apply(value);
}
/*!
\brief Calculates the haversine of an angle
\ingroup utility
\note See http://en.wikipedia.org/wiki/Haversine_formula
haversin(alpha) = sin2(alpha/2)
*/
template <typename T>
inline T hav(T const& theta)
{
T const half = T(0.5);
T const sn = sin(half * theta);
return sn * sn;
}
/*!
\brief Short utility to return the square
\ingroup utility
\param value Value to calculate the square from
\return The squared value
*/
template <typename T>
inline T sqr(T const& value)
{
return value * value;
}
/*!
\brief Short utility to return the square root
\ingroup utility
\param value Value to calculate the square root from
\return The square root value
*/
template <typename T>
inline typename detail::square_root<T>::return_type
sqrt(T const& value)
{
return detail::square_root
<
T, std::is_fundamental<T>::value
>::apply(value);
}
/*!
\brief Short utility to return the modulo of two values
\ingroup utility
\param value1 First value
\param value2 Second value
\return The result of the modulo operation on the (ordered) pair
(value1, value2)
*/
template <typename T>
inline typename detail::modulo<T>::return_type
mod(T const& value1, T const& value2)
{
return detail::modulo
<
T, std::is_fundamental<T>::value
>::apply(value1, value2);
}
/*!
\brief Short utility to workaround gcc/clang problem that abs is converting to integer
and that older versions of MSVC does not support abs of long long...
\ingroup utility
*/
template<typename T>
inline T abs(T const& value)
{
return detail::abs<T>::apply(value);
}
/*!
\brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
\ingroup utility
*/
template <typename T>
inline int sign(T const& value)
{
T const zero = T();
return value > zero ? 1 : value < zero ? -1 : 0;
}
/*!
\brief Short utility to cast a value possibly rounding it to the nearest
integral value.
\ingroup utility
\note If the source T is NOT an integral type and Result is an integral type
the value is rounded towards the closest integral value. Otherwise it's
casted without rounding.
*/
template <typename Result, typename T>
inline Result rounding_cast(T const& v)
{
return detail::rounding_cast<Result, T>::apply(v);
}
/*!
\brief Evaluate the sine and cosine function with the argument in degrees
\note The results obey exactly the elementary properties of the trigonometric
functions, e.g., sin 9&deg; = cos 81&deg; = &minus; sin 123456789&deg;.
If x = &minus;0, then \e sinx = &minus;0; this is the only case where
&minus;0 is returned.
*/
template<typename T>
inline void sin_cos_degrees(T const& x,
T & sinx,
T & cosx)
{
// In order to minimize round-off errors, this function exactly reduces
// the argument to the range [-45, 45] before converting it to radians.
T remainder; int quotient;
remainder = math::mod(x, T(360));
quotient = floor(remainder / 90 + T(0.5));
remainder -= 90 * quotient;
// Convert to radians.
remainder *= d2r<T>();
T s = sin(remainder), c = cos(remainder);
switch (unsigned(quotient) & 3U)
{
case 0U: sinx = s; cosx = c; break;
case 1U: sinx = c; cosx = -s; break;
case 2U: sinx = -s; cosx = -c; break;
default: sinx = -c; cosx = s; break; // case 3U
}
// Set sign of 0 results. -0 only produced for sin(-0).
if (x != 0)
{
sinx += T(0); cosx += T(0);
}
}
/*!
\brief Round off a given angle
*/
template<typename T>
inline T round_angle(T const& x) {
static const T z = 1/T(16);
if (x == 0)
{
return 0;
}
T y = math::abs(x);
// z - (z - y) must not be simplified to y.
y = y < z ? z - (z - y) : y;
return x < 0 ? -y : y;
}
/*!
\brief The error-free sum of two numbers.
*/
template<typename T>
inline T sum_error(T const& u, T const& v, T& t)
{
volatile T s = u + v;
volatile T up = s - v;
volatile T vpp = s - up;
up -= u;
vpp -= v;
t = -(up + vpp);
return s;
}
/*!
\brief Evaluate the polynomial in x using Horner's method.
*/
// TODO: adl1995 - Merge these functions with formulas/area_formulas.hpp
// i.e. place them in one file.
template <typename NT, typename IteratorType>
inline NT horner_evaluate(NT const& x,
IteratorType begin,
IteratorType end)
{
NT result(0);
IteratorType it = end;
do
{
result = result * x + *--it;
}
while (it != begin);
return result;
}
/*!
\brief Evaluate the polynomial.
*/
template<typename IteratorType, typename CT>
inline CT polyval(IteratorType first,
IteratorType last,
CT const& eps)
{
int N = std::distance(first, last) - 1;
int index = 0;
CT y = N < 0 ? 0 : *(first + (index++));
while (--N >= 0)
{
y = y * eps + *(first + (index++));
}
return y;
}
/*
\brief Short utility to calculate the power
\ingroup utility
*/
template <typename T1, typename T2>
inline T1 pow(T1 const& a, T2 const& b)
{
using std::pow;
return pow(a, b);
}
} // namespace math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_MATH_HPP

View File

@@ -0,0 +1,192 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry
{
namespace math
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Units, typename CoordinateType, bool IsEquatorial = true>
class normalize_spheroidal_box_coordinates
{
private:
typedef normalize_spheroidal_coordinates<Units, CoordinateType> normalize;
typedef constants_on_spheroid<CoordinateType, Units> constants;
static inline bool is_band(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
return ! math::smaller(math::abs(longitude1 - longitude2),
constants::period());
}
public:
static inline void apply(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2,
bool band)
{
normalize::apply(longitude1, latitude1, false);
normalize::apply(longitude2, latitude2, false);
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude1);
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude2);
if (math::equals(latitude1, constants::min_latitude())
&& math::equals(latitude2, constants::min_latitude()))
{
// box degenerates to the south pole
longitude1 = longitude2 = CoordinateType(0);
}
else if (math::equals(latitude1, constants::max_latitude())
&& math::equals(latitude2, constants::max_latitude()))
{
// box degenerates to the north pole
longitude1 = longitude2 = CoordinateType(0);
}
else if (band)
{
// the box is a band between two small circles (parallel
// to the equator) on the spheroid
longitude1 = constants::min_longitude();
longitude2 = constants::max_longitude();
}
else if (longitude1 > longitude2)
{
// the box crosses the antimeridian, so we need to adjust
// the longitudes
longitude2 += constants::period();
}
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude1);
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude2);
#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2));
BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude()));
BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude()));
#endif
BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));
BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));
BOOST_GEOMETRY_ASSERT
(! math::larger(longitude2 - longitude1, constants::period()));
}
static inline void apply(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2)
{
bool const band = is_band(longitude1, longitude2);
apply(longitude1, latitude1, longitude2, latitude2, band);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Short utility to normalize the coordinates of a box on a spheroid
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Minimum longitude of the box
\param latitude1 Minimum latitude of the box
\param longitude2 Maximum longitude of the box
\param latitude2 Maximum latitude of the box
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType
>::apply(longitude1, latitude1, longitude2, latitude2);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude1, latitude1, longitude2, latitude2);
}
/*!
\brief Short utility to normalize the coordinates of a box on a spheroid
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Minimum longitude of the box
\param latitude1 Minimum latitude of the box
\param longitude2 Maximum longitude of the box
\param latitude2 Maximum latitude of the box
\param band Indicates whether the box should be treated as a band or
not and avoid the computation done in the other version of the function
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2,
bool band)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType
>::apply(longitude1, latitude1, longitude2, latitude2, band);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2,
bool band)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude1, latitude1, longitude2, latitude2, band);
}
} // namespace math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP

View File

@@ -0,0 +1,510 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace math
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// CoordinateType, radian, true
template <typename CoordinateType, typename Units, bool IsEquatorial = true>
struct constants_on_spheroid
{
static inline CoordinateType period()
{
return math::two_pi<CoordinateType>();
}
static inline CoordinateType half_period()
{
return math::pi<CoordinateType>();
}
static inline CoordinateType quarter_period()
{
static CoordinateType const
pi_half = math::pi<CoordinateType>() / CoordinateType(2);
return pi_half;
}
static inline CoordinateType min_longitude()
{
static CoordinateType const minus_pi = -math::pi<CoordinateType>();
return minus_pi;
}
static inline CoordinateType max_longitude()
{
return math::pi<CoordinateType>();
}
static inline CoordinateType min_latitude()
{
static CoordinateType const minus_half_pi
= -math::half_pi<CoordinateType>();
return minus_half_pi;
}
static inline CoordinateType max_latitude()
{
return math::half_pi<CoordinateType>();
}
};
template <typename CoordinateType>
struct constants_on_spheroid<CoordinateType, radian, false>
: constants_on_spheroid<CoordinateType, radian, true>
{
static inline CoordinateType min_latitude()
{
return CoordinateType(0);
}
static inline CoordinateType max_latitude()
{
return math::pi<CoordinateType>();
}
};
template <typename CoordinateType>
struct constants_on_spheroid<CoordinateType, degree, true>
{
static inline CoordinateType period()
{
return CoordinateType(360.0);
}
static inline CoordinateType half_period()
{
return CoordinateType(180.0);
}
static inline CoordinateType quarter_period()
{
return CoordinateType(90.0);
}
static inline CoordinateType min_longitude()
{
return CoordinateType(-180.0);
}
static inline CoordinateType max_longitude()
{
return CoordinateType(180.0);
}
static inline CoordinateType min_latitude()
{
return CoordinateType(-90.0);
}
static inline CoordinateType max_latitude()
{
return CoordinateType(90.0);
}
};
template <typename CoordinateType>
struct constants_on_spheroid<CoordinateType, degree, false>
: constants_on_spheroid<CoordinateType, degree, true>
{
static inline CoordinateType min_latitude()
{
return CoordinateType(0);
}
static inline CoordinateType max_latitude()
{
return CoordinateType(180.0);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Units, typename CoordinateType>
inline CoordinateType latitude_convert_ep(CoordinateType const& lat)
{
typedef math::detail::constants_on_spheroid
<
CoordinateType,
Units
> constants;
return constants::quarter_period() - lat;
}
template <typename Units, bool IsEquatorial, typename T>
static bool is_latitude_pole(T const& lat)
{
typedef math::detail::constants_on_spheroid
<
T,
Units
> constants;
return math::equals(math::abs(IsEquatorial
? lat
: math::latitude_convert_ep<Units>(lat)),
constants::quarter_period());
}
template <typename Units, typename T>
static bool is_longitude_antimeridian(T const& lon)
{
typedef math::detail::constants_on_spheroid
<
T,
Units
> constants;
return math::equals(math::abs(lon), constants::half_period());
}
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Units, bool IsEquatorial>
struct latitude_convert_if_polar
{
template <typename T>
static inline void apply(T & /*lat*/) {}
};
template <typename Units>
struct latitude_convert_if_polar<Units, false>
{
template <typename T>
static inline void apply(T & lat)
{
lat = latitude_convert_ep<Units>(lat);
}
};
template <typename Units, typename CoordinateType, bool IsEquatorial = true>
class normalize_spheroidal_coordinates
{
typedef constants_on_spheroid<CoordinateType, Units> constants;
protected:
static inline CoordinateType normalize_up(CoordinateType const& value)
{
return
math::mod(value + constants::half_period(), constants::period())
- constants::half_period();
}
static inline CoordinateType normalize_down(CoordinateType const& value)
{
return
math::mod(value - constants::half_period(), constants::period())
+ constants::half_period();
}
public:
static inline void apply(CoordinateType& longitude)
{
// normalize longitude
if (math::equals(math::abs(longitude), constants::half_period()))
{
longitude = constants::half_period();
}
else if (longitude > constants::half_period())
{
longitude = normalize_up(longitude);
if (math::equals(longitude, -constants::half_period()))
{
longitude = constants::half_period();
}
}
else if (longitude < -constants::half_period())
{
longitude = normalize_down(longitude);
}
}
static inline void apply(CoordinateType& longitude,
CoordinateType& latitude,
bool normalize_poles = true)
{
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
// normalize latitude
if (math::larger(latitude, constants::half_period()))
{
latitude = normalize_up(latitude);
}
else if (math::smaller(latitude, -constants::half_period()))
{
latitude = normalize_down(latitude);
}
// fix latitude range
if (latitude < constants::min_latitude())
{
latitude = -constants::half_period() - latitude;
longitude -= constants::half_period();
}
else if (latitude > constants::max_latitude())
{
latitude = constants::half_period() - latitude;
longitude -= constants::half_period();
}
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
// normalize longitude
apply(longitude);
// finally normalize poles
if (normalize_poles)
{
if (math::equals(math::abs(latitude), constants::max_latitude()))
{
// for the north and south pole we set the longitude to 0
// (works for both radians and degrees)
longitude = CoordinateType(0);
}
}
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
BOOST_GEOMETRY_ASSERT(! math::larger(constants::min_latitude(), latitude));
BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude()));
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
BOOST_GEOMETRY_ASSERT(math::smaller(constants::min_longitude(), longitude));
BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude()));
}
};
template <typename Units, typename CoordinateType>
inline void normalize_angle_loop(CoordinateType& angle)
{
typedef constants_on_spheroid<CoordinateType, Units> constants;
CoordinateType const pi = constants::half_period();
CoordinateType const two_pi = constants::period();
while (angle > pi)
angle -= two_pi;
while (angle <= -pi)
angle += two_pi;
}
template <typename Units, typename CoordinateType>
inline void normalize_angle_cond(CoordinateType& angle)
{
typedef constants_on_spheroid<CoordinateType, Units> constants;
CoordinateType const pi = constants::half_period();
CoordinateType const two_pi = constants::period();
if (angle > pi)
angle -= two_pi;
else if (angle <= -pi)
angle += two_pi;
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Short utility to normalize the coordinates on a spheroid
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude Longitude
\param latitude Latitude
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
CoordinateType& latitude)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType
>::apply(longitude, latitude);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
CoordinateType& latitude)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude, latitude);
}
/*!
\brief Short utility to normalize the longitude on a spheroid.
Note that in general both coordinates should be normalized at once.
This utility is suitable e.g. for normalization of the difference of longitudes.
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude Longitude
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_longitude(CoordinateType& longitude)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType
>::apply(longitude);
}
/*!
\brief Short utility to normalize the azimuth on a spheroid
in the range (-180, 180].
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param angle Angle
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_azimuth(CoordinateType& angle)
{
normalize_longitude<Units, CoordinateType>(angle);
}
/*!
\brief Normalize the given values.
\tparam ValueType The type of the values
\param x Value x
\param y Value y
TODO: adl1995 - Merge this function with
formulas/vertex_longitude.hpp
*/
template<typename ValueType>
inline void normalize_unit_vector(ValueType& x, ValueType& y)
{
ValueType h = boost::math::hypot(x, y);
BOOST_GEOMETRY_ASSERT(h > 0);
x /= h; y /= h;
}
/*!
\brief Short utility to calculate difference between two longitudes
normalized in range (-180, 180].
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Longitude 1
\param longitude2 Longitude 2
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_distance_signed(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
CoordinateType diff = longitude2 - longitude1;
math::normalize_longitude<Units, CoordinateType>(diff);
return diff;
}
/*!
\brief Short utility to calculate difference between two longitudes
normalized in range [0, 360).
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Longitude 1
\param longitude2 Longitude 2
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
typedef math::detail::constants_on_spheroid
<
CoordinateType, Units
> constants;
CoordinateType const c0 = 0;
CoordinateType diff = longitude_distance_signed<Units>(longitude1, longitude2);
if (diff < c0) // (-180, 180] -> [0, 360)
{
diff += constants::period();
}
return diff;
}
/*!
\brief The abs difference between longitudes in range [0, 180].
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Longitude 1
\param longitude2 Longitude 2
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_difference(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
return math::abs(math::longitude_distance_signed<Units>(longitude1, longitude2));
}
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_interval_distance_signed(CoordinateType const& longitude_a1,
CoordinateType const& longitude_a2,
CoordinateType const& longitude_b)
{
CoordinateType const c0 = 0;
CoordinateType dist_a12 = longitude_distance_signed<Units>(longitude_a1, longitude_a2);
CoordinateType dist_a1b = longitude_distance_signed<Units>(longitude_a1, longitude_b);
if (dist_a12 < c0)
{
dist_a12 = -dist_a12;
dist_a1b = -dist_a1b;
}
return dist_a1b < c0 ? dist_a1b
: dist_a1b > dist_a12 ? dist_a1b - dist_a12
: c0;
}
} // namespace math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP

View File

@@ -0,0 +1,46 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
#define BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/views/reversible_view.hpp>
namespace boost { namespace geometry
{
template<order_selector Order>
struct order_as_direction
{};
template<>
struct order_as_direction<clockwise>
{
static const iterate_direction value = iterate_forward;
};
template<>
struct order_as_direction<counterclockwise>
{
static const iterate_direction value = iterate_reverse;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP

View File

@@ -0,0 +1,78 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
#define BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
#include <type_traits>
#include <boost/function_types/function_arity.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/at.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function selecting a parameter type of a (member) function, by index
\ingroup utility
*/
template <typename Method, std::size_t Index>
struct parameter_type_of
{
typedef typename boost::function_types::parameter_types
<
Method
>::type parameter_types;
typedef std::conditional_t
<
boost::function_types::is_member_function_pointer<Method>::value,
std::integral_constant<int, 1>,
std::integral_constant<int, 0>
> base_index_type;
typedef std::conditional_t
<
Index == 0,
base_index_type,
std::integral_constant
<
int,
(base_index_type::value + Index)
>
> indexed_type;
typedef typename std::remove_reference
<
typename boost::mpl::at
<
parameter_types,
indexed_type
>::type
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP

View File

@@ -0,0 +1,52 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
#include <type_traits>
namespace boost { namespace geometry
{
/*!
\brief Meta-function converting, if necessary, to "a floating point" type
\details
- if input type is integer, type is double
- else type is input type
\ingroup utility
*/
template <typename T, typename PromoteIntegerTo = double>
struct promote_floating_point
{
typedef std::conditional_t
<
std::is_integral<T>::value,
PromoteIntegerTo,
T
> type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP

View File

@@ -0,0 +1,299 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
#define BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
// For now deactivate the use of multiprecision integers
// TODO: activate it later
#define BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
#include <climits>
#include <cstddef>
#include <type_traits>
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
#include <boost/multiprecision/cpp_int.hpp>
#endif
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace promote_integral
{
// meta-function that returns the bit size of a type
template
<
typename T,
bool IsFundamental = std::is_fundamental<T>::value
>
struct bit_size
{};
// for fundamental types, just return CHAR_BIT * sizeof(T)
template <typename T>
struct bit_size<T, true>
: std::integral_constant<std::size_t, (CHAR_BIT * sizeof(T))>
{};
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
// partial specialization for cpp_int
template
<
unsigned MinSize,
unsigned MaxSize,
boost::multiprecision::cpp_integer_type SignType,
boost::multiprecision::cpp_int_check_type Checked,
typename Allocator,
boost::multiprecision::expression_template_option ExpressionTemplates
>
struct bit_size
<
boost::multiprecision::number
<
boost::multiprecision::cpp_int_backend
<
MinSize, MaxSize, SignType, Checked, Allocator
>,
ExpressionTemplates
>,
false
>
: std::integral_constant<std::size_t, MaxSize>
{};
#endif // BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
template <typename T, std::size_t MinSize, typename ...Ts>
struct promote_to_larger
{
// if promotion fails, keep the number T
// (and cross fingers that overflow will not occur)
typedef T type;
};
template <typename T, std::size_t MinSize, typename CurrentT, typename ...Ts>
struct promote_to_larger<T, MinSize, CurrentT, Ts...>
{
typedef std::conditional_t
<
(bit_size<CurrentT>::value >= MinSize),
CurrentT,
typename promote_to_larger<T, MinSize, Ts...>::type
> type;
};
template <typename ...Ts>
struct integral_types {};
template <typename T, std::size_t MinSize, typename ...Ts>
struct promote_to_larger<T, MinSize, integral_types<Ts...>>
: promote_to_larger<T, MinSize, Ts...>
{};
}} // namespace detail::promote_integral
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Meta-function to define an integral type with size
than is (roughly) twice the bit size of T
\ingroup utility
\details
This meta-function tries to promote the fundamental integral type T
to a another integral type with size (roughly) twice the bit size of T.
To do this, two times the bit size of T is tested against the bit sizes of:
short, int, long, long long, boost::int128_t
and the one that first matches is chosen.
For unsigned types the bit size of T is tested against the bit
sizes of the types above, if T is promoted to a signed type, or
the bit sizes of
unsigned short, unsigned int, unsigned long, std::size_t,
unsigned long long, boost::uint128_t
if T is promoted to an unsigned type.
By default an unsigned type is promoted to a signed type.
This behavior is controlled by the PromoteUnsignedToUnsigned
boolean template parameter, whose default value is "false".
To promote an unsigned type to an unsigned type set the value of
this template parameter to "true".
If the macro BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is not
defined, boost's multiprecision integer cpp_int<> is used as a
last resort.
If BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is defined and an
appropriate type cannot be detected, the input type is returned as is.
Finally, if the passed type is either a floating-point type or a
user-defined type it is returned as is.
\note boost::int128_type and boost::uint128_type are considered
only if the macros BOOST_HAS_INT128 and BOOST_GEOMETRY_ENABLE_INT128
are defined
*/
template
<
typename T,
bool PromoteUnsignedToUnsigned = false,
bool UseCheckedInteger = false,
bool IsIntegral = std::is_integral<T>::value
>
class promote_integral
{
private:
static bool const is_unsigned = std::is_unsigned<T>::value;
typedef detail::promote_integral::bit_size<T> bit_size_type;
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
// Define the proper check policy for the multiprecision integer
typedef std::conditional_t
<
UseCheckedInteger,
std::integral_constant
<
boost::multiprecision::cpp_int_check_type,
boost::multiprecision::checked
>,
std::integral_constant
<
boost::multiprecision::cpp_int_check_type,
boost::multiprecision::unchecked
>
> check_policy_type;
// Meta-function to get the multiprecision integer type for the
// given size and sign type (signed/unsigned)
template
<
unsigned int Size,
boost::multiprecision::cpp_integer_type SignType
>
struct multiprecision_integer_type
{
typedef boost::multiprecision::number
<
boost::multiprecision::cpp_int_backend
<
Size,
Size,
SignType,
check_policy_type::value,
void
>
> type;
};
#endif
// Define the minimum size (in bits) needed for the promoted type
// If T is the input type and P the promoted type, then the
// minimum number of bits for P are (below b stands for the number
// of bits of T):
// * if T is unsigned and P is unsigned: 2 * b
// * if T is signed and P is signed: 2 * b - 1
// * if T is unsigned and P is signed: 2 * b + 1
typedef std::conditional_t
<
(PromoteUnsignedToUnsigned && is_unsigned),
std::integral_constant<std::size_t, (2 * bit_size_type::value)>,
std::conditional_t
<
is_unsigned,
std::integral_constant<std::size_t, (2 * bit_size_type::value + 1)>,
std::integral_constant<std::size_t, (2 * bit_size_type::value - 1)>
>
> min_bit_size_type;
// Define the list of signed integral types we are going to use
// for promotion
typedef detail::promote_integral::integral_types
<
short,
int,
long,
long long
#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
, boost::int128_type
#endif
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
, typename multiprecision_integer_type
<
min_bit_size_type::value,
boost::multiprecision::signed_magnitude
>::type
#endif
> signed_integral_types;
// Define the list of unsigned integral types we are going to use
// for promotion
typedef detail::promote_integral::integral_types
<
unsigned short,
unsigned int,
unsigned long,
std::size_t,
unsigned long long
#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
, boost::uint128_type
#endif
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
, typename multiprecision_integer_type
<
min_bit_size_type::value,
boost::multiprecision::unsigned_magnitude
>::type
#endif
> unsigned_integral_types;
// Define the list of integral types that will be used for
// promotion (depending in whether we was to promote unsigned to
// unsigned or not)
typedef std::conditional_t
<
(is_unsigned && PromoteUnsignedToUnsigned),
unsigned_integral_types,
signed_integral_types
> integral_types;
public:
typedef typename detail::promote_integral::promote_to_larger
<
T,
min_bit_size_type::value,
integral_types
>::type type;
};
template <typename T, bool PromoteUnsignedToUnsigned, bool UseCheckedInteger>
class promote_integral
<
T, PromoteUnsignedToUnsigned, UseCheckedInteger, false
>
{
public:
typedef T type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP

View File

@@ -0,0 +1,460 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013-2020.
// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
#include <algorithm>
#include <iterator>
#include <type_traits>
#include <boost/concept_check.hpp>
#include <boost/config.hpp>
#include <boost/core/addressof.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/rbegin.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/mutable_range.hpp>
namespace boost { namespace geometry { namespace range
{
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
template <typename T>
struct is_iterator
: std::integral_constant
<
bool,
has_iterator_category
<
std::iterator_traits<T>
>::value
>
{};
template <typename T, bool HasIterator = boost::has_range_iterator<T>::value>
struct is_range_impl
: is_iterator
<
typename boost::range_iterator<T>::type
>
{};
template <typename T>
struct is_range_impl<T, false>
: std::false_type
{};
template <typename T>
struct is_range
: is_range_impl<T>
{};
// NOTE: For SinglePassRanges pos could iterate over all elements until the i-th element was met.
template <typename RandomAccessRange>
struct pos
{
typedef typename boost::range_iterator<RandomAccessRange>::type iterator;
typedef typename boost::range_size<RandomAccessRange>::type size_type;
typedef typename boost::range_difference<RandomAccessRange>::type difference_type;
static inline iterator apply(RandomAccessRange & rng, size_type i)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<RandomAccessRange> ));
return boost::begin(rng) + static_cast<difference_type>(i);
}
};
} // namespace detail
/*!
\brief Short utility to conveniently return an iterator of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_iterator<RandomAccessRange const>::type
pos(RandomAccessRange const& rng,
typename boost::range_size<RandomAccessRange const>::type i)
{
BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
return detail::pos<RandomAccessRange const>::apply(rng, i);
}
/*!
\brief Short utility to conveniently return an iterator of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_iterator<RandomAccessRange>::type
pos(RandomAccessRange & rng,
typename boost::range_size<RandomAccessRange>::type i)
{
BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
return detail::pos<RandomAccessRange>::apply(rng, i);
}
/*!
\brief Short utility to conveniently return an element of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_reference<RandomAccessRange const>::type
at(RandomAccessRange const& rng,
typename boost::range_size<RandomAccessRange const>::type i)
{
BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
return * detail::pos<RandomAccessRange const>::apply(rng, i);
}
/*!
\brief Short utility to conveniently return an element of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_reference<RandomAccessRange>::type
at(RandomAccessRange & rng,
typename boost::range_size<RandomAccessRange>::type i)
{
BOOST_GEOMETRY_ASSERT(i < boost::size(rng));
return * detail::pos<RandomAccessRange>::apply(rng, i);
}
/*!
\brief Short utility to conveniently return the front element of a Range.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_reference<Range const>::type
front(Range const& rng)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
/*!
\brief Short utility to conveniently return the front element of a Range.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_reference<Range>::type
front(Range & rng)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
// NOTE: For SinglePassRanges back() could iterate over all elements until the last element is met.
/*!
\brief Short utility to conveniently return the back element of a BidirectionalRange.
\ingroup utility
*/
template <typename BidirectionalRange>
inline typename boost::range_reference<BidirectionalRange const>::type
back(BidirectionalRange const& rng)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept<BidirectionalRange const> ));
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *(boost::rbegin(rng));
}
/*!
\brief Short utility to conveniently return the back element of a BidirectionalRange.
\ingroup utility
*/
template <typename BidirectionalRange>
inline typename boost::range_reference<BidirectionalRange>::type
back(BidirectionalRange & rng)
{
BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *(boost::rbegin(rng));
}
/*!
\brief Short utility to conveniently clear a mutable range.
It uses traits::clear<>.
\ingroup utility
*/
template <typename Range>
inline void clear(Range & rng)
{
// NOTE: this trait is probably not needed since it could be implemented using resize()
geometry::traits::clear<Range>::apply(rng);
}
/*!
\brief Short utility to conveniently insert a new element at the end of a mutable range.
It uses boost::geometry::traits::push_back<>.
\ingroup utility
*/
template <typename Range>
inline void push_back(Range & rng,
typename boost::range_value<Range>::type const& value)
{
geometry::traits::push_back<Range>::apply(rng, value);
}
/*!
\brief Short utility to conveniently resize a mutable range.
It uses boost::geometry::traits::resize<>.
\ingroup utility
*/
template <typename Range>
inline void resize(Range & rng,
typename boost::range_size<Range>::type new_size)
{
geometry::traits::resize<Range>::apply(rng, new_size);
}
/*!
\brief Short utility to conveniently remove an element from the back of a mutable range.
It uses resize().
\ingroup utility
*/
template <typename Range>
inline void pop_back(Range & rng)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
range::resize(rng, boost::size(rng) - 1);
}
namespace detail {
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename It,
typename OutIt,
bool UseMove = std::is_convertible
<
typename std::iterator_traits<It>::value_type &&,
typename std::iterator_traits<OutIt>::value_type
>::value>
struct copy_or_move_impl
{
static inline OutIt apply(It first, It last, OutIt out)
{
return std::move(first, last, out);
}
};
template <typename It, typename OutIt>
struct copy_or_move_impl<It, OutIt, false>
{
static inline OutIt apply(It first, It last, OutIt out)
{
return std::copy(first, last, out);
}
};
template <typename It, typename OutIt>
inline OutIt copy_or_move(It first, It last, OutIt out)
{
return copy_or_move_impl<It, OutIt>::apply(first, last, out);
}
#else
template <typename It, typename OutIt>
inline OutIt copy_or_move(It first, It last, OutIt out)
{
return std::copy(first, last, out);
}
#endif
} // namespace detail
/*!
\brief Short utility to conveniently remove an element from a mutable range.
It uses std::copy() and resize(). Version taking mutable iterators.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range>::type it)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
BOOST_GEOMETRY_ASSERT(it != boost::end(rng));
typename boost::range_difference<Range>::type const
d = std::distance(boost::begin(rng), it);
typename boost::range_iterator<Range>::type
next = it;
++next;
detail::copy_or_move(next, boost::end(rng), it);
range::resize(rng, boost::size(rng) - 1);
// NOTE: In general this should be sufficient:
// return it;
// But in MSVC using the returned iterator causes
// assertion failures when iterator debugging is enabled
// Furthermore the code below should work in the case if resize()
// invalidates iterators when the container is resized down.
return boost::begin(rng) + d;
}
/*!
\brief Short utility to conveniently remove an element from a mutable range.
It uses std::copy() and resize(). Version taking non-mutable iterators.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range const>::type cit)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
typename boost::range_iterator<Range>::type
it = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cit);
return range::erase(rng, it);
}
/*!
\brief Short utility to conveniently remove a range of elements from a mutable range.
It uses std::copy() and resize(). Version taking mutable iterators.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range>::type first,
typename boost::range_iterator<Range>::type last)
{
typename boost::range_difference<Range>::type const
diff = std::distance(first, last);
BOOST_GEOMETRY_ASSERT(diff >= 0);
std::size_t const count = static_cast<std::size_t>(diff);
BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));
if ( count > 0 )
{
typename boost::range_difference<Range>::type const
d = std::distance(boost::begin(rng), first);
detail::copy_or_move(last, boost::end(rng), first);
range::resize(rng, boost::size(rng) - count);
// NOTE: In general this should be sufficient:
// return first;
// But in MSVC using the returned iterator causes
// assertion failures when iterator debugging is enabled
// Furthermore the code below should work in the case if resize()
// invalidates iterators when the container is resized down.
return boost::begin(rng) + d;
}
return first;
}
/*!
\brief Short utility to conveniently remove a range of elements from a mutable range.
It uses std::copy() and resize(). Version taking non-mutable iterators.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range const>::type cfirst,
typename boost::range_iterator<Range const>::type clast)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
typename boost::range_iterator<Range>::type
first = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cfirst);
typename boost::range_iterator<Range>::type
last = boost::begin(rng)
+ std::distance(boost::const_begin(rng), clast);
return range::erase(rng, first, last);
}
// back_inserter
template <class Container>
class back_insert_iterator
{
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
typedef Container container_type;
explicit back_insert_iterator(Container & c)
: container(boost::addressof(c))
{}
back_insert_iterator & operator=(typename Container::value_type const& value)
{
range::push_back(*container, value);
return *this;
}
back_insert_iterator & operator* ()
{
return *this;
}
back_insert_iterator & operator++ ()
{
return *this;
}
back_insert_iterator operator++(int)
{
return *this;
}
private:
Container * container;
};
template <typename Range>
inline back_insert_iterator<Range> back_inserter(Range & rng)
{
return back_insert_iterator<Range>(rng);
}
}}} // namespace boost::geometry::range
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP

View File

@@ -0,0 +1,179 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2011-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2011-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP
#define BOOST_GEOMETRY_UTIL_RATIONAL_HPP
#include <boost/rational.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/geometry/util/coordinate_cast.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost{ namespace geometry
{
// Specialize for Boost.Geometry's coordinate cast
// (from string to coordinate type)
namespace detail
{
template <typename T>
struct coordinate_cast<rational<T> >
{
static inline void split_parts(std::string const& source, std::string::size_type p,
T& before, T& after, bool& negate, std::string::size_type& len)
{
std::string before_part = source.substr(0, p);
std::string const after_part = source.substr(p + 1);
negate = false;
if (before_part.size() > 0 && before_part[0] == '-')
{
negate = true;
before_part.erase(0, 1);
}
before = atol(before_part.c_str());
after = atol(after_part.c_str());
len = after_part.length();
}
static inline rational<T> apply(std::string const& source)
{
T before, after;
bool negate;
std::string::size_type len;
// Note: decimal comma is not (yet) supported, it does (and should) not
// occur in a WKT, where points are comma separated.
std::string::size_type p = source.find(".");
if (p == std::string::npos)
{
p = source.find("/");
if (p == std::string::npos)
{
return rational<T>(atol(source.c_str()));
}
split_parts(source, p, before, after, negate, len);
return negate
? -rational<T>(before, after)
: rational<T>(before, after)
;
}
split_parts(source, p, before, after, negate, len);
T den = 1;
for (std::string::size_type i = 0; i < len; i++)
{
den *= 10;
}
return negate
? -rational<T>(before) - rational<T>(after, den)
: rational<T>(before) + rational<T>(after, den)
;
}
};
} // namespace detail
// Specialize for Boost.Geometry's select_most_precise
template <typename T1, typename T2>
struct select_most_precise<boost::rational<T1>, boost::rational<T2> >
{
typedef typename boost::rational
<
typename select_most_precise<T1, T2>::type
> type;
};
template <typename T>
struct select_most_precise<boost::rational<T>, double>
{
typedef typename boost::rational<T> type;
};
}} // namespace boost::geometry
// Specializes boost::rational to boost::numeric::bounds
namespace boost { namespace numeric
{
template<class T>
struct bounds<rational<T> >
{
static inline rational<T> lowest()
{
return rational<T>(bounds<T>::lowest(), 1);
}
static inline rational<T> highest()
{
return rational<T>(bounds<T>::highest(), 1);
}
};
}} // namespace boost::numeric
// Support for boost::numeric_cast to int and to double (necessary for SVG-mapper)
namespace boost { namespace numeric
{
template
<
typename T,
typename Traits,
typename OverflowHandler,
typename Float2IntRounder,
typename RawConverter,
typename UserRangeChecker
>
struct converter<int, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
{
static inline int convert(rational<T> const& arg)
{
return int(rational_cast<double>(arg));
}
};
template
<
typename T,
typename Traits,
typename OverflowHandler,
typename Float2IntRounder,
typename RawConverter,
typename UserRangeChecker
>
struct converter<double, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
{
static inline double convert(rational<T> const& arg)
{
return rational_cast<double>(arg);
}
};
}}
#endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP

View File

@@ -0,0 +1,76 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function selecting the "calculation" type
\details Based on two input geometry types, and an input calculation type,
(which defaults to void in the calling function), this meta-function
selects the most appropriate:
- if calculation type is specified, that one is used,
- if it is void, the most precise of the two points is used
\ingroup utility
*/
template <typename Geometry1, typename Geometry2, typename CalculationType>
struct select_calculation_type
{
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename select_coordinate_type
<
Geometry1,
Geometry2
>::type,
CalculationType
> type;
};
// alternative version supporting more than 2 Geometries
template
<
typename CalculationType,
typename ...Geometries
>
struct select_calculation_type_alt
{
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename select_coordinate_type
<
Geometries...
>::type,
CalculationType
> type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP

View File

@@ -0,0 +1,48 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function selecting the most precise coordinate type
of geometries
\ingroup utility
*/
template <typename ...Geometries>
struct select_coordinate_type
{
typedef typename select_most_precise
<
typename coordinate_type<Geometries>::type...
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP

View File

@@ -0,0 +1,148 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
#include <type_traits>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace select_most_precise
{
// 0 - void
// 1 - integral
// 2 - floating point
// 3 - non-fundamental
template <typename T>
struct type_priority
: std::conditional_t
<
std::is_void<T>::value,
std::integral_constant<int, 0>,
std::conditional_t
<
std::is_fundamental<T>::value,
std::conditional_t
<
std::is_floating_point<T>::value,
std::integral_constant<int, 2>,
std::integral_constant<int, 1>
>,
std::integral_constant<int, 3>
>
>
{};
template <typename T>
struct type_size
: std::integral_constant<std::size_t, sizeof(T)>
{};
template <>
struct type_size<void>
: std::integral_constant<std::size_t, 0>
{};
}} // namespace detail::select_most_precise
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Meta-function to select the most accurate type for
calculations
\ingroup utility
\details select_most_precise classes, compares types on compile time.
For example, if an addition must be done with a double and an integer, the
result must be a double.
If both types are integer, the result can be an integer.
\note It is different from the "promote" class, already in boost. That
class promotes e.g. a (one) float to a double. This class selects a
type from two types. It takes the most accurate, but does not promote
afterwards.
\note If the input is a non-fundamental type, it might be a calculation
type such as a GMP-value or another high precision value. Therefore,
if one is non-fundamental, that one is chosen.
\note If both types are non-fundamental, the result is indeterminate and
currently the first one is chosen.
*/
template <typename ...Types>
struct select_most_precise
{
typedef void type;
};
template <typename T>
struct select_most_precise<T>
{
typedef T type;
};
template <typename T1, typename T2>
struct select_most_precise<T1, T2>
{
static const int priority1 = detail::select_most_precise::type_priority<T1>::value;
static const int priority2 = detail::select_most_precise::type_priority<T2>::value;
static const std::size_t size1 = detail::select_most_precise::type_size<T1>::value;
static const std::size_t size2 = detail::select_most_precise::type_size<T2>::value;
typedef std::conditional_t
<
(priority1 > priority2),
T1,
std::conditional_t
<
(priority2 > priority1),
T2,
std::conditional_t // priority1 == priority2
<
(priority1 == 0 || priority1 == 3), // both void or non-fundamental
T1,
std::conditional_t // both fundamental
<
(size2 > size1),
T2,
T1
>
>
>
> type;
};
template <typename T1, typename T2, typename ...Types>
struct select_most_precise<T1, T2, Types...>
{
typedef typename select_most_precise
<
typename select_most_precise<T1, T2>::type,
typename select_most_precise<Types...>::type
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP

View File

@@ -0,0 +1,274 @@
// Boost.Geometry
// Copyright (c) 2020, 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_SEQUENCE_HPP
#define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
#include <type_traits>
namespace boost { namespace geometry
{
namespace util
{
// An alternative would be to use std:tuple and std::pair
// but it would add dependency.
template <typename ...Ts>
struct type_sequence {};
// true if T is a sequence
template <typename T>
struct is_sequence : std::false_type {};
template <typename ...Ts>
struct is_sequence<type_sequence<Ts...>> : std::true_type {};
template <typename T, T ...Is>
struct is_sequence<std::integer_sequence<T, Is...>> : std::true_type {};
// number of elements in a sequence
template <typename Sequence>
struct sequence_size {};
template <typename ...Ts>
struct sequence_size<type_sequence<Ts...>>
: std::integral_constant<std::size_t, sizeof...(Ts)>
{};
template <typename T, T ...Is>
struct sequence_size<std::integer_sequence<T, Is...>>
: std::integral_constant<std::size_t, sizeof...(Is)>
{};
// element of a sequence
template <std::size_t I, typename Sequence>
struct sequence_element {};
template <std::size_t I, typename T, typename ...Ts>
struct sequence_element<I, type_sequence<T, Ts...>>
{
typedef typename sequence_element<I - 1, type_sequence<Ts...>>::type type;
};
template <typename T, typename ...Ts>
struct sequence_element<0, type_sequence<T, Ts...>>
{
typedef T type;
};
template <std::size_t I, typename T, T J, T ...Js>
struct sequence_element<I, std::integer_sequence<T, J, Js...>>
: std::integral_constant
<
T,
sequence_element<I - 1, std::integer_sequence<T, Js...>>::value
>
{};
template <typename T, T J, T ...Js>
struct sequence_element<0, std::integer_sequence<T, J, Js...>>
: std::integral_constant<T, J>
{};
template <typename Sequence>
struct sequence_front
: sequence_element<0, Sequence>
{
static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
};
template <typename Sequence>
struct sequence_back
: sequence_element<sequence_size<Sequence>::value - 1, Sequence>
{
static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
};
template <typename Sequence>
struct sequence_empty
: std::integral_constant
<
bool,
sequence_size<Sequence>::value == 0
>
{};
// merge<type_sequence<A, B>, type_sequence<C, D>>::type is
// type_sequence<A, B, C, D>
// merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
// integer_sequence<A, B, C, D>
template <typename ...Sequences>
struct merge;
template <typename S>
struct merge<S>
{
typedef S type;
};
template <typename ...T1s, typename ...T2s>
struct merge<type_sequence<T1s...>, type_sequence<T2s...>>
{
typedef type_sequence<T1s..., T2s...> type;
};
template <typename T, T ...I1s, T ...I2s>
struct merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
{
typedef std::integer_sequence<T, I1s..., I2s...> type;
};
template <typename S1, typename S2, typename ...Sequences>
struct merge<S1, S2, Sequences...>
{
typedef typename merge
<
typename merge<S1, S2>::type,
typename merge<Sequences...>::type
>::type type;
};
// combine<type_sequence<A, B>, type_sequence<C, D>>::type is
// type_sequence<type_sequence<A, C>, type_sequence<A, D>,
// type_sequence<B, C>, type_sequence<B, D>>
template <typename Sequence1, typename Sequence2>
struct combine;
template <typename ...T1s, typename ...T2s>
struct combine<type_sequence<T1s...>, type_sequence<T2s...>>
{
template <typename U1, typename ...U2s>
using type_sequence_t = type_sequence<type_sequence<U1, U2s>...>;
typedef typename merge
<
type_sequence_t<T1s, T2s...>...
>::type type;
};
// combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
// type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
// integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
template <typename T, T ...I1s, T ...I2s>
struct combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
{
template <T J1, T ...J2s>
using type_sequence_t = type_sequence<std::integer_sequence<T, J1, J2s>...>;
typedef typename merge
<
type_sequence_t<I1s, I2s...>...
>::type type;
};
// Selects least element from a parameter pack based on
// LessPred<T1, T2>::value comparison, similar to std::min_element
template
<
template <typename, typename> class LessPred,
typename ...Ts
>
struct select_pack_element;
template
<
template <typename, typename> class LessPred,
typename T
>
struct select_pack_element<LessPred, T>
{
typedef T type;
};
template
<
template <typename, typename> class LessPred,
typename T1, typename T2
>
struct select_pack_element<LessPred, T1, T2>
{
typedef std::conditional_t<LessPred<T1, T2>::value, T1, T2> type;
};
template
<
template <typename, typename> class LessPred,
typename T1, typename T2, typename ...Ts
>
struct select_pack_element<LessPred, T1, T2, Ts...>
{
typedef typename select_pack_element
<
LessPred,
typename select_pack_element<LessPred, T1, T2>::type,
typename select_pack_element<LessPred, Ts...>::type
>::type type;
};
// Selects least element from a sequence based on
// LessPred<T1, T2>::value comparison, similar to std::min_element
template
<
typename Sequence,
template <typename, typename> class LessPred
>
struct select_element;
template
<
typename ...Ts,
template <typename, typename> class LessPred
>
struct select_element<type_sequence<Ts...>, LessPred>
{
typedef typename select_pack_element<LessPred, Ts...>::type type;
};
// Selects least pair sequence of elements from a parameter pack based on
// LessPred<xxx_sequence<T11, T12>, xxx_sequence<T21, T22>>::value comparison
template
<
typename Sequence1,
typename Sequence2,
template <typename, typename> class LessPred
>
struct select_combination_element
{
typedef typename select_element
<
typename combine<Sequence1, Sequence2>::type,
LessPred
>::type type;
};
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP

View File

@@ -0,0 +1,752 @@
// Boost.Geometry
// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program.
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is converted from GeographicLib, https://geographiclib.sourceforge.io
// GeographicLib is originally written by Charles Karney.
// Author: Charles Karney (2008-2017)
// Last updated version of GeographicLib: 1.49
// Original copyright notice:
// Copyright (c) Charles Karney (2008-2017) <charles@karney.com> and licensed
// under the MIT/X11 License. For more information, see
// https://geographiclib.sourceforge.io
#ifndef BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
#define BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry { namespace series_expansion {
/*
Generate and evaluate the series expansion of the following integral
I1 = integrate( sqrt(1+k2*sin(sigma1)^2), sigma1, 0, sigma )
which is valid for k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
and expand (1 - eps) * I1 retaining terms up to order eps^maxpow
in A1 and C1[l].
The resulting series is of the form
A1 * ( sigma + sum(C1[l] * sin(2*l*sigma), l, 1, maxpow) ).
The scale factor A1-1 = mean value of (d/dsigma)I1 - 1
The expansion above is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_A1 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
To replace each number x by CT(x) the following
script can be used:
sed -e 's/[0-9]\+/CT(&)/g; s/\[CT/\[/g; s/)\]/\]/g;
s/case\sCT(/case /g; s/):/:/g; s/epsCT(2)/eps2/g;'
*/
template <size_t SeriesOrder, typename CT>
inline CT evaluate_A1(CT eps)
{
CT eps2 = math::sqr(eps);
CT t;
switch (SeriesOrder/2) {
case 0:
t = CT(0);
break;
case 1:
t = eps2/CT(4);
break;
case 2:
t = eps2*(eps2+CT(16))/CT(64);
break;
case 3:
t = eps2*(eps2*(eps2+CT(4))+CT(64))/CT(256);
break;
case 4:
t = eps2*(eps2*(eps2*(CT(25)*eps2+CT(64))+CT(256))+CT(4096))/CT(16384);
break;
}
return (t + eps) / (CT(1) - eps);
}
/*
Generate and evaluate the series expansion of the following integral
I2 = integrate( 1/sqrt(1+k2*sin(sigma1)^2), sigma1, 0, sigma )
which is valid for k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
and expand (1 - eps) * I2 retaining terms up to order eps^maxpow
in A2 and C2[l].
The resulting series is of the form
A2 * ( sigma + sum(C2[l] * sin(2*l*sigma), l, 1, maxpow) )
The scale factor A2-1 = mean value of (d/dsigma)2 - 1
The expansion above is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_A2 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <size_t SeriesOrder, typename CT>
inline CT evaluate_A2(CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT t;
switch (SeriesOrder/2) {
case 0:
t = CT(0);
break;
case 1:
t = -CT(3)*eps2/CT(4);
break;
case 2:
t = (-CT(7)*eps2-CT(48))*eps2/CT(64);
break;
case 3:
t = eps2*((-CT(11)*eps2-CT(28))*eps2-CT(192))/CT(256);
break;
default:
t = eps2*(eps2*((-CT(375)*eps2-CT(704))*eps2-CT(1792))-CT(12288))/CT(16384);
break;
}
return (t - eps) / (CT(1) + eps);
}
/*
Express
I3 = integrate( (2-f)/(1+(1-f)*sqrt(1+k2*sin(sigma1)^2)), sigma1, 0, sigma )
as a series
A3 * ( sigma + sum(C3[l] * sin(2*l*sigma), l, 1, maxpow-1) )
valid for f and k2 small. It is convenient to write k2 = 4 * eps / (1 -
eps)^2 and f = 2*n/(1+n) and expand in eps and n. This procedure leads
to a series where the coefficients of eps^j are terminating series in n.
The scale factor A3 = mean value of (d/dsigma)I3
The expansion above is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_A3 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_A3(Coeffs &c, CT const& n)
{
switch (int(Coeffs::static_size)) {
case 0:
break;
case 1:
c[0] = CT(1);
break;
case 2:
c[0] = CT(1);
c[1] = -CT(1)/CT(2);
break;
case 3:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = -CT(1)/CT(4);
break;
case 4:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (-n-CT(2))/CT(8);
c[3] = -CT(1)/CT(16);
break;
case 5:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = (-CT(3)*n-CT(1))/CT(16);
c[4] = -CT(3)/CT(64);
break;
case 6:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = ((-n-CT(3))*n-CT(1))/CT(16);
c[4] = (-CT(2)*n-CT(3))/CT(64);
c[5] = -CT(3)/CT(128);
break;
case 7:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = (n*(n*(CT(5)*n-CT(1))-CT(3))-CT(1))/CT(16);
c[4] = ((-CT(10)*n-CT(2))*n-CT(3))/CT(64);
c[5] = (-CT(5)*n-CT(3))/CT(128);
c[6] = -CT(5)/CT(256);
break;
default:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = (n*(n*(CT(5)*n-CT(1))-CT(3))-CT(1))/CT(16);
c[4] = (n*((-CT(5)*n-CT(20))*n-CT(4))-CT(6))/CT(128);
c[5] = ((-CT(5)*n-CT(10))*n-CT(6))/CT(256);
c[6] = (-CT(15)*n-CT(20))/CT(1024);
c[7] = -CT(25)/CT(2048);
break;
}
}
/*
The coefficients C1[l] in the Fourier expansion of B1.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C1 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C1(Coeffs &c, CT const& eps)
{
CT eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1) {
case 0:
break;
case 1:
c[1] = -d/CT(2);
break;
case 2:
c[1] = -d/CT(2);
d *= eps;
c[2] = -d/CT(16);
break;
case 3:
c[1] = d*(CT(3)*eps2-CT(8))/CT(16);
d *= eps;
c[2] = -d/CT(16);
d *= eps;
c[3] = -d/CT(48);
break;
case 4:
c[1] = d*(CT(3)*eps2-CT(8))/CT(16);
d *= eps;
c[2] = d*(eps2-CT(2))/CT(32);
d *= eps;
c[3] = -d/CT(48);
d *= eps;
c[4] = -CT(5)*d/CT(512);
break;
case 5:
c[1] = d*((CT(6)-eps2)*eps2-CT(16))/CT(32);
d *= eps;
c[2] = d*(eps2-CT(2))/CT(32);
d *= eps;
c[3] = d*(CT(9)*eps2-CT(16))/CT(768);
d *= eps;
c[4] = -CT(5)*d/CT(512);
d *= eps;
c[5] = -CT(7)*d/CT(1280);
break;
case 6:
c[1] = d*((CT(6)-eps2)*eps2-CT(16))/CT(32);
d *= eps;
c[2] = d*((CT(64)-CT(9)*eps2)*eps2-CT(128))/CT(2048);
d *= eps;
c[3] = d*(CT(9)*eps2-CT(16))/CT(768);
d *= eps;
c[4] = d*(CT(3)*eps2-CT(5))/CT(512);
d *= eps;
c[5] = -CT(7)*d/CT(1280);
d *= eps;
c[6] = -CT(7)*d/CT(2048);
break;
case 7:
c[1] = d*(eps2*(eps2*(CT(19)*eps2-CT(64))+CT(384))-CT(1024))/CT(2048);
d *= eps;
c[2] = d*((CT(64)-CT(9)*eps2)*eps2-CT(128))/CT(2048);
d *= eps;
c[3] = d*((CT(72)-CT(9)*eps2)*eps2-CT(128))/CT(6144);
d *= eps;
c[4] = d*(CT(3)*eps2-CT(5))/CT(512);
d *= eps;
c[5] = d*(CT(35)*eps2-CT(56))/CT(10240);
d *= eps;
c[6] = -CT(7)*d/CT(2048);
d *= eps;
c[7] = -CT(33)*d/CT(14336);
break;
default:
c[1] = d*(eps2*(eps2*(CT(19)*eps2-CT(64))+CT(384))-CT(1024))/CT(2048);
d *= eps;
c[2] = d*(eps2*(eps2*(CT(7)*eps2-CT(18))+CT(128))-CT(256))/CT(4096);
d *= eps;
c[3] = d*((CT(72)-CT(9)*eps2)*eps2-CT(128))/CT(6144);
d *= eps;
c[4] = d*((CT(96)-CT(11)*eps2)*eps2-CT(160))/CT(16384);
d *= eps;
c[5] = d*(CT(35)*eps2-CT(56))/CT(10240);
d *= eps;
c[6] = d*(CT(9)*eps2-CT(14))/CT(4096);
d *= eps;
c[7] = -CT(33)*d/CT(14336);
d *= eps;
c[8] = -CT(429)*d/CT(262144);
break;
}
}
/*
The coefficients C1p[l] in the Fourier expansion of B1p.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C1p below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C1p(Coeffs& c, CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1) {
case 0:
break;
case 1:
c[1] = d/CT(2);
break;
case 2:
c[1] = d/CT(2);
d *= eps;
c[2] = CT(5)*d/CT(16);
break;
case 3:
c[1] = d*(CT(16)-CT(9)*eps2)/CT(32);
d *= eps;
c[2] = CT(5)*d/CT(16);
d *= eps;
c[3] = CT(29)*d/CT(96);
break;
case 4:
c[1] = d*(CT(16)-CT(9)*eps2)/CT(32);
d *= eps;
c[2] = d*(CT(30)-CT(37)*eps2)/CT(96);
d *= eps;
c[3] = CT(29)*d/CT(96);
d *= eps;
c[4] = CT(539)*d/CT(1536);
break;
case 5:
c[1] = d*(eps2*(CT(205)*eps2-CT(432))+CT(768))/CT(1536);
d *= eps;
c[2] = d*(CT(30)-CT(37)*eps2)/CT(96);
d *= eps;
c[3] = d*(CT(116)-CT(225)*eps2)/CT(384);
d *= eps;
c[4] = CT(539)*d/CT(1536);
d *= eps;
c[5] = CT(3467)*d/CT(7680);
break;
case 6:
c[1] = d*(eps2*(CT(205)*eps2-CT(432))+CT(768))/CT(1536);
d *= eps;
c[2] = d*(eps2*(CT(4005)*eps2-CT(4736))+CT(3840))/CT(12288);
d *= eps;
c[3] = d*(CT(116)-CT(225)*eps2)/CT(384);
d *= eps;
c[4] = d*(CT(2695)-CT(7173)*eps2)/CT(7680);
d *= eps;
c[5] = CT(3467)*d/CT(7680);
d *= eps;
c[6] = CT(38081)*d/CT(61440);
break;
case 7:
c[1] = d*(eps2*((CT(9840)-CT(4879)*eps2)*eps2-CT(20736))+CT(36864))/CT(73728);
d *= eps;
c[2] = d*(eps2*(CT(4005)*eps2-CT(4736))+CT(3840))/CT(12288);
d *= eps;
c[3] = d*(eps2*(CT(8703)*eps2-CT(7200))+CT(3712))/CT(12288);
d *= eps;
c[4] = d*(CT(2695)-CT(7173)*eps2)/CT(7680);
d *= eps;
c[5] = d*(CT(41604)-CT(141115)*eps2)/CT(92160);
d *= eps;
c[6] = CT(38081)*d/CT(61440);
d *= eps;
c[7] = CT(459485)*d/CT(516096);
break;
default:
c[1] = d*(eps2*((CT(9840)-CT(4879)*eps2)*eps2-CT(20736))+CT(36864))/CT(73728);
d *= eps;
c[2] = d*(eps2*((CT(120150)-CT(86171)*eps2)*eps2-CT(142080))+CT(115200))/CT(368640);
d *= eps;
c[3] = d*(eps2*(CT(8703)*eps2-CT(7200))+CT(3712))/CT(12288);
d *= eps;
c[4] = d*(eps2*(CT(1082857)*eps2-CT(688608))+CT(258720))/CT(737280);
d *= eps;
c[5] = d*(CT(41604)-CT(141115)*eps2)/CT(92160);
d *= eps;
c[6] = d*(CT(533134)-CT(2200311)*eps2)/CT(860160);
d *= eps;
c[7] = CT(459485)*d/CT(516096);
d *= eps;
c[8] = CT(109167851)*d/CT(82575360);
break;
}
}
/*
The coefficients C2[l] in the Fourier expansion of B2.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C2 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C2(Coeffs& c, CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1) {
case 0:
break;
case 1:
c[1] = d/CT(2);
break;
case 2:
c[1] = d/CT(2);
d *= eps;
c[2] = CT(3)*d/CT(16);
break;
case 3:
c[1] = d*(eps2+CT(8))/CT(16);
d *= eps;
c[2] = CT(3)*d/CT(16);
d *= eps;
c[3] = CT(5)*d/CT(48);
break;
case 4:
c[1] = d*(eps2+CT(8))/CT(16);
d *= eps;
c[2] = d*(eps2+CT(6))/CT(32);
d *= eps;
c[3] = CT(5)*d/CT(48);
d *= eps;
c[4] = CT(35)*d/CT(512);
break;
case 5:
c[1] = d*(eps2*(eps2+CT(2))+CT(16))/CT(32);
d *= eps;
c[2] = d*(eps2+CT(6))/CT(32);
d *= eps;
c[3] = d*(CT(15)*eps2+CT(80))/CT(768);
d *= eps;
c[4] = CT(35)*d/CT(512);
d *= eps;
c[5] = CT(63)*d/CT(1280);
break;
case 6:
c[1] = d*(eps2*(eps2+CT(2))+CT(16))/CT(32);
d *= eps;
c[2] = d*(eps2*(CT(35)*eps2+CT(64))+CT(384))/CT(2048);
d *= eps;
c[3] = d*(CT(15)*eps2+CT(80))/CT(768);
d *= eps;
c[4] = d*(CT(7)*eps2+CT(35))/CT(512);
d *= eps;
c[5] = CT(63)*d/CT(1280);
d *= eps;
c[6] = CT(77)*d/CT(2048);
break;
case 7:
c[1] = d*(eps2*(eps2*(CT(41)*eps2+CT(64))+CT(128))+CT(1024))/CT(2048);
d *= eps;
c[2] = d*(eps2*(CT(35)*eps2+CT(64))+CT(384))/CT(2048);
d *= eps;
c[3] = d*(eps2*(CT(69)*eps2+CT(120))+CT(640))/CT(6144);
d *= eps;
c[4] = d*(CT(7)*eps2+CT(35))/CT(512);
d *= eps;
c[5] = d*(CT(105)*eps2+CT(504))/CT(10240);
d *= eps;
c[6] = CT(77)*d/CT(2048);
d *= eps;
c[7] = CT(429)*d/CT(14336);
break;
default:
c[1] = d*(eps2*(eps2*(CT(41)*eps2+CT(64))+CT(128))+CT(1024))/CT(2048);
d *= eps;
c[2] = d*(eps2*(eps2*(CT(47)*eps2+CT(70))+CT(128))+CT(768))/CT(4096);
d *= eps;
c[3] = d*(eps2*(CT(69)*eps2+CT(120))+CT(640))/CT(6144);
d *= eps;
c[4] = d*(eps2*(CT(133)*eps2+CT(224))+CT(1120))/CT(16384);
d *= eps;
c[5] = d*(CT(105)*eps2+CT(504))/CT(10240);
d *= eps;
c[6] = d*(CT(33)*eps2+CT(154))/CT(4096);
d *= eps;
c[7] = CT(429)*d/CT(14336);
d *= eps;
c[8] = CT(6435)*d/CT(262144);
break;
}
}
/*
The coefficients C3[l] in the Fourier expansion of B3.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C3 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <size_t SeriesOrder, typename Coeffs, typename CT>
inline void evaluate_coeffs_C3x(Coeffs &c, CT const& n) {
size_t const coeff_size = Coeffs::static_size;
size_t const expected_size = (SeriesOrder * (SeriesOrder - 1)) / 2;
BOOST_GEOMETRY_ASSERT((coeff_size == expected_size));
const CT n2 = math::sqr(n);
switch (SeriesOrder) {
case 0:
break;
case 1:
break;
case 2:
c[0] = (CT(1)-n)/CT(4);
break;
case 3:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = ((n-CT(3))*n+CT(2))/CT(32);
break;
case 4:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = ((n-CT(3))*n+CT(2))/CT(32);
c[4] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[5] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
break;
case 5:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = ((n-CT(3))*n+CT(2))/CT(32);
c[5] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[6] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[7] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[8] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[9] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
break;
case 6:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
c[5] = ((n-CT(3))*n+CT(2))/CT(32);
c[6] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[7] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[8] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
c[9] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[10] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[11] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
c[12] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
c[13] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
c[14] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
break;
case 7:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
c[5] = (CT(10)*n+CT(21))/CT(1024);
c[6] = ((n-CT(3))*n+CT(2))/CT(32);
c[7] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[8] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[9] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
c[10] = (CT(69)*n+CT(108))/CT(8192);
c[11] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[12] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[13] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
c[14] = (CT(12)-n)/CT(1024);
c[15] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
c[16] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
c[17] = (CT(72)-CT(43)*n)/CT(8192);
c[18] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
c[19] = (CT(9)-CT(15)*n)/CT(1024);
c[20] = (CT(44)-CT(99)*n)/CT(8192);
break;
default:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
c[5] = (CT(10)*n+CT(21))/CT(1024);
c[6] = CT(243)/CT(16384);
c[7] = ((n-CT(3))*n+CT(2))/CT(32);
c[8] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[9] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[10] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
c[11] = (CT(69)*n+CT(108))/CT(8192);
c[12] = CT(187)/CT(16384);
c[13] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[14] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[15] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
c[16] = (CT(12)-n)/CT(1024);
c[17] = CT(139)/CT(16384);
c[18] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
c[19] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
c[20] = (CT(72)-CT(43)*n)/CT(8192);
c[21] = CT(127)/CT(16384);
c[22] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
c[23] = (CT(9)-CT(15)*n)/CT(1024);
c[24] = CT(99)/CT(16384);
c[25] = (CT(44)-CT(99)*n)/CT(8192);
c[26] = CT(99)/CT(16384);
c[27] = CT(429)/CT(114688);
break;
}
}
/*
\brief Given the set of coefficients coeffs2[] evaluate on
C3 and return the set of coefficients coeffs1[].
Elements coeffs1[1] through coeffs1[SeriesOrder - 1] are set.
*/
template <typename Coeffs1, typename Coeffs2, typename CT>
inline void evaluate_coeffs_C3(Coeffs1 &coeffs1, Coeffs2 &coeffs2, CT const& eps)
{
CT mult = 1;
size_t offset = 0;
// i is the index of C3[i].
for (size_t i = 1; i < Coeffs1::static_size; ++i)
{
// Order of polynomial in eps.
size_t m = Coeffs1::static_size - i;
mult *= eps;
coeffs1[i] = mult * math::horner_evaluate(eps, coeffs2.begin() + offset,
coeffs2.begin() + offset + m);
offset += m;
}
// Post condition: offset == coeffs_C3_size
}
/*
\brief Evaluate the following:
y = sum(c[i] * sin(2*i * x), i, 1, n)
using Clenshaw summation.
*/
template <typename CT, typename Coeffs>
inline CT sin_cos_series(CT const& sinx, CT const& cosx, Coeffs const& coeffs)
{
size_t n = Coeffs::static_size - 1;
size_t index = 0;
// Point to one beyond last element.
index += (n + 1);
CT ar = 2 * (cosx - sinx) * (cosx + sinx);
// If n is odd, get the last element.
CT k0 = n & 1 ? coeffs[--index] : 0;
CT k1 = 0;
// Make n even.
n /= 2;
while (n--) {
// Unroll loop x 2, so accumulators return to their original role.
k1 = ar * k0 - k1 + coeffs[--index];
k0 = ar * k1 - k0 + coeffs[--index];
}
return 2 * sinx * cosx * k0;
}
/*
The coefficient containers for the series expansions.
These structs allow the caller to only know the series order.
*/
template <size_t SeriesOrder, typename CT>
struct coeffs_C1 : boost::array<CT, SeriesOrder + 1>
{
coeffs_C1(CT const& epsilon)
{
evaluate_coeffs_C1(*this, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C1p : boost::array<CT, SeriesOrder + 1>
{
coeffs_C1p(CT const& epsilon)
{
evaluate_coeffs_C1p(*this, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C2 : boost::array<CT, SeriesOrder + 1>
{
coeffs_C2(CT const& epsilon)
{
evaluate_coeffs_C2(*this, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C3x : boost::array<CT, (SeriesOrder * (SeriesOrder - 1)) / 2>
{
coeffs_C3x(CT const& n)
{
evaluate_coeffs_C3x<SeriesOrder>(*this, n);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C3 : boost::array<CT, SeriesOrder>
{
coeffs_C3(CT const& n, CT const& epsilon)
{
coeffs_C3x<SeriesOrder, CT> coeffs_C3x(n);
evaluate_coeffs_C3(*this, coeffs_C3x, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_A3 : boost::array<CT, SeriesOrder>
{
coeffs_A3(CT const& n)
{
evaluate_coeffs_A3(*this, n);
}
};
}}} // namespace boost::geometry::series_expansion
#endif // BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP

View File

@@ -0,0 +1,91 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP
#define BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE("This header is deprecated.")
#endif
#include <boost/mpl/transform.hpp>
#include <boost/variant/variant_fwd.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function that takes a Sequence type, an MPL lambda
expression and an optional Inserter and returns a variant type over
the same types as the initial variant type, each transformed using
the lambda expression.
\ingroup utility
\par Example
\code
typedef boost::mpl::vector<int, float, long> types;
typedef transform_variant<types, add_pointer<_> > transformed;
typedef variant<int*, float*, long*> result;
BOOST_MPL_ASSERT(( equal<result, transformed> ));
\endcode
*/
template <typename Sequence, typename Op, typename In = boost::mpl::na>
struct transform_variant:
make_variant_over<
typename boost::mpl::transform<
Sequence,
Op,
In
>::type
>
{};
/*!
\brief Meta-function that takes a boost::variant type and an MPL lambda
expression and returns a variant type over the same types as the
initial variant type, each transformed using the lambda expression.
\ingroup utility
\par Example
\code
typedef variant<int, float, long> variant_type;
typedef transform_variant<variant_type, add_pointer<_> > transformed;
typedef variant<int*, float*, long*> result;
BOOST_MPL_ASSERT(( equal<result, transformed> ));
\endcode
*/
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Op>
struct transform_variant<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Op, boost::mpl::na> :
make_variant_over<
typename boost::mpl::transform<
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
Op
>::type
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP

View File

@@ -0,0 +1,389 @@
// Boost.Geometry Index
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_TUPLES_HPP
#define BOOST_GEOMETRY_UTIL_TUPLES_HPP
#include <tuple>
#include <type_traits>
#include <utility>
#include <boost/geometry/core/config.hpp>
#include <boost/tuple/tuple.hpp>
namespace boost { namespace geometry { namespace tuples
{
template <typename T>
struct is_tuple
: std::integral_constant<bool, false>
{};
template <typename ...Ts>
struct is_tuple<std::tuple<Ts...>>
: std::integral_constant<bool, true>
{};
template <typename F, typename S>
struct is_tuple<std::pair<F, S>>
: std::integral_constant<bool, true>
{};
template <typename ...Ts>
struct is_tuple<boost::tuples::tuple<Ts...>>
: std::integral_constant<bool, true>
{};
template <typename HT, typename TT>
struct is_tuple<boost::tuples::cons<HT, TT>>
: std::integral_constant<bool, true>
{};
template <std::size_t I, typename Tuple>
struct element;
template <std::size_t I, typename ...Ts>
struct element<I, std::tuple<Ts...>>
: std::tuple_element<I, std::tuple<Ts...>>
{};
template <std::size_t I, typename HT, typename TT>
struct element<I, std::pair<HT, TT>>
: std::tuple_element<I, std::pair<HT, TT>>
{};
template <std::size_t I, typename ...Ts>
struct element<I, boost::tuples::tuple<Ts...>>
{
typedef typename boost::tuples::element
<
I, boost::tuples::tuple<Ts...>
>::type type;
};
template <std::size_t I, typename HT, typename TT>
struct element<I, boost::tuples::cons<HT, TT>>
{
typedef typename boost::tuples::element
<
I, boost::tuples::cons<HT, TT>
>::type type;
};
template <typename Tuple>
struct size;
template <typename ...Ts>
struct size<std::tuple<Ts...>>
: std::tuple_size<std::tuple<Ts...>>
{};
template <typename HT, typename TT>
struct size<std::pair<HT, TT>>
: std::tuple_size<std::pair<HT, TT>>
{};
template <typename ...Ts>
struct size<boost::tuples::tuple<Ts...>>
: std::integral_constant
<
std::size_t,
boost::tuples::length<boost::tuples::tuple<Ts...>>::value
>
{};
template <typename HT, typename TT>
struct size<boost::tuples::cons<HT, TT>>
: std::integral_constant
<
std::size_t,
boost::tuples::length<boost::tuples::cons<HT, TT>>::value
>
{};
template <std::size_t I, typename ...Ts>
constexpr inline typename std::tuple_element<I, std::tuple<Ts...>>::type&
get(std::tuple<Ts...> & t)
{
return std::get<I>(t);
}
template <std::size_t I, typename ...Ts>
constexpr inline typename std::tuple_element<I, std::tuple<Ts...>>::type const&
get(std::tuple<Ts...> const& t)
{
return std::get<I>(t);
}
template <std::size_t I, typename HT, typename TT>
constexpr inline typename std::tuple_element<I, std::pair<HT, TT>>::type&
get(std::pair<HT, TT> & t)
{
return std::get<I>(t);
}
template <std::size_t I, typename HT, typename TT>
constexpr inline typename std::tuple_element<I, std::pair<HT, TT>>::type const&
get(std::pair<HT, TT> const& t)
{
return std::get<I>(t);
}
template <std::size_t I, typename ...Ts>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::tuple<Ts...>>::type
>::non_const_type
get(boost::tuples::tuple<Ts...> & t)
{
return boost::tuples::get<I>(t);
}
template <std::size_t I, typename ...Ts>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::tuple<Ts...>>::type
>::const_type
get(boost::tuples::tuple<Ts...> const& t)
{
return boost::tuples::get<I>(t);
}
template <std::size_t I, typename HT, typename TT>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
>::non_const_type
get(boost::tuples::cons<HT, TT> & tup)
{
return boost::tuples::get<I>(tup);
}
template <std::size_t I, typename HT, typename TT>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
>::const_type
get(boost::tuples::cons<HT, TT> const& tup)
{
return boost::tuples::get<I>(tup);
}
// find_index_if
// Searches for the index of an element for which UnaryPredicate returns true
// If such element is not found the result is N
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t I = 0,
std::size_t N = size<Tuple>::value
>
struct find_index_if
: std::conditional_t
<
UnaryPred<typename element<I, Tuple>::type>::value,
std::integral_constant<std::size_t, I>,
typename find_index_if<Tuple, UnaryPred, I+1, N>::type
>
{};
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t N
>
struct find_index_if<Tuple, UnaryPred, N, N>
: std::integral_constant<std::size_t, N>
{};
// find_if
// Searches for an element for which UnaryPredicate returns true
// If such element is not found the result is detail::null_type
namespace detail
{
struct null_type {};
} // detail
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t I = 0,
std::size_t N = size<Tuple>::value
>
struct find_if
: std::conditional_t
<
UnaryPred<typename element<I, Tuple>::type>::value,
element<I, Tuple>,
find_if<Tuple, UnaryPred, I+1, N>
>
{};
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t N
>
struct find_if<Tuple, UnaryPred, N, N>
{
typedef detail::null_type type;
};
// is_found
// Returns true if a type T (the result of find_if) was found.
template <typename T>
struct is_found
: std::integral_constant
<
bool,
! std::is_same<T, detail::null_type>::value
>
{};
// is_not_found
// Returns true if a type T (the result of find_if) was not found.
template <typename T>
struct is_not_found
: std::is_same<T, detail::null_type>
{};
// exists_if
// Returns true if search for element meeting UnaryPred can be found.
template <typename Tuple, template <typename> class UnaryPred>
struct exists_if
: is_found<typename find_if<Tuple, UnaryPred>::type>
{};
// push_back
// A utility used to create a type/object of a Tuple containing
// all types/objects stored in another Tuple plus additional one.
template <typename Tuple,
typename T,
std::size_t I = 0,
std::size_t N = size<Tuple>::value>
struct push_back_bt
{
typedef
boost::tuples::cons<
typename element<I, Tuple>::type,
typename push_back_bt<Tuple, T, I+1, N>::type
> type;
static type apply(Tuple const& tup, T const& t)
{
return
type(
geometry::tuples::get<I>(tup),
push_back_bt<Tuple, T, I+1, N>::apply(tup, t)
);
}
};
template <typename Tuple, typename T, std::size_t N>
struct push_back_bt<Tuple, T, N, N>
{
typedef boost::tuples::cons<T, boost::tuples::null_type> type;
static type apply(Tuple const&, T const& t)
{
return type(t, boost::tuples::null_type());
}
};
template <typename Tuple, typename T>
struct push_back
: push_back_bt<Tuple, T>
{};
template <typename F, typename S, typename T>
struct push_back<std::pair<F, S>, T>
{
typedef std::tuple<F, S, T> type;
static type apply(std::pair<F, S> const& p, T const& t)
{
return type(p.first, p.second, t);
}
static type apply(std::pair<F, S> && p, T const& t)
{
return type(std::move(p.first), std::move(p.second), t);
}
static type apply(std::pair<F, S> && p, T && t)
{
return type(std::move(p.first), std::move(p.second), std::move(t));
}
};
template <typename Is, typename Tuple, typename T>
struct push_back_st;
template <std::size_t ...Is, typename ...Ts, typename T>
struct push_back_st<std::index_sequence<Is...>, std::tuple<Ts...>, T>
{
typedef std::tuple<Ts..., T> type;
static type apply(std::tuple<Ts...> const& tup, T const& t)
{
return type(std::get<Is>(tup)..., t);
}
static type apply(std::tuple<Ts...> && tup, T const& t)
{
return type(std::move(std::get<Is>(tup))..., t);
}
static type apply(std::tuple<Ts...> && tup, T && t)
{
return type(std::move(std::get<Is>(tup))..., std::move(t));
}
};
template <typename ...Ts, typename T>
struct push_back<std::tuple<Ts...>, T>
: push_back_st
<
std::make_index_sequence<sizeof...(Ts)>,
std::tuple<Ts...>,
T
>
{};
}}} // namespace boost::geometry::tuples
#endif // BOOST_GEOMETRY_UTIL_TUPLES_HPP

View File

@@ -0,0 +1,242 @@
// Boost.Geometry
// Copyright (c) 2020, 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_TYPE_TRAITS_HPP
#define BOOST_GEOMETRY_UTIL_TYPE_TRAITS_HPP
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
namespace util
{
template <typename T>
struct is_geometry
: bool_constant<! std::is_void<typename tag<T>::type>::value>
{};
template <typename T>
struct is_not_geometry
: std::is_void<typename tag<T>::type>
{};
template <typename T>
struct is_point
: std::is_same<point_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_point
: std::is_same<multi_point_tag, typename tag<T>::type>
{};
template <typename T>
struct is_pointlike
: std::is_base_of<pointlike_tag, typename tag<T>::type>
{};
template <typename T>
struct is_segment
: std::is_same<segment_tag, typename tag<T>::type>
{};
template <typename T>
struct is_linestring
: std::is_same<linestring_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_linestring
: std::is_same<multi_linestring_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polylinear
: std::is_base_of<polylinear_tag, typename tag<T>::type>
{};
template <typename T>
struct is_linear
: std::is_base_of<linear_tag, typename tag<T>::type>
{};
template <typename T>
struct is_box
: std::is_same<box_tag, typename tag<T>::type>
{};
template <typename T>
struct is_ring
: std::is_same<ring_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polygon
: std::is_same<polygon_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_polygon
: std::is_same<multi_polygon_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polygonal
: std::is_base_of<polygonal_tag, typename tag<T>::type>
{};
template <typename T>
struct is_areal
: std::is_base_of<areal_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polysegmental
: bool_constant<is_polylinear<T>::value || is_polygonal<T>::value>
{};
template <typename T>
struct is_multi
: std::is_base_of<multi_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_element
: bool_constant<is_point<T>::value || is_linestring<T>::value || is_polygon<T>::value>
{};
template <typename T>
struct is_single
: std::is_base_of<single_tag, typename tag<T>::type>
{};
template <typename Geometry, typename T = void>
struct enable_if_point
: std::enable_if<is_point<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_point_t = typename enable_if_point<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_multi_point
: std::enable_if<is_multi_point<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_multi_point_t = typename enable_if_multi_point<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_pointlike
: std::enable_if<is_pointlike<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_pointlike_t = typename enable_if_pointlike<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_segment
: std::enable_if<is_segment<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_segment_t = typename enable_if_segment<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polylinear
: std::enable_if<is_polylinear<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polylinear_t = typename enable_if_polylinear<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_linear
: std::enable_if<is_linear<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_linear_t = typename enable_if_linear<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_box
: std::enable_if<is_box<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_box_t = typename enable_if_box<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polygonal
: std::enable_if<is_polygonal<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polygonal_t = typename enable_if_polygonal<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_areal
: std::enable_if<is_areal<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_areal_t = typename enable_if_areal<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polysegmental
: std::enable_if<is_polysegmental<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polysegmental_t = typename enable_if_polysegmental<Geometry, T>::type;
} // namespace util
// Deprecated utilities, defined for backward compatibility but might be
// removed in the future.
/*!
\brief Meta-function defining "true" for areal types (box, (multi)polygon, ring),
\note Used for tag dispatching and meta-function finetuning
\note Also a "ring" has areal properties within Boost.Geometry
\ingroup core
*/
using util::is_areal;
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DETAIL_HPP

View File

@@ -0,0 +1,186 @@
// Boost.Geometry
// Copyright (c) 2020, 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_TYPE_TRAITS_STD_HPP
#define BOOST_GEOMETRY_UTIL_TYPE_TRAITS_STD_HPP
#include <cstddef>
#include <type_traits>
namespace boost { namespace geometry
{
namespace util
{
// C++17
template <bool B>
using bool_constant = std::integral_constant<bool, B>;
// non-standard
template <int I>
using int_constant = std::integral_constant<int, I>;
// non-standard
template <std::size_t I>
using index_constant = std::integral_constant<std::size_t, I>;
// non-standard
template <std::size_t S>
using size_constant = std::integral_constant<std::size_t, S>;
// C++17
template <typename ...>
struct conjunction
: std::true_type
{};
template<typename Trait>
struct conjunction<Trait>
: Trait
{};
template <typename Trait, typename ...Traits>
struct conjunction<Trait, Traits...>
: std::conditional_t<Trait::value, conjunction<Traits...>, Trait>
{};
// C++17
template <typename ...>
struct disjunction
: std::false_type
{};
template <typename Trait>
struct disjunction<Trait>
: Trait
{};
template <typename Trait, typename ...Traits>
struct disjunction<Trait, Traits...>
: std::conditional_t<Trait::value, Trait, disjunction<Traits...>>
{};
// C++17
template <typename Trait>
struct negation
: bool_constant<!Trait::value>
{};
// non-standard
/*
template <typename ...Traits>
using and_ = conjunction<Traits...>;
template <typename ...Traits>
using or_ = disjunction<Traits...>;
template <typename Trait>
using not_ = negation<Trait>;
*/
// C++20
template <typename T>
struct remove_cvref
{
using type = std::remove_cv_t<std::remove_reference_t<T>>;
};
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
// non-standard
template <typename T>
struct remove_cref
{
using type = std::remove_const_t<std::remove_reference_t<T>>;
};
template <typename T>
using remove_cref_t = typename remove_cref<T>::type;
// non-standard
template <typename T>
struct remove_cptrref
{
using type = std::remove_const_t
<
std::remove_pointer_t<std::remove_reference_t<T>>
>;
};
template <typename T>
using remove_cptrref_t = typename remove_cptrref<T>::type;
// non-standard
template <typename From, typename To>
struct transcribe_const
{
using type = std::conditional_t
<
std::is_const<std::remove_reference_t<From>>::value,
std::add_const_t<To>,
To
>;
};
template <typename From, typename To>
using transcribe_const_t = typename transcribe_const<From, To>::type;
} // namespace util
// Deprecated utilities, defined for backward compatibility but might be
// removed in the future.
/*!
\brief Meta-function to define a const or non const type
\ingroup utility
\details If the boolean template parameter is true, the type parameter
will be defined as const, otherwise it will be defined as it was.
This meta-function is used to have one implementation for both
const and non const references
\note This traits class is completely independant from Boost.Geometry
and might be a separate addition to Boost
\note Used in a.o. for_each, interior_rings, exterior_ring
\par Example
\code
void foo(typename add_const_if_c<IsConst, Point>::type& point)
\endcode
*/
template <bool IsConst, typename Type>
struct add_const_if_c
{
typedef std::conditional_t
<
IsConst,
Type const,
Type
> type;
};
namespace util
{
template <typename T>
using bare_type = remove_cptrref<T>;
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_TYPE_TRAITS_STD_HPP