Add optional traits::make and use it in cross_product() and make().

This commit is contained in:
Adam Wulkiewicz
2020-08-26 00:47:41 +02:00
parent 0e7972b438
commit dbd0bb62df
11 changed files with 292 additions and 64 deletions

View File

@@ -4,6 +4,9 @@
// 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.
@@ -14,8 +17,12 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
#include <type_traits>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/core/make.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
namespace boost { namespace geometry
@@ -32,12 +39,10 @@ namespace detail { namespace make
\tparam Range \tparam_range_point
\param range \param_range_point
\return The constructed geometry, here: a linestring or a ring
\qbk{distinguish, with a range}
\qbk{
[heading Example]
[make_with_range] [make_with_range_output]
[heading See also]
\* [link geometry.reference.algorithms.assign.assign_points assign]
}
@@ -75,7 +80,12 @@ inline Geometry make_points(Range const& range)
\* [link geometry.reference.algorithms.assign.assign_values_3_2_coordinate_values assign]
}
*/
template <typename Geometry, typename Type>
template
<
typename Geometry,
typename Type,
std::enable_if_t<! traits::make<Geometry>::is_specialized, int> = 0
>
inline Geometry make(Type const& c1, Type const& c2)
{
concepts::check<Geometry>();
@@ -90,6 +100,23 @@ inline Geometry make(Type const& c1, Type const& c2)
return geometry;
}
template
<
typename Geometry,
typename Type,
std::enable_if_t<traits::make<Geometry>::is_specialized, int> = 0
>
constexpr inline Geometry make(Type const& c1, Type const& c2)
{
concepts::check<Geometry>();
// NOTE: This is not fully equivalent to the above because assign uses
// numeric_cast which can't be used here since it's not constexpr.
return traits::make<Geometry>::apply(c1, c2);
}
/*!
\brief Construct a geometry
\ingroup make
@@ -109,7 +136,12 @@ inline Geometry make(Type const& c1, Type const& c2)
\* [link geometry.reference.algorithms.assign.assign_values_4_3_coordinate_values assign]
}
*/
template <typename Geometry, typename Type>
template
<
typename Geometry,
typename Type,
std::enable_if_t<! traits::make<Geometry>::is_specialized, int> = 0
>
inline Geometry make(Type const& c1, Type const& c2, Type const& c3)
{
concepts::check<Geometry>();
@@ -124,6 +156,22 @@ inline Geometry make(Type const& c1, Type const& c2, Type const& c3)
return geometry;
}
template
<
typename Geometry,
typename Type,
std::enable_if_t<traits::make<Geometry>::is_specialized, int> = 0
>
constexpr inline Geometry make(Type const& c1, Type const& c2, Type const& c3)
{
concepts::check<Geometry>();
// NOTE: This is not fully equivalent to the above because assign uses
// numeric_cast which can't be used here since it's not constexpr.
return traits::make<Geometry>::apply(c1, c2, c3);
}
template <typename Geometry, typename Type>
inline Geometry make(Type const& c1, Type const& c2, Type const& c3, Type const& c4)
{

View File

@@ -22,6 +22,7 @@
#include <boost/mpl/size_t.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/make.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
@@ -85,9 +86,10 @@ struct cross_product<3>
assert_dimension<P2, 3>();
assert_dimension<ResultP, 3>();
return ResultP(get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2),
get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2),
get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2));
return traits::make<ResultP>::apply(
get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2),
get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2),
get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2));
}
};
@@ -111,13 +113,7 @@ template
std::enable_if_t
<
dimension<ResultP>::value != 3
|| ! std::is_constructible
<
ResultP,
typename coordinate_type<ResultP>::type const&,
typename coordinate_type<ResultP>::type const&,
typename coordinate_type<ResultP>::type const&
>::value,
|| ! traits::make<ResultP>::is_specialized,
int
> = 0
>
@@ -138,13 +134,7 @@ template
std::enable_if_t
<
dimension<ResultP>::value == 3
&& std::is_constructible
<
ResultP,
typename coordinate_type<ResultP>::type const&,
typename coordinate_type<ResultP>::type const&,
typename coordinate_type<ResultP>::type const&
>::value,
&& traits::make<ResultP>::is_specialized,
int
> = 0
>
@@ -174,13 +164,7 @@ template
std::enable_if_t
<
dimension<P>::value != 3
|| ! std::is_constructible
<
P,
typename coordinate_type<P>::type const&,
typename coordinate_type<P>::type const&,
typename coordinate_type<P>::type const&
>::value,
|| ! traits::make<P>::is_specialized,
int
> = 0
>
@@ -201,13 +185,7 @@ template
std::enable_if_t
<
dimension<P>::value == 3
&& std::is_constructible
<
P,
typename coordinate_type<P>::type const&,
typename coordinate_type<P>::type const&,
typename coordinate_type<P>::type const&
>::value,
&& traits::make<P>::is_specialized,
int
> = 0
>

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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.

View File

@@ -0,0 +1,46 @@
// Boost.Geometry
// Copyright (c) 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_CORE_MAKE_HPP
#define BOOST_GEOMETRY_CORE_MAKE_HPP
namespace boost { namespace geometry
{
namespace traits
{
/*!
\brief Traits class to create an object of Geometry type.
\details This trait is optional and allows to define efficient way of creating Geometries.
\ingroup traits
\par Geometries:
- points
- boxes
- segments
\par Specializations should provide:
- static const bool is_specialized = true;
- static member function apply() taking:
- N coordinates (points)
- 2 points, min and max (boxes)
- 2 points, first and second (segments)
\tparam Geometry geometry
*/
template <typename Geometry>
struct make
{
static const bool is_specialized = false;
};
} // namespace traits
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_CORE_MAKE_HPP

View File

@@ -24,6 +24,13 @@
#include <boost/concept/assert.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/make.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
@@ -84,18 +91,14 @@ public:
*/
template
<
typename P1 = Point,
typename P2 = Point,
typename P = Point,
std::enable_if_t
<
! std::is_copy_constructible<P1>::value
|| ! std::is_copy_constructible<P2>::value
|| ! std::is_convertible<P1 const&, Point>::value
|| ! std::is_convertible<P2 const&, Point>::value,
! std::is_copy_constructible<P>::value,
int
> = 0
>
box(P1 const& min_corner, P2 const& max_corner)
box(Point const& min_corner, Point const& max_corner)
{
geometry::convert(min_corner, m_min_corner);
geometry::convert(max_corner, m_max_corner);
@@ -110,21 +113,17 @@ public:
*/
template
<
typename P1 = Point,
typename P2 = Point,
typename P = Point,
std::enable_if_t
<
std::is_copy_constructible<P1>::value
&& std::is_copy_constructible<P2>::value
&& std::is_convertible<P1 const&, Point>::value
&& std::is_convertible<P2 const&, Point>::value,
std::is_copy_constructible<P>::value,
int
> = 0
>
#if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
constexpr
#endif
box(P1 const& min_corner, P2 const& max_corner)
box(Point const& min_corner, Point const& max_corner)
: m_min_corner(min_corner)
, m_max_corner(max_corner)
{
@@ -234,6 +233,20 @@ struct indexed_access<model::box<Point>, max_corner, Dimension>
}
};
template <typename Point>
struct make<model::box<Point> >
{
typedef model::box<Point> box_type;
static const bool is_specialized = true;
static constexpr box_type apply(Point const& min_corner, Point const& max_corner)
{
return box_type(min_corner, max_corner);
}
};
} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS

View File

@@ -4,6 +4,9 @@
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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.
@@ -214,7 +217,7 @@ struct checker<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const>
\ingroup concepts
*/
template <typename Geometry>
inline void check()
constexpr inline void check()
{
detail::checker<Geometry> c;
boost::ignore_unused(c);
@@ -227,7 +230,7 @@ inline void check()
\ingroup concepts
*/
template <typename Geometry1, typename Geometry2>
inline void check_concepts_and_equal_dimensions()
constexpr inline void check_concepts_and_equal_dimensions()
{
check<Geometry1>();
check<Geometry2>();

View File

@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 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.
@@ -14,15 +18,15 @@
#ifndef BOOST_GEOMETRY_GEOMETRIES_HPP
#define BOOST_GEOMETRY_GEOMETRIES_HPP
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/multi_point.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/point_xyz.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/geometries/segment.hpp>

View File

@@ -32,6 +32,9 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/make.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
#include <algorithm>
@@ -47,6 +50,23 @@ namespace boost { namespace geometry
#pragma warning(disable : 4127)
#endif
namespace detail
{
template <typename Dummy, std::size_t N, std::size_t DimensionCount>
struct is_coordinates_number_leq
{
static const bool value = (N <= DimensionCount);
};
template <typename Dummy, std::size_t N, std::size_t DimensionCount>
struct is_coordinates_number_eq
{
static const bool value = (N == DimensionCount);
};
} // namespace detail
namespace model
{
@@ -109,6 +129,11 @@ public:
#endif
/// @brief Constructor to set one value
template
<
typename C = CoordinateType,
std::enable_if_t<geometry::detail::is_coordinates_number_leq<C, 1, DimensionCount>::value, int> = 0
>
#if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
constexpr
#endif
@@ -117,11 +142,16 @@ public:
{
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
m_created = 1;
std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);
std::fill_n(m_values_initialized, DimensionCount, 1);
#endif
}
/// @brief Constructor to set two values
template
<
typename C = CoordinateType,
std::enable_if_t<geometry::detail::is_coordinates_number_leq<C, 2, DimensionCount>::value, int> = 0
>
#if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
constexpr
#endif
@@ -130,21 +160,25 @@ public:
{
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
m_created = 1;
std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);
std::fill_n(m_values_initialized, DimensionCount, 1);
#endif
}
/// @brief Constructor to set three values
template
<
typename C = CoordinateType,
std::enable_if_t<geometry::detail::is_coordinates_number_leq<C, 3, DimensionCount>::value, int> = 0
>
#if ! defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
constexpr
#endif
point(CoordinateType const& v0, CoordinateType const& v1,
CoordinateType const& v2)
point(CoordinateType const& v0, CoordinateType const& v1, CoordinateType const& v2)
: m_values{ v0, v1, v2 }
{
#if defined(BOOST_GEOMETRY_ENABLE_ACCESS_DEBUGGING)
m_created = 1;
std::fill_n(m_values_initialized, (std::min)(std::size_t(3), DimensionCount), 1);
std::fill_n(m_values_initialized, DimensionCount, 1);
#endif
}
@@ -262,6 +296,53 @@ struct access<model::point<CoordinateType, DimensionCount, CoordinateSystem>, Di
}
};
template
<
typename CoordinateType,
std::size_t DimensionCount,
typename CoordinateSystem
>
struct make<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
{
typedef model::point<CoordinateType, DimensionCount, CoordinateSystem> point_type;
static const bool is_specialized = true;
template
<
typename C = CoordinateType,
std::enable_if_t<geometry::detail::is_coordinates_number_eq<C, 1, DimensionCount>::value, int> = 0
>
static constexpr point_type apply(CoordinateType const& v0)
{
return point_type(v0);
}
template
<
typename C = CoordinateType,
std::enable_if_t<geometry::detail::is_coordinates_number_eq<C, 2, DimensionCount>::value, int> = 0
>
static constexpr point_type apply(CoordinateType const& v0,
CoordinateType const& v1)
{
return point_type(v0, v1);
}
template
<
typename C = CoordinateType,
std::enable_if_t<geometry::detail::is_coordinates_number_eq<C, 3, DimensionCount>::value, int> = 0
>
static constexpr point_type apply(CoordinateType const& v0,
CoordinateType const& v1,
CoordinateType const& v2)
{
return point_type(v0, v1, v2);
}
};
} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS

View File

@@ -121,6 +121,21 @@ struct access<model::d2::point_xy<CoordinateType, CoordinateSystem>, Dimension >
}
};
template<typename CoordinateType, typename CoordinateSystem>
struct make<model::d2::point_xy<CoordinateType, CoordinateSystem> >
{
typedef model::d2::point_xy<CoordinateType, CoordinateSystem> point_type;
static const bool is_specialized = true;
static constexpr point_type apply(CoordinateType const& x,
CoordinateType const& y)
{
return point_type(x, y);
}
};
} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS

View File

@@ -124,6 +124,22 @@ struct access<model::d3::point_xyz<CoordinateType, CoordinateSystem>, Dimension>
}
};
template<typename CoordinateType, typename CoordinateSystem>
struct make<model::d3::point_xyz<CoordinateType, CoordinateSystem> >
{
typedef model::d3::point_xyz<CoordinateType, CoordinateSystem> point_type;
static const bool is_specialized = true;
static constexpr point_type apply(CoordinateType const& x,
CoordinateType const& y,
CoordinateType const& z)
{
return point_type(x, y, z);
}
};
} // namespace traits
#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS

View File

@@ -25,6 +25,12 @@
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/make.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
namespace boost { namespace geometry
@@ -164,6 +170,21 @@ struct indexed_access<model::segment<Point>, 1, Dimension>
};
template <typename Point>
struct make<model::segment<Point> >
{
typedef model::segment<Point> segment_type;
static const bool is_specialized = true;
static constexpr segment_type apply(Point const& p1, Point const& p2)
{
return segment_type(p1, p2);
}
};
template <typename ConstOrNonConstPoint>
struct tag<model::referring_segment<ConstOrNonConstPoint> >
{