mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-06 15:37:52 +00:00
Added thirdparty: boost library
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 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
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
|
||||
#define BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Other implementations can be found in the history of this file.
|
||||
// The discussion and benchmarks can be found here:
|
||||
// https://github.com/boostorg/geometry/pull/827
|
||||
|
||||
// O(logN) version 2
|
||||
|
||||
template <std::size_t N>
|
||||
struct for_each_index_impl2
|
||||
{
|
||||
static const std::size_t N1 = N / 2;
|
||||
static const std::size_t N2 = N - N1;
|
||||
|
||||
template <std::size_t Offset, typename UnaryFunction>
|
||||
constexpr static inline void apply(UnaryFunction& function)
|
||||
{
|
||||
for_each_index_impl2<N1>::template apply<Offset>(function);
|
||||
for_each_index_impl2<N2>::template apply<Offset + N1>(function);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct for_each_index_impl2<3>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryFunction>
|
||||
constexpr static inline void apply(UnaryFunction& function)
|
||||
{
|
||||
function(util::index_constant<Offset>());
|
||||
function(util::index_constant<Offset + 1>());
|
||||
function(util::index_constant<Offset + 2>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct for_each_index_impl2<2>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryFunction>
|
||||
constexpr static inline void apply(UnaryFunction& function)
|
||||
{
|
||||
function(util::index_constant<Offset>());
|
||||
function(util::index_constant<Offset + 1>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct for_each_index_impl2<1>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryFunction>
|
||||
constexpr static inline void apply(UnaryFunction& function)
|
||||
{
|
||||
function(util::index_constant<Offset>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct for_each_index_impl2<0>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryFunction>
|
||||
constexpr static inline void apply(UnaryFunction& )
|
||||
{}
|
||||
};
|
||||
|
||||
// Interface
|
||||
|
||||
template <std::size_t N, typename UnaryFunction>
|
||||
constexpr inline UnaryFunction for_each_index(UnaryFunction function)
|
||||
{
|
||||
for_each_index_impl2
|
||||
<
|
||||
N
|
||||
>::template apply<0>(function);
|
||||
return function;
|
||||
}
|
||||
|
||||
template <typename Geometry, typename UnaryFunction>
|
||||
constexpr inline UnaryFunction for_each_dimension(UnaryFunction function)
|
||||
{
|
||||
for_each_index_impl2
|
||||
<
|
||||
geometry::dimension<Geometry>::value
|
||||
>::template apply<0>(function);
|
||||
return function;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// O(logN) version 2
|
||||
|
||||
template <std::size_t N>
|
||||
struct all_indexes_of_impl2
|
||||
{
|
||||
static const std::size_t N1 = N / 2;
|
||||
static const std::size_t N2 = N - N1;
|
||||
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return all_indexes_of_impl2<N1>::template apply<Offset>(predicate)
|
||||
&& all_indexes_of_impl2<N2>::template apply<Offset + N1>(predicate);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct all_indexes_of_impl2<3>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return predicate(util::index_constant<Offset>())
|
||||
&& predicate(util::index_constant<Offset + 1>())
|
||||
&& predicate(util::index_constant<Offset + 2>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct all_indexes_of_impl2<2>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return predicate(util::index_constant<Offset>())
|
||||
&& predicate(util::index_constant<Offset + 1>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct all_indexes_of_impl2<1>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return predicate(util::index_constant<Offset>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct all_indexes_of_impl2<0>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Interface
|
||||
|
||||
template <std::size_t N, typename UnaryPredicate>
|
||||
constexpr inline bool all_indexes_of(UnaryPredicate predicate)
|
||||
{
|
||||
return all_indexes_of_impl2<N>::template apply<0>(predicate);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename UnaryPredicate>
|
||||
constexpr inline bool all_dimensions_of(UnaryPredicate predicate)
|
||||
{
|
||||
return all_indexes_of_impl2
|
||||
<
|
||||
geometry::dimension<Geometry>::value
|
||||
>::template apply<0>(predicate);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// O(logN) version 2
|
||||
|
||||
template <std::size_t N>
|
||||
struct any_index_of_impl2
|
||||
{
|
||||
static const std::size_t N1 = N / 2;
|
||||
static const std::size_t N2 = N - N1;
|
||||
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return any_index_of_impl2<N1>::template apply<Offset>(predicate)
|
||||
|| any_index_of_impl2<N2>::template apply<Offset + N1>(predicate);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct any_index_of_impl2<3>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return predicate(util::index_constant<Offset>())
|
||||
|| predicate(util::index_constant<Offset + 1>())
|
||||
|| predicate(util::index_constant<Offset + 2>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct any_index_of_impl2<2>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return predicate(util::index_constant<Offset>())
|
||||
|| predicate(util::index_constant<Offset + 1>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct any_index_of_impl2<1>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& predicate)
|
||||
{
|
||||
return predicate(util::index_constant<Offset>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct any_index_of_impl2<0>
|
||||
{
|
||||
template <std::size_t Offset, typename UnaryPredicate>
|
||||
constexpr static inline bool apply(UnaryPredicate& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Interface
|
||||
|
||||
template <std::size_t N, typename UnaryPredicate>
|
||||
constexpr inline bool any_index_of(UnaryPredicate predicate)
|
||||
{
|
||||
return any_index_of_impl2<N>::template apply<0>(predicate);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename UnaryPredicate>
|
||||
constexpr inline bool any_dimension_of(UnaryPredicate predicate)
|
||||
{
|
||||
return any_index_of_impl2
|
||||
<
|
||||
geometry::dimension<Geometry>::value
|
||||
>::template apply<0>(predicate);
|
||||
}
|
||||
|
||||
template <std::size_t N, typename UnaryPredicate>
|
||||
constexpr inline bool none_index_of(UnaryPredicate predicate)
|
||||
{
|
||||
return ! any_index_of_impl2<N>::template apply<0>(predicate);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename UnaryPredicate>
|
||||
constexpr inline bool none_dimension_of(UnaryPredicate predicate)
|
||||
{
|
||||
return ! any_index_of_impl2
|
||||
<
|
||||
geometry::dimension<Geometry>::value
|
||||
>::template apply<0>(predicate);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
|
||||
+25
@@ -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
|
||||
+176
@@ -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
|
||||
+46
@@ -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
|
||||
+98
@@ -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
|
||||
+111
@@ -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
|
||||
+44
@@ -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
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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_CONSTEXPR_HPP
|
||||
#define BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
|
||||
#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
|
||||
|
||||
#define BOOST_GEOMETRY_CONSTEXPR(CONDITION) constexpr (CONDITION)
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_GEOMETRY_CONSTEXPR(CONDITION) (BOOST_GEOMETRY_CONDITION(CONDITION))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
|
||||
+54
@@ -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
|
||||
+82
@@ -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
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
|
||||
#define BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/size_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Utility function to implement a Kotlin like range based for loop
|
||||
template <typename Container, typename Function>
|
||||
inline void for_each_with_index(Container const& container, Function func)
|
||||
{
|
||||
typename boost::range_size<Container>::type index = 0;
|
||||
for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
|
||||
{
|
||||
func(index, *it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container, typename Function>
|
||||
inline void for_each_with_index(Container& container, Function func)
|
||||
{
|
||||
typename boost::range_size<Container>::type index = 0;
|
||||
for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
|
||||
{
|
||||
func(index, *it);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
|
||||
+56
@@ -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
|
||||
+98
@@ -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
|
||||
+56
@@ -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
|
||||
+48
@@ -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
|
||||
+966
@@ -0,0 +1,966 @@
|
||||
// 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-2022.
|
||||
// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_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;
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void multiply_epsilon(E const& multiplier)
|
||||
{
|
||||
factor *= multiplier;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void multiply_epsilon(T const& ) {}
|
||||
};
|
||||
|
||||
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(T const& 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));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool IsIntegral = std::is_integral<T>::value>
|
||||
struct divide
|
||||
{
|
||||
static inline T apply(T const& n, T const& d)
|
||||
{
|
||||
return n / d;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct divide<T, true>
|
||||
{
|
||||
static inline T apply(T const& n, T const& d)
|
||||
{
|
||||
return n == 0 ? 0
|
||||
: n < 0
|
||||
? (d < 0 ? (n + (-d + 1) / 2) / d + 1
|
||||
: (n + ( d + 1) / 2) / d - 1 )
|
||||
: (d < 0 ? (n - (-d + 1) / 2) / d - 1
|
||||
: (n - ( d + 1) / 2) / d + 1 )
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
} // 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;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Wraps an angle in the range [-pi, +pi] (both inclusive)
|
||||
*/
|
||||
template <typename T>
|
||||
inline T wrap_azimuth_in_radian(T const& azimuth)
|
||||
{
|
||||
static T const pi = geometry::math::pi<T>();
|
||||
static T const two_pi = geometry::math::two_pi<T>();
|
||||
T result = azimuth;
|
||||
while (result > pi) { result -= two_pi; }
|
||||
while (result < -pi) { result += two_pi; }
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
#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 Short utility to divide. If the division is integer, it rounds the division
|
||||
to the nearest value, without using floating point calculations
|
||||
\ingroup utility
|
||||
*/
|
||||
template <typename T>
|
||||
inline T divide(T const& n, T const& d)
|
||||
{
|
||||
return detail::divide<T>::apply(n, d);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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° = cos 81° = − sin 123456789°.
|
||||
If x = −0, then \e sinx = −0; this is the only case where
|
||||
−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 = math::mod(x, T(360));
|
||||
T const quotient = std::floor(remainder / T(90) + T(0.5));
|
||||
remainder -= T(90) * quotient;
|
||||
|
||||
// Convert to radians.
|
||||
remainder *= d2r<T>();
|
||||
|
||||
T const s = sin(remainder);
|
||||
T const 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 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
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2022, 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::larger_or_equals(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
|
||||
+510
@@ -0,0 +1,510 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2015-2022, 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::larger_or_equals(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
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
|
||||
#define BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
|
||||
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Flag for iterating a reversible_view in forward or reverse direction
|
||||
\ingroup views
|
||||
*/
|
||||
enum iterate_direction { iterate_forward, iterate_reverse };
|
||||
|
||||
|
||||
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
|
||||
+78
@@ -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
|
||||
+633
@@ -0,0 +1,633 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Contributed and/or modified by Tinko Bartels,
|
||||
// as part of Google Summer of Code 2019 program.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, 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_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
|
||||
#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
|
||||
|
||||
#include<numeric>
|
||||
#include<cmath>
|
||||
#include<limits>
|
||||
#include<array>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
// The following code is based on "Adaptive Precision Floating-Point Arithmetic
|
||||
// and Fast Robust Geometric Predicates" by Richard Shewchuk,
|
||||
// J. Discrete Comput Geom (1997) 18: 305. https://doi.org/10.1007/PL00009321
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace detail { namespace precise_math
|
||||
{
|
||||
|
||||
// See Theorem 6, page 6
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline std::array<RealNumber, 2> fast_two_sum(RealNumber const a,
|
||||
RealNumber const b)
|
||||
{
|
||||
RealNumber x = a + b;
|
||||
RealNumber b_virtual = x - a;
|
||||
return {{x, b - b_virtual}};
|
||||
}
|
||||
|
||||
// See Theorem 7, page 7 - 8
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline std::array<RealNumber, 2> two_sum(RealNumber const a,
|
||||
RealNumber const b)
|
||||
{
|
||||
RealNumber x = a + b;
|
||||
RealNumber b_virtual = x - a;
|
||||
RealNumber a_virtual = x - b_virtual;
|
||||
RealNumber b_roundoff = b - b_virtual;
|
||||
RealNumber a_roundoff = a - a_virtual;
|
||||
RealNumber y = a_roundoff + b_roundoff;
|
||||
return {{ x, y }};
|
||||
}
|
||||
|
||||
// See bottom of page 8
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline RealNumber two_diff_tail(RealNumber const a,
|
||||
RealNumber const b,
|
||||
RealNumber const x)
|
||||
{
|
||||
RealNumber b_virtual = a - x;
|
||||
RealNumber a_virtual = x + b_virtual;
|
||||
RealNumber b_roundoff = b_virtual - b;
|
||||
RealNumber a_roundoff = a - a_virtual;
|
||||
return a_roundoff + b_roundoff;
|
||||
}
|
||||
|
||||
// see bottom of page 8
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline std::array<RealNumber, 2> two_diff(RealNumber const a,
|
||||
RealNumber const b)
|
||||
{
|
||||
RealNumber x = a - b;
|
||||
RealNumber y = two_diff_tail(a, b, x);
|
||||
return {{ x, y }};
|
||||
}
|
||||
|
||||
// see theorem 18, page 19
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline RealNumber two_product_tail(RealNumber const a,
|
||||
RealNumber const b,
|
||||
RealNumber const x)
|
||||
{
|
||||
return std::fma(a, b, -x);
|
||||
}
|
||||
|
||||
// see theorem 18, page 19
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline std::array<RealNumber, 2> two_product(RealNumber const a,
|
||||
RealNumber const b)
|
||||
{
|
||||
RealNumber x = a * b;
|
||||
RealNumber y = two_product_tail(a, b, x);
|
||||
return {{ x , y }};
|
||||
}
|
||||
|
||||
// see theorem 12, figure 7, page 11 - 12,
|
||||
// this is the 2 by 2 case for the corresponding diff-method
|
||||
// note that this method takes input in descending order of magnitude and
|
||||
// returns components in ascending order of magnitude
|
||||
template
|
||||
<
|
||||
typename RealNumber
|
||||
>
|
||||
inline std::array<RealNumber, 4> two_two_expansion_diff(
|
||||
std::array<RealNumber, 2> const a,
|
||||
std::array<RealNumber, 2> const b)
|
||||
{
|
||||
std::array<RealNumber, 4> h;
|
||||
std::array<RealNumber, 2> Qh = two_diff(a[1], b[1]);
|
||||
h[0] = Qh[1];
|
||||
Qh = two_sum( a[0], Qh[0] );
|
||||
RealNumber _j = Qh[0];
|
||||
Qh = two_diff(Qh[1], b[0]);
|
||||
h[1] = Qh[1];
|
||||
Qh = two_sum( _j, Qh[0] );
|
||||
h[2] = Qh[1];
|
||||
h[3] = Qh[0];
|
||||
return h;
|
||||
}
|
||||
|
||||
// see theorem 13, figure 8. This implementation uses zero elimination as
|
||||
// suggested on page 17, second to last paragraph. Returns the number of
|
||||
// non-zero components in the result and writes the result to h.
|
||||
// the merger into a single sequence g is done implicitly
|
||||
template
|
||||
<
|
||||
typename RealNumber,
|
||||
std::size_t InSize1,
|
||||
std::size_t InSize2,
|
||||
std::size_t OutSize
|
||||
>
|
||||
inline int fast_expansion_sum_zeroelim(
|
||||
std::array<RealNumber, InSize1> const& e,
|
||||
std::array<RealNumber, InSize2> const& f,
|
||||
std::array<RealNumber, OutSize> & h,
|
||||
int m = InSize1,
|
||||
int n = InSize2)
|
||||
{
|
||||
std::array<RealNumber, 2> Qh;
|
||||
int i_e = 0;
|
||||
int i_f = 0;
|
||||
int i_h = 0;
|
||||
if (std::abs(f[0]) > std::abs(e[0]))
|
||||
{
|
||||
Qh[0] = e[i_e++];
|
||||
}
|
||||
else
|
||||
{
|
||||
Qh[0] = f[i_f++];
|
||||
}
|
||||
i_h = 0;
|
||||
if ((i_e < m) && (i_f < n))
|
||||
{
|
||||
if (std::abs(f[i_f]) > std::abs(e[i_e]))
|
||||
{
|
||||
Qh = fast_two_sum(e[i_e++], Qh[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Qh = fast_two_sum(f[i_f++], Qh[0]);
|
||||
}
|
||||
if (Qh[1] != 0.0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
while ((i_e < m) && (i_f < n))
|
||||
{
|
||||
if (std::abs(f[i_f]) > std::abs(e[i_e]))
|
||||
{
|
||||
Qh = two_sum(Qh[0], e[i_e++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Qh = two_sum(Qh[0], f[i_f++]);
|
||||
}
|
||||
if (Qh[1] != 0.0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i_e < m)
|
||||
{
|
||||
Qh = two_sum(Qh[0], e[i_e++]);
|
||||
if (Qh[1] != 0.0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
}
|
||||
while (i_f < n)
|
||||
{
|
||||
Qh = two_sum(Qh[0], f[i_f++]);
|
||||
if (Qh[1] != 0.0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
}
|
||||
if ((Qh[0] != 0.0) || (i_h == 0))
|
||||
{
|
||||
h[i_h++] = Qh[0];
|
||||
}
|
||||
return i_h;
|
||||
}
|
||||
|
||||
// see theorem 19, figure 13, page 20 - 21. This implementation uses zero
|
||||
// elimination as suggested on page 17, second to last paragraph. Returns the
|
||||
// number of non-zero components in the result and writes the result to h.
|
||||
template
|
||||
<
|
||||
typename RealNumber,
|
||||
std::size_t InSize
|
||||
>
|
||||
inline int scale_expansion_zeroelim(
|
||||
std::array<RealNumber, InSize> const& e,
|
||||
RealNumber const b,
|
||||
std::array<RealNumber, 2 * InSize> & h,
|
||||
int e_non_zeros = InSize)
|
||||
{
|
||||
std::array<RealNumber, 2> Qh = two_product(e[0], b);
|
||||
int i_h = 0;
|
||||
if (Qh[1] != 0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
for (int i_e = 1; i_e < e_non_zeros; i_e++)
|
||||
{
|
||||
std::array<RealNumber, 2> Tt = two_product(e[i_e], b);
|
||||
Qh = two_sum(Qh[0], Tt[1]);
|
||||
if (Qh[1] != 0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
Qh = fast_two_sum(Tt[0], Qh[0]);
|
||||
if (Qh[1] != 0)
|
||||
{
|
||||
h[i_h++] = Qh[1];
|
||||
}
|
||||
}
|
||||
if ((Qh[0] != 0.0) || (i_h == 0))
|
||||
{
|
||||
h[i_h++] = Qh[0];
|
||||
}
|
||||
return i_h;
|
||||
}
|
||||
|
||||
template<typename RealNumber>
|
||||
struct vec2d
|
||||
{
|
||||
RealNumber x;
|
||||
RealNumber y;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename RealNumber,
|
||||
std::size_t Robustness
|
||||
>
|
||||
inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
|
||||
vec2d<RealNumber> const& p2,
|
||||
vec2d<RealNumber> const& p3,
|
||||
std::array<RealNumber, 2>& t1,
|
||||
std::array<RealNumber, 2>& t2,
|
||||
std::array<RealNumber, 2>& t3,
|
||||
std::array<RealNumber, 2>& t4,
|
||||
std::array<RealNumber, 2>& t5_01,
|
||||
std::array<RealNumber, 2>& t6_01,
|
||||
RealNumber const& magnitude)
|
||||
{
|
||||
t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]);
|
||||
t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]);
|
||||
std::array<RealNumber, 4> tA_03 = two_two_expansion_diff(t5_01, t6_01);
|
||||
RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast<RealNumber>(0));
|
||||
if (BOOST_GEOMETRY_CONDITION(Robustness == 1))
|
||||
{
|
||||
return det;
|
||||
}
|
||||
// see p.39, mind the different definition of epsilon for error bound
|
||||
RealNumber B_relative_bound =
|
||||
(1 + 3 * std::numeric_limits<RealNumber>::epsilon())
|
||||
* std::numeric_limits<RealNumber>::epsilon();
|
||||
RealNumber absolute_bound = B_relative_bound * magnitude;
|
||||
if (std::abs(det) >= absolute_bound)
|
||||
{
|
||||
return det; //B estimate
|
||||
}
|
||||
t1[1] = two_diff_tail(p1.x, p3.x, t1[0]);
|
||||
t2[1] = two_diff_tail(p2.y, p3.y, t2[0]);
|
||||
t3[1] = two_diff_tail(p1.y, p3.y, t3[0]);
|
||||
t4[1] = two_diff_tail(p2.x, p3.x, t4[0]);
|
||||
|
||||
if ((t1[1] == 0) && (t3[1] == 0) && (t2[1] == 0) && (t4[1] == 0))
|
||||
{
|
||||
return det; //If all tails are zero, there is noething else to compute
|
||||
}
|
||||
RealNumber sub_bound =
|
||||
(1.5 + 2 * std::numeric_limits<RealNumber>::epsilon())
|
||||
* std::numeric_limits<RealNumber>::epsilon();
|
||||
// see p.39, mind the different definition of epsilon for error bound
|
||||
RealNumber C_relative_bound =
|
||||
(2.25 + 8 * std::numeric_limits<RealNumber>::epsilon())
|
||||
* std::numeric_limits<RealNumber>::epsilon()
|
||||
* std::numeric_limits<RealNumber>::epsilon();
|
||||
absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det);
|
||||
det += (t1[0] * t2[1] + t2[0] * t1[1]) - (t3[0] * t4[1] + t4[0] * t3[1]);
|
||||
if (Robustness == 2 || std::abs(det) >= absolute_bound)
|
||||
{
|
||||
return det; //C estimate
|
||||
}
|
||||
std::array<RealNumber, 8> D_left;
|
||||
int D_left_nz;
|
||||
{
|
||||
std::array<RealNumber, 2> t5_23 = two_product(t1[1], t2[0]);
|
||||
std::array<RealNumber, 2> t6_23 = two_product(t3[1], t4[0]);
|
||||
std::array<RealNumber, 4> tA_47 = two_two_expansion_diff(t5_23, t6_23);
|
||||
D_left_nz = fast_expansion_sum_zeroelim(tA_03, tA_47, D_left);
|
||||
}
|
||||
std::array<RealNumber, 8> D_right;
|
||||
int D_right_nz;
|
||||
{
|
||||
std::array<RealNumber, 2> t5_45 = two_product(t1[0], t2[1]);
|
||||
std::array<RealNumber, 2> t6_45 = two_product(t3[0], t4[1]);
|
||||
std::array<RealNumber, 4> tA_8_11 = two_two_expansion_diff(t5_45, t6_45);
|
||||
std::array<RealNumber, 2> t5_67 = two_product(t1[1], t2[1]);
|
||||
std::array<RealNumber, 2> t6_67 = two_product(t3[1], t4[1]);
|
||||
std::array<RealNumber, 4> tA_12_15 = two_two_expansion_diff(t5_67, t6_67);
|
||||
D_right_nz = fast_expansion_sum_zeroelim(tA_8_11, tA_12_15, D_right);
|
||||
}
|
||||
std::array<RealNumber, 16> D;
|
||||
int D_nz = fast_expansion_sum_zeroelim(D_left, D_right, D, D_left_nz, D_right_nz);
|
||||
// only return component of highest magnitude because we mostly care about the sign.
|
||||
return(D[D_nz - 1]);
|
||||
}
|
||||
|
||||
// see page 38, Figure 21 for the calculations, notation follows the notation
|
||||
// in the figure.
|
||||
template
|
||||
<
|
||||
typename RealNumber,
|
||||
std::size_t Robustness = 3,
|
||||
typename EpsPolicy
|
||||
>
|
||||
inline RealNumber orient2d(vec2d<RealNumber> const& p1,
|
||||
vec2d<RealNumber> const& p2,
|
||||
vec2d<RealNumber> const& p3,
|
||||
EpsPolicy& eps_policy)
|
||||
{
|
||||
std::array<RealNumber, 2> t1, t2, t3, t4;
|
||||
t1[0] = p1.x - p3.x;
|
||||
t2[0] = p2.y - p3.y;
|
||||
t3[0] = p1.y - p3.y;
|
||||
t4[0] = p2.x - p3.x;
|
||||
|
||||
eps_policy = EpsPolicy(t1[0], t2[0], t3[0], t4[0]);
|
||||
|
||||
std::array<RealNumber, 2> t5_01, t6_01;
|
||||
t5_01[0] = t1[0] * t2[0];
|
||||
t6_01[0] = t3[0] * t4[0];
|
||||
RealNumber det = t5_01[0] - t6_01[0];
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(Robustness == 0))
|
||||
{
|
||||
return det;
|
||||
}
|
||||
|
||||
RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]);
|
||||
|
||||
// see p.39, mind the different definition of epsilon for error bound
|
||||
RealNumber const A_relative_bound =
|
||||
(1.5 + 4 * std::numeric_limits<RealNumber>::epsilon())
|
||||
* std::numeric_limits<RealNumber>::epsilon();
|
||||
RealNumber absolute_bound = A_relative_bound * magnitude;
|
||||
if ( std::abs(det) >= absolute_bound )
|
||||
{
|
||||
return det; //A estimate
|
||||
}
|
||||
|
||||
if ( (t5_01[0] > 0 && t6_01[0] <= 0) || (t5_01[0] < 0 && t6_01[0] >= 0) )
|
||||
{
|
||||
//if diagonal and antidiagonal have different sign, the sign of det is
|
||||
//obvious
|
||||
return det;
|
||||
}
|
||||
return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4,
|
||||
t5_01, t6_01, magnitude);
|
||||
}
|
||||
|
||||
// This method adaptively computes increasingly precise approximations of the following
|
||||
// determinant using Laplace expansion along the last column.
|
||||
// det A =
|
||||
// | p1_x - p4_x p1_y - p4_y ( p1_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 |
|
||||
// | p2_x - p4_x p2_y - p4_y ( p2_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 |
|
||||
// | p3_x - p4_x p3_y - p4_y ( p3_x - p4_x ) ^ 2 + ( p3_y - p4_y ) ^ 2 |
|
||||
// = a_13 * C_13 + a_23 * C_23 + a_33 * C_33
|
||||
// where a_ij is the i-j-entry and C_ij is the i_j Cofactor
|
||||
|
||||
template
|
||||
<
|
||||
typename RealNumber,
|
||||
std::size_t Robustness = 2
|
||||
>
|
||||
RealNumber incircle(std::array<RealNumber, 2> const& p1,
|
||||
std::array<RealNumber, 2> const& p2,
|
||||
std::array<RealNumber, 2> const& p3,
|
||||
std::array<RealNumber, 2> const& p4)
|
||||
{
|
||||
RealNumber A_11 = p1[0] - p4[0];
|
||||
RealNumber A_21 = p2[0] - p4[0];
|
||||
RealNumber A_31 = p3[0] - p4[0];
|
||||
RealNumber A_12 = p1[1] - p4[1];
|
||||
RealNumber A_22 = p2[1] - p4[1];
|
||||
RealNumber A_32 = p3[1] - p4[1];
|
||||
|
||||
std::array<RealNumber, 2> A_21_x_A_32,
|
||||
A_31_x_A_22,
|
||||
A_31_x_A_12,
|
||||
A_11_x_A_32,
|
||||
A_11_x_A_22,
|
||||
A_21_x_A_12;
|
||||
A_21_x_A_32[0] = A_21 * A_32;
|
||||
A_31_x_A_22[0] = A_31 * A_22;
|
||||
RealNumber A_13 = A_11 * A_11 + A_12 * A_12;
|
||||
|
||||
A_31_x_A_12[0] = A_31 * A_12;
|
||||
A_11_x_A_32[0] = A_11 * A_32;
|
||||
RealNumber A_23 = A_21 * A_21 + A_22 * A_22;
|
||||
|
||||
A_11_x_A_22[0] = A_11 * A_22;
|
||||
A_21_x_A_12[0] = A_21 * A_12;
|
||||
RealNumber A_33 = A_31 * A_31 + A_32 * A_32;
|
||||
|
||||
RealNumber det = A_13 * (A_21_x_A_32[0] - A_31_x_A_22[0])
|
||||
+ A_23 * (A_31_x_A_12[0] - A_11_x_A_32[0])
|
||||
+ A_33 * (A_11_x_A_22[0] - A_21_x_A_12[0]);
|
||||
if(Robustness == 0) return det;
|
||||
|
||||
RealNumber magnitude =
|
||||
(std::abs(A_21_x_A_32[0]) + std::abs(A_31_x_A_22[0])) * A_13
|
||||
+ (std::abs(A_31_x_A_12[0]) + std::abs(A_11_x_A_32[0])) * A_23
|
||||
+ (std::abs(A_11_x_A_22[0]) + std::abs(A_21_x_A_12[0])) * A_33;
|
||||
RealNumber A_relative_bound =
|
||||
(5 + 24 * std::numeric_limits<RealNumber>::epsilon())
|
||||
* std::numeric_limits<RealNumber>::epsilon();
|
||||
RealNumber absolute_bound = A_relative_bound * magnitude;
|
||||
if (std::abs(det) > absolute_bound)
|
||||
{
|
||||
return det;
|
||||
}
|
||||
// (p2_x - p4_x) * (p3_y - p4_y)
|
||||
A_21_x_A_32[1] = two_product_tail(A_21, A_32, A_21_x_A_32[0]);
|
||||
// (p3_x - p4_x) * (p2_y - p4_y)
|
||||
A_31_x_A_22[1] = two_product_tail(A_31, A_22, A_31_x_A_22[0]);
|
||||
// (bx - dx) * (cy - dy) - (cx - dx) * (by - dy)
|
||||
std::array<RealNumber, 4> C_13 = two_two_expansion_diff(A_21_x_A_32, A_31_x_A_22);
|
||||
std::array<RealNumber, 8> C_13_x_A11;
|
||||
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx )
|
||||
int C_13_x_A11_nz = scale_expansion_zeroelim(C_13, A_11, C_13_x_A11);
|
||||
std::array<RealNumber, 16> C_13_x_A11_sq;
|
||||
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) * (ax - dx)
|
||||
int C_13_x_A11_sq_nz = scale_expansion_zeroelim(C_13_x_A11,
|
||||
A_11,
|
||||
C_13_x_A11_sq,
|
||||
C_13_x_A11_nz);
|
||||
|
||||
std::array<RealNumber, 8> C_13_x_A12;
|
||||
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy )
|
||||
int C_13_x_A12_nz = scale_expansion_zeroelim(C_13, A_12, C_13_x_A12);
|
||||
|
||||
std::array<RealNumber, 16> C_13_x_A12_sq;
|
||||
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) * ( ay - dy )
|
||||
int C_13_x_A12_sq_nz = scale_expansion_zeroelim(C_13_x_A12, A_12,
|
||||
C_13_x_A12_sq,
|
||||
C_13_x_A12_nz);
|
||||
|
||||
std::array<RealNumber, 32> A_13_x_C13;
|
||||
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) )
|
||||
// * ( ( ay - dy ) * ( ay - dy ) + ( ax - dx ) * (ax - dx) )
|
||||
int A_13_x_C13_nz = fast_expansion_sum_zeroelim(C_13_x_A11_sq,
|
||||
C_13_x_A12_sq,
|
||||
A_13_x_C13,
|
||||
C_13_x_A11_sq_nz,
|
||||
C_13_x_A12_sq_nz);
|
||||
|
||||
// (cx - dx) * (ay - dy)
|
||||
A_31_x_A_12[1] = two_product_tail(A_31, A_12, A_31_x_A_12[0]);
|
||||
// (ax - dx) * (cy - dy)
|
||||
A_11_x_A_32[1] = two_product_tail(A_11, A_32, A_11_x_A_32[0]);
|
||||
// (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy)
|
||||
std::array<RealNumber, 4> C_23 = two_two_expansion_diff(A_31_x_A_12,
|
||||
A_11_x_A_32);
|
||||
std::array<RealNumber, 8> C_23_x_A_21;
|
||||
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx )
|
||||
int C_23_x_A_21_nz = scale_expansion_zeroelim(C_23, A_21, C_23_x_A_21);
|
||||
std::array<RealNumber, 16> C_23_x_A_21_sq;
|
||||
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) * ( bx - dx )
|
||||
int C_23_x_A_21_sq_nz = scale_expansion_zeroelim(C_23_x_A_21, A_21,
|
||||
C_23_x_A_21_sq,
|
||||
C_23_x_A_21_nz);
|
||||
std::array<RealNumber, 8> C_23_x_A_22;
|
||||
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy )
|
||||
int C_23_x_A_22_nz = scale_expansion_zeroelim(C_23, A_22, C_23_x_A_22);
|
||||
std::array<RealNumber, 16> C_23_x_A_22_sq;
|
||||
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) * ( by - dy )
|
||||
int C_23_x_A_22_sq_nz = scale_expansion_zeroelim(C_23_x_A_22, A_22,
|
||||
C_23_x_A_22_sq,
|
||||
C_23_x_A_22_nz);
|
||||
std::array<RealNumber, 32> A_23_x_C_23;
|
||||
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) )
|
||||
// * ( ( bx - dx ) * ( bx - dx ) + ( by - dy ) * ( by - dy ) )
|
||||
int A_23_x_C_23_nz = fast_expansion_sum_zeroelim(C_23_x_A_21_sq,
|
||||
C_23_x_A_22_sq,
|
||||
A_23_x_C_23,
|
||||
C_23_x_A_21_sq_nz,
|
||||
C_23_x_A_22_sq_nz);
|
||||
|
||||
// (ax - dx) * (by - dy)
|
||||
A_11_x_A_22[1] = two_product_tail(A_11, A_22, A_11_x_A_22[0]);
|
||||
// (bx - dx) * (ay - dy)
|
||||
A_21_x_A_12[1] = two_product_tail(A_21, A_12, A_21_x_A_12[0]);
|
||||
// (ax - dx) * (by - dy) - (bx - dx) * (ay - dy)
|
||||
std::array<RealNumber, 4> C_33 = two_two_expansion_diff(A_11_x_A_22,
|
||||
A_21_x_A_12);
|
||||
std::array<RealNumber, 8> C_33_x_A31;
|
||||
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx )
|
||||
int C_33_x_A31_nz = scale_expansion_zeroelim(C_33, A_31, C_33_x_A31);
|
||||
std::array<RealNumber, 16> C_33_x_A31_sq;
|
||||
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) * ( cx - dx )
|
||||
int C_33_x_A31_sq_nz = scale_expansion_zeroelim(C_33_x_A31, A_31,
|
||||
C_33_x_A31_sq,
|
||||
C_33_x_A31_nz);
|
||||
std::array<RealNumber, 8> C_33_x_A_32;
|
||||
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy )
|
||||
int C_33_x_A_32_nz = scale_expansion_zeroelim(C_33, A_32, C_33_x_A_32);
|
||||
std::array<RealNumber, 16> C_33_x_A_32_sq;
|
||||
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) * ( cy - dy )
|
||||
int C_33_x_A_32_sq_nz = scale_expansion_zeroelim(C_33_x_A_32, A_32,
|
||||
C_33_x_A_32_sq,
|
||||
C_33_x_A_32_nz);
|
||||
|
||||
std::array<RealNumber, 32> A_33_x_C_33;
|
||||
int A_33_x_C_33_nz = fast_expansion_sum_zeroelim(C_33_x_A31_sq,
|
||||
C_33_x_A_32_sq,
|
||||
A_33_x_C_33,
|
||||
C_33_x_A31_sq_nz,
|
||||
C_33_x_A_32_sq_nz);
|
||||
std::array<RealNumber, 64> A_13_x_C13_p_A_13_x_C13;
|
||||
int A_13_x_C13_p_A_13_x_C13_nz = fast_expansion_sum_zeroelim(
|
||||
A_13_x_C13, A_23_x_C_23,
|
||||
A_13_x_C13_p_A_13_x_C13,
|
||||
A_13_x_C13_nz,
|
||||
A_23_x_C_23_nz);
|
||||
std::array<RealNumber, 96> det_expansion;
|
||||
int det_expansion_nz = fast_expansion_sum_zeroelim(
|
||||
A_13_x_C13_p_A_13_x_C13,
|
||||
A_33_x_C_33,
|
||||
det_expansion,
|
||||
A_13_x_C13_p_A_13_x_C13_nz,
|
||||
A_33_x_C_33_nz);
|
||||
|
||||
det = std::accumulate(det_expansion.begin(),
|
||||
det_expansion.begin() + det_expansion_nz,
|
||||
static_cast<RealNumber>(0));
|
||||
if(Robustness == 1) return det;
|
||||
RealNumber B_relative_bound =
|
||||
(2 + 12 * std::numeric_limits<RealNumber>::epsilon())
|
||||
* std::numeric_limits<RealNumber>::epsilon();
|
||||
absolute_bound = B_relative_bound * magnitude;
|
||||
if (std::abs(det) >= absolute_bound)
|
||||
{
|
||||
return det;
|
||||
}
|
||||
RealNumber A_11tail = two_diff_tail(p1[0], p4[0], A_11);
|
||||
RealNumber A_12tail = two_diff_tail(p1[1], p4[1], A_12);
|
||||
RealNumber A_21tail = two_diff_tail(p2[0], p4[0], A_21);
|
||||
RealNumber A_22tail = two_diff_tail(p2[1], p4[1], A_22);
|
||||
RealNumber A_31tail = two_diff_tail(p3[0], p4[0], A_31);
|
||||
RealNumber A_32tail = two_diff_tail(p3[1], p4[1], A_32);
|
||||
if ((A_11tail == 0) && (A_21tail == 0) && (A_31tail == 0)
|
||||
&& (A_12tail == 0) && (A_22tail == 0) && (A_32tail == 0))
|
||||
{
|
||||
return det;
|
||||
}
|
||||
// RealNumber sub_bound = (1.5 + 2.0 * std::numeric_limits<RealNumber>::epsilon())
|
||||
// * std::numeric_limits<RealNumber>::epsilon();
|
||||
// RealNumber C_relative_bound = (11.0 + 72.0 * std::numeric_limits<RealNumber>::epsilon())
|
||||
// * std::numeric_limits<RealNumber>::epsilon()
|
||||
// * std::numeric_limits<RealNumber>::epsilon();
|
||||
//absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det);
|
||||
det += ((A_11 * A_11 + A_12 * A_12) * ((A_21 * A_32tail + A_32 * A_21tail)
|
||||
- (A_22 * A_31tail + A_31 * A_22tail))
|
||||
+ 2 * (A_11 * A_11tail + A_12 * A_12tail) * (A_21 * A_32 - A_22 * A_31))
|
||||
+ ((A_21 * A_21 + A_22 * A_22) * ((A_31 * A_12tail + A_12 * A_31tail)
|
||||
- (A_32 * A_11tail + A_11 * A_32tail))
|
||||
+ 2 * (A_21 * A_21tail + A_22 * A_22tail) * (A_31 * A_12 - A_32 * A_11))
|
||||
+ ((A_31 * A_31 + A_32 * A_32) * ((A_11 * A_22tail + A_22 * A_11tail)
|
||||
- (A_12 * A_21tail + A_21 * A_12tail))
|
||||
+ 2 * (A_31 * A_31tail + A_32 * A_32tail) * (A_11 * A_22 - A_12 * A_21));
|
||||
//if (std::abs(det) >= absolute_bound)
|
||||
//{
|
||||
return det;
|
||||
//}
|
||||
}
|
||||
|
||||
}} // namespace detail::precise_math
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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 <boost/config/header_deprecated.hpp>
|
||||
BOOST_HEADER_DEPRECATED("boost/geometry/core/coordinate_promotion.hpp")
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
|
||||
+299
@@ -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
|
||||
+435
@@ -0,0 +1,435 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#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/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>
|
||||
{};
|
||||
|
||||
template <typename Range, typename T = void>
|
||||
using enable_if_mutable_t = std::enable_if_t
|
||||
<
|
||||
(! std::is_const<std::remove_reference_t<Range>>::value),
|
||||
T
|
||||
>;
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/*!
|
||||
\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_RANGE_CONCEPT_ASSERT((boost::RandomAccessRangeConcept<RandomAccessRange>));
|
||||
BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
|
||||
return boost::begin(rng)
|
||||
+ static_cast<typename boost::range_difference<RandomAccessRange>::type>(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)
|
||||
{
|
||||
return *pos(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>::type
|
||||
front(Range && rng)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
|
||||
return *boost::begin(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));
|
||||
auto it = boost::end(rng);
|
||||
return *(--it);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Short utility to conveniently clear a mutable range.
|
||||
It uses traits::clear<>.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline void clear(Range && rng)
|
||||
{
|
||||
geometry::traits::clear
|
||||
<
|
||||
std::remove_reference_t<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,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline void push_back(Range && rng,
|
||||
typename boost::range_value<Range>::type const& value)
|
||||
{
|
||||
geometry::traits::push_back
|
||||
<
|
||||
std::remove_reference_t<Range>
|
||||
>::apply(rng, value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline void push_back(Range && rng,
|
||||
typename boost::range_value<Range>::type && value)
|
||||
{
|
||||
geometry::traits::push_back
|
||||
<
|
||||
std::remove_reference_t<Range>
|
||||
>::apply(rng, std::move(value));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Short utility to conveniently insert a new element at the end of a mutable range.
|
||||
It uses boost::geometry::traits::emplace_back<>.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
typename ...Args,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline void emplace_back(Range && rng, Args &&... args)
|
||||
{
|
||||
geometry::traits::emplace_back
|
||||
<
|
||||
std::remove_reference_t<Range>
|
||||
>::apply(rng, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Short utility to conveniently resize a mutable range.
|
||||
It uses boost::geometry::traits::resize<>.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline void resize(Range && rng,
|
||||
typename boost::range_size<Range>::type new_size)
|
||||
{
|
||||
geometry::traits::resize
|
||||
<
|
||||
std::remove_reference_t<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,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline void pop_back(Range && rng)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
|
||||
range::resize(rng, boost::size(rng) - 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Short utility to conveniently remove an element from a mutable range.
|
||||
It uses std::move() and resize(). Version taking mutable iterators.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
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;
|
||||
|
||||
std::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::move() and resize(). Version taking non-mutable iterators.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline typename boost::range_iterator<Range>::type
|
||||
erase(Range && rng,
|
||||
typename boost::range_iterator<std::remove_reference_t<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::move() and resize(). Version taking mutable iterators.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
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);
|
||||
|
||||
std::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::move() and resize(). Version taking non-mutable iterators.
|
||||
\ingroup utility
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
detail::enable_if_mutable_t<Range, int> = 0
|
||||
>
|
||||
inline typename boost::range_iterator<Range>::type
|
||||
erase(Range && rng,
|
||||
typename boost::range_iterator<std::remove_reference_t<Range> const>::type cfirst,
|
||||
typename boost::range_iterator<std::remove_reference_t<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=(typename Container::value_type && value)
|
||||
{
|
||||
range::push_back(*container, std::move(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
|
||||
+179
@@ -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
|
||||
+76
@@ -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
|
||||
+48
@@ -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
|
||||
+148
@@ -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
|
||||
+299
@@ -0,0 +1,299 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2020-2023, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// 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 <utility>
|
||||
#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...>>
|
||||
{
|
||||
using type = typename sequence_element<I - 1, type_sequence<Ts...>>::type;
|
||||
};
|
||||
|
||||
template <typename T, typename ...Ts>
|
||||
struct sequence_element<0, type_sequence<T, Ts...>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
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 ...Ts>
|
||||
struct pack_front
|
||||
{
|
||||
static_assert(sizeof...(Ts) > 0, "Parameter pack can not be empty.");
|
||||
};
|
||||
|
||||
template <typename T, typename ... Ts>
|
||||
struct pack_front<T, Ts...>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
// Defines type member for the first type in sequence that satisfies UnaryPred.
|
||||
template
|
||||
<
|
||||
typename Sequence,
|
||||
template <typename> class UnaryPred
|
||||
>
|
||||
struct sequence_find_if {};
|
||||
|
||||
template
|
||||
<
|
||||
typename T, typename ...Ts,
|
||||
template <typename> class UnaryPred
|
||||
>
|
||||
struct sequence_find_if<type_sequence<T, Ts...>, UnaryPred>
|
||||
: std::conditional
|
||||
<
|
||||
UnaryPred<T>::value,
|
||||
T,
|
||||
// TODO: prevent instantiation for the rest of the sequence if value is true
|
||||
typename sequence_find_if<type_sequence<Ts...>, UnaryPred>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <template <typename> class UnaryPred>
|
||||
struct sequence_find_if<type_sequence<>, UnaryPred>
|
||||
{
|
||||
// TODO: This is technically incorrect because void can be stored in a type_sequence
|
||||
using type = void;
|
||||
};
|
||||
|
||||
|
||||
// sequence_merge<type_sequence<A, B>, type_sequence<C, D>>::type is
|
||||
// type_sequence<A, B, C, D>
|
||||
// sequence_merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
|
||||
// integer_sequence<A, B, C, D>
|
||||
template <typename ...Sequences>
|
||||
struct sequence_merge;
|
||||
|
||||
template <typename S>
|
||||
struct sequence_merge<S>
|
||||
{
|
||||
using type = S;
|
||||
};
|
||||
|
||||
template <typename ...T1s, typename ...T2s>
|
||||
struct sequence_merge<type_sequence<T1s...>, type_sequence<T2s...>>
|
||||
{
|
||||
using type = type_sequence<T1s..., T2s...>;
|
||||
};
|
||||
|
||||
template <typename T, T ...I1s, T ...I2s>
|
||||
struct sequence_merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
|
||||
{
|
||||
using type = std::integer_sequence<T, I1s..., I2s...>;
|
||||
};
|
||||
|
||||
template <typename S1, typename S2, typename ...Sequences>
|
||||
struct sequence_merge<S1, S2, Sequences...>
|
||||
{
|
||||
using type = typename sequence_merge
|
||||
<
|
||||
typename sequence_merge<S1, S2>::type,
|
||||
typename sequence_merge<Sequences...>::type
|
||||
>::type;
|
||||
};
|
||||
|
||||
|
||||
// sequence_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 sequence_combine;
|
||||
|
||||
template <typename ...T1s, typename ...T2s>
|
||||
struct sequence_combine<type_sequence<T1s...>, type_sequence<T2s...>>
|
||||
{
|
||||
template <typename T1>
|
||||
using type_sequence_t = type_sequence<type_sequence<T1, T2s>...>;
|
||||
|
||||
using type = typename sequence_merge<type_sequence_t<T1s>...>::type;
|
||||
};
|
||||
|
||||
// sequence_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 sequence_combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
|
||||
{
|
||||
template <T I1>
|
||||
using type_sequence_t = type_sequence<std::integer_sequence<T, I1, I2s>...>;
|
||||
|
||||
using type = typename sequence_merge<type_sequence_t<I1s>...>::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 pack_min_element;
|
||||
|
||||
template
|
||||
<
|
||||
template <typename, typename> class LessPred,
|
||||
typename T
|
||||
>
|
||||
struct pack_min_element<LessPred, T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
template <typename, typename> class LessPred,
|
||||
typename T1, typename T2
|
||||
>
|
||||
struct pack_min_element<LessPred, T1, T2>
|
||||
{
|
||||
using type = std::conditional_t<LessPred<T1, T2>::value, T1, T2>;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
template <typename, typename> class LessPred,
|
||||
typename T1, typename T2, typename ...Ts
|
||||
>
|
||||
struct pack_min_element<LessPred, T1, T2, Ts...>
|
||||
{
|
||||
using type = typename pack_min_element
|
||||
<
|
||||
LessPred,
|
||||
typename pack_min_element<LessPred, T1, T2>::type,
|
||||
typename pack_min_element<LessPred, Ts...>::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 sequence_min_element;
|
||||
|
||||
template
|
||||
<
|
||||
typename ...Ts,
|
||||
template <typename, typename> class LessPred
|
||||
>
|
||||
struct sequence_min_element<type_sequence<Ts...>, LessPred>
|
||||
{
|
||||
using type = typename pack_min_element<LessPred, Ts...>::type;
|
||||
};
|
||||
|
||||
|
||||
// TODO: Since there are two kinds of parameter packs and sequences there probably should be two
|
||||
// versions of sequence_find_if as well as parameter_pack_min_element and sequence_min_element.
|
||||
// Currently these utilities support only types.
|
||||
|
||||
|
||||
} // namespace util
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
|
||||
+759
@@ -0,0 +1,759 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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/array.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 const& eps)
|
||||
{
|
||||
CT const 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;
|
||||
default:
|
||||
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 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] = -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) {
|
||||
BOOST_GEOMETRY_ASSERT((Coeffs::static_size == (SeriesOrder * (SeriesOrder - 1)) / 2));
|
||||
|
||||
CT const 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
|
||||
+91
@@ -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
|
||||
+389
@@ -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
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2020-2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_UTIL_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_segmental
|
||||
: bool_constant<is_linear<T>::value || is_polygonal<T>::value>
|
||||
{};
|
||||
|
||||
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 T>
|
||||
struct is_geometry_collection
|
||||
: std::is_same<geometry_collection_tag, typename tag<T>::type>
|
||||
{};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_dynamic_geometry
|
||||
: std::is_same<dynamic_geometry_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_linestring
|
||||
: std::enable_if<is_linestring<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_linestring_t = typename enable_if_linestring<Geometry, T>::type;
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
struct enable_if_multi_linestring
|
||||
: std::enable_if<is_multi_linestring<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_multi_linestring_t = typename enable_if_multi_linestring<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_ring
|
||||
: std::enable_if<is_ring<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_ring_t = typename enable_if_ring<Geometry, T>::type;
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
struct enable_if_polygon
|
||||
: std::enable_if<is_polygon<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_polygon_t = typename enable_if_polygon<Geometry, T>::type;
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
struct enable_if_multi_polygon
|
||||
: std::enable_if<is_multi_polygon<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_multi_polygon_t = typename enable_if_multi_polygon<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;
|
||||
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
struct enable_if_dynamic_geometry
|
||||
: std::enable_if<is_dynamic_geometry<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_dynamic_geometry_t = typename enable_if_dynamic_geometry<Geometry, T>::type;
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
struct enable_if_geometry_collection
|
||||
: std::enable_if<is_geometry_collection<Geometry>::value, T>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename T = void>
|
||||
using enable_if_geometry_collection_t = typename enable_if_geometry_collection<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
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
// 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;
|
||||
|
||||
|
||||
// non-standard
|
||||
template <typename From, typename To>
|
||||
struct transcribe_reference
|
||||
{
|
||||
using type = std::remove_reference_t<To>;
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
struct transcribe_reference<From &, To>
|
||||
{
|
||||
using type = std::remove_reference_t<To> &;
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
struct transcribe_reference<From &&, To>
|
||||
{
|
||||
using type = std::remove_reference_t<To> &&;
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
using transcribe_reference_t = typename transcribe_reference<From, To>::type;
|
||||
|
||||
|
||||
// non-standard
|
||||
template <typename From, typename To>
|
||||
struct transcribe_cref
|
||||
{
|
||||
using type = transcribe_reference_t<From, transcribe_const_t<From, To>>;
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
using transcribe_cref_t = typename transcribe_cref<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
|
||||
Reference in New Issue
Block a user