feat():initial version

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

View File

@@ -0,0 +1,94 @@
// 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) 2017 Adam Wulkiewicz, Lodz, Poland.
// 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_STRATEGY_AREA_HPP
#define BOOST_GEOMETRY_STRATEGY_AREA_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// If user specified a CalculationType, use that type, whatever it is
// and whatever the Geometry is.
// Else, use Geometry's coordinate-type promoted to double if needed.
template
<
typename Geometry,
typename CalculationType
>
struct result_type
{
typedef CalculationType type;
};
template
<
typename Geometry
>
struct result_type<Geometry, void>
: select_most_precise
<
typename coordinate_type<Geometry>::type,
double
>
{};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
namespace services
{
/*!
\brief Traits class binding a default area strategy to a coordinate system
\ingroup area
\tparam Tag tag of coordinate system
*/
template <typename Tag>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this coordinate system.",
Tag);
};
} // namespace services
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_AREA_HPP

View File

@@ -0,0 +1,145 @@
// 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) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016-2020.
// Modifications copyright (c) 2016-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_STRATEGY_CARTESIAN_AREA_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_HPP
//#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategy/area.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Cartesian area calculation
\ingroup strategies
\details Calculates cartesian area using the trapezoidal rule
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class cartesian
{
public :
template <typename Geometry>
struct result_type
: strategy::area::detail::result_type
<
Geometry,
CalculationType
>
{};
template <typename Geometry>
class state
{
friend class cartesian;
typedef typename result_type<Geometry>::type return_type;
public:
inline state()
: sum(0)
{
// Strategy supports only 2D areas
assert_dimension<Geometry, 2>();
}
private:
inline return_type area() const
{
return_type const two = 2;
return sum / two;
}
return_type sum;
};
template <typename PointOfSegment, typename Geometry>
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
state<Geometry>& st)
{
typedef typename state<Geometry>::return_type return_type;
// Below formulas are equivalent, however the two lower ones
// suffer less from accuracy loss for great values of coordinates.
// See: https://svn.boost.org/trac/boost/ticket/11928
// SUM += x2 * y1 - x1 * y2;
// state.sum += detail::determinant<return_type>(p2, p1);
// SUM += (x2 - x1) * (y2 + y1)
//state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))
// * (return_type(get<1>(p2)) + return_type(get<1>(p1)));
// SUM += (x1 + x2) * (y1 - y2)
st.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))
* (return_type(get<1>(p1)) - return_type(get<1>(p2)));
}
template <typename Geometry>
static inline typename result_type<Geometry>::type
result(state<Geometry>& st)
{
return st.area();
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::area::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_HPP

View File

@@ -0,0 +1,120 @@
// 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 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.
// Distributed under 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_STRATEGY_CARTESIAN_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/strategy/cartesian/envelope_box.hpp>
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template <typename CalculationType = void>
class cartesian
{
public:
typedef cartesian_tag cs_tag;
// Linestring, Ring, Polygon
template <typename Range>
static inline typename boost::range_iterator<Range const>::type begin(Range const& range)
{
return boost::begin(range);
}
template <typename Range>
static inline typename boost::range_iterator<Range const>::type end(Range const& range)
{
return boost::end(range);
}
// MultiLinestring, MultiPolygon
template <typename Box>
struct multi_state
{
multi_state()
: m_initialized(false)
{}
void apply(Box const& single_box)
{
if (! m_initialized)
{
m_box = single_box;
m_initialized = true;
}
else
{
strategy::expand::cartesian_box::apply(m_box, single_box);
}
}
void result(Box & box)
{
if (m_initialized)
{
box = m_box;
}
else
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
}
}
private:
bool m_initialized;
Box m_box;
};
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian<CalculationType> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_HPP

View File

@@ -0,0 +1,123 @@
// 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 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
// Distributed under 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_STRATEGY_CARTESIAN_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOX_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template
<
std::size_t Index,
std::size_t Dimension,
std::size_t DimensionCount
>
struct envelope_indexed_box
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
Dimension,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace envelope
{
struct cartesian_box
{
typedef cartesian_tag cs_tag;
template<typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
geometry::detail::envelope::envelope_indexed_box
<
min_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
geometry::detail::envelope::envelope_indexed_box
<
max_corner, 0, dimension<BoxIn>::value
>::apply(box_in, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_box type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,83 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Distributed under 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_STRATEGY_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/strategy/cartesian/envelope.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class cartesian_multipoint
{
public:
template <typename MultiPoint, typename Box>
static inline void apply(MultiPoint const& multipoint, Box& mbr)
{
apply(boost::begin(multipoint), boost::end(multipoint), mbr);
}
private:
template <typename Iterator, typename Box>
static inline void apply(Iterator it,
Iterator last,
Box& mbr)
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(mbr);
if (it != last)
{
strategy::envelope::cartesian_point::apply(*it, mbr);
for (++it; it != last; ++it)
{
strategy::expand::cartesian_point::apply(mbr, *it);
}
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<multi_point_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_multipoint type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_MULTIPOINT_HPP

View File

@@ -0,0 +1,111 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_CARTESIAN_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/strategy/envelope.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_point
{
template <std::size_t Index, typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
detail::indexed_point_view<Box, Index> box_corner(mbr);
detail::conversion::point_to_point
<
Point,
detail::indexed_point_view<Box, Index>,
Dimension,
DimensionCount
>::apply(point, box_corner);
}
template <typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
apply<min_corner>(point, mbr);
apply<max_corner>(point, mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace envelope
{
struct cartesian_point
{
template <typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
geometry::detail::envelope::envelope_one_point
<
0, dimension<Point>::value
>::apply(point, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_point type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_POINT_HPP

View File

@@ -0,0 +1,93 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, 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_STRATEGY_CARTESIAN_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_SEGMENT_HPP
#include <cstddef>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategy/envelope.hpp>
namespace boost { namespace geometry { namespace strategy { namespace envelope
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct envelope_one_segment
{
template<typename Point, typename Box>
static inline void apply(Point const& p1,
Point const& p2,
Box& mbr)
{
geometry::detail::envelope::envelope_one_point
<
Dimension, DimensionCount
>::apply(p1, mbr);
strategy::expand::detail::point_loop
<
Dimension, DimensionCount
>::apply(mbr, p2);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename CalculationType = void
>
class cartesian_segment
{
public:
template <typename Point, typename Box>
static inline void apply(Point const& point1, Point const& point2, Box& box)
{
strategy::envelope::detail::envelope_one_segment
<
0,
dimension<Point>::value
>::apply(point1, point2, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, cartesian_tag, CalculationType>
{
typedef strategy::envelope::cartesian_segment<CalculationType> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_SEGMENT_HPP

View File

@@ -0,0 +1,69 @@
// 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.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015, 2016, 2017.
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_CARTESIAN_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_EXPAND_BOX_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/strategy/expand.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
struct cartesian_box
{
template <typename BoxOut, typename BoxIn>
static void apply(BoxOut & box_out, BoxIn const& box_in)
{
geometry::detail::expand::expand_indexed
<
0, dimension<BoxIn>::value
>::apply(box_out, box_in);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, cartesian_tag, CalculationType>
{
typedef cartesian_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_EXPAND_BOX_HPP

View File

@@ -0,0 +1,125 @@
// 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.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015-2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// 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.
// Distributed under 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_STRATEGY_CARTESIAN_EXPAND_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_EXPAND_POINT_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/strategy/expand.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_loop
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& source)
{
typedef typename select_coordinate_type
<
Point, Box
>::type coordinate_type;
std::less<coordinate_type> less;
std::greater<coordinate_type> greater;
coordinate_type const coord = get<Dimension>(source);
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
}
if (greater(coord, get<max_corner, Dimension>(box)))
{
set<max_corner, Dimension>(box, coord);
}
point_loop<Dimension + 1, DimensionCount>::apply(box, source);
}
};
template <std::size_t DimensionCount>
struct point_loop<DimensionCount, DimensionCount>
{
template <typename Box, typename Point>
static inline void apply(Box&, Point const&) {}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct cartesian_point
{
template <typename Box, typename Point>
static void apply(Box & box, Point const& point)
{
expand::detail::point_loop
<
0, dimension<Point>::value
>::apply(box, point);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, cartesian_tag, CalculationType>
{
typedef cartesian_point type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_EXPAND_POINT_HPP

View File

@@ -0,0 +1,71 @@
// 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.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_CARTESIAN_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_EXPAND_SEGMENT_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
#include <boost/geometry/strategy/expand.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
class cartesian_segment
{
public:
template <typename Box, typename Segment>
static void apply(Box & box, Segment const& segment)
{
geometry::detail::expand::expand_indexed
<
0, dimension<Segment>::value
>::apply(box, segment);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, cartesian_tag, CalculationType>
{
typedef cartesian_segment type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_EXPAND_SEGMENT_HPP

View File

@@ -0,0 +1,44 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, 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_STRATEGY_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGY_ENVELOPE_HPP
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope { namespace services
{
/*!
\brief Traits class binding a default envelope strategy to a coordinate system
\ingroup util
\tparam Tag tag of geometry
\tparam CSTag tag of coordinate system
\tparam CalculationType \tparam_calculation
*/
template <typename Tag, typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this type.",
Tag, CSTag);
};
}}} // namespace strategy::envelope::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_ENVELOPE_HPP

View File

@@ -0,0 +1,43 @@
// Boost.Geometry
// 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_STRATEGY_EXPAND_HPP
#define BOOST_GEOMETRY_STRATEGY_EXPAND_HPP
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand { namespace services
{
/*!
\brief Traits class binding a default envelope strategy to a coordinate system
\ingroup util
\tparam Tag tag of geometry
\tparam CSTag tag of coordinate system
\tparam CalculationType \tparam_calculation
*/
template <typename Tag, typename CSTag, typename CalculationType = void>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for this type.",
Tag, CSTag);
};
}}} // namespace strategy::expand::services
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_EXPAND_HPP

View File

@@ -0,0 +1,239 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2016-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, 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_STRATEGY_GEOGRAPHIC_AREA_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_HPP
#include <type_traits>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/formulas/area_formulas.hpp>
#include <boost/geometry/formulas/authalic_radius_sqr.hpp>
#include <boost/geometry/formulas/eccentricity_sqr.hpp>
#include <boost/geometry/strategy/area.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Geographic area calculation
\ingroup strategies
\details Geographic area calculation by trapezoidal rule plus integral
approximation that gives the ellipsoidal correction
\tparam FormulaPolicy Formula used to calculate azimuths
\tparam SeriesOrder The order of approximation of the geodesic integral
\tparam Spheroid The spheroid model
\tparam CalculationType \tparam_calculation
\author See
- Danielsen JS, The area under the geodesic. Surv Rev 30(232): 6166, 1989
- Charles F.F Karney, Algorithms for geodesics, 2011 https://arxiv.org/pdf/1109.4448.pdf
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
\* [link geometry.reference.srs.srs_spheroid srs::spheroid]
}
*/
template
<
typename FormulaPolicy = strategy::andoyer,
std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic
{
// Switch between two kinds of approximation(series in eps and n v.s.series in k ^ 2 and e'^2)
static const bool ExpandEpsN = true;
// LongSegment Enables special handling of long segments
static const bool LongSegment = false;
//Select default types in case they are not set
public:
template <typename Geometry>
struct result_type
: strategy::area::detail::result_type
<
Geometry,
CalculationType
>
{};
protected :
struct spheroid_constants
{
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename geometry::radius_type<Spheroid>::type,
CalculationType
> calc_t;
Spheroid m_spheroid;
calc_t const m_a2; // squared equatorial radius
calc_t const m_e2; // squared eccentricity
calc_t const m_ep2; // squared second eccentricity
calc_t const m_ep; // second eccentricity
calc_t const m_c2; // squared authalic radius
inline spheroid_constants(Spheroid const& spheroid)
: m_spheroid(spheroid)
, m_a2(math::sqr(get_radius<0>(spheroid)))
, m_e2(formula::eccentricity_sqr<calc_t>(spheroid))
, m_ep2(m_e2 / (calc_t(1.0) - m_e2))
, m_ep(math::sqrt(m_ep2))
, m_c2(formula_dispatch::authalic_radius_sqr
<
calc_t, Spheroid, srs_spheroid_tag
>::apply(m_a2, m_e2))
{}
};
public:
template <typename Geometry>
class state
{
friend class geographic;
typedef typename result_type<Geometry>::type return_type;
public:
inline state()
: m_excess_sum(0)
, m_correction_sum(0)
, m_crosses_prime_meridian(0)
{}
private:
inline return_type area(spheroid_constants const& spheroid_const) const
{
return_type result;
return_type sum = spheroid_const.m_c2 * m_excess_sum
+ spheroid_const.m_e2 * spheroid_const.m_a2 * m_correction_sum;
// If encircles some pole
if (m_crosses_prime_meridian % 2 == 1)
{
std::size_t times_crosses_prime_meridian
= 1 + (m_crosses_prime_meridian / 2);
result = return_type(2.0)
* geometry::math::pi<return_type>()
* spheroid_const.m_c2
* return_type(times_crosses_prime_meridian)
- geometry::math::abs(sum);
if (geometry::math::sign<return_type>(sum) == 1)
{
result = - result;
}
}
else
{
result = sum;
}
return result;
}
return_type m_excess_sum;
return_type m_correction_sum;
// Keep track if encircles some pole
std::size_t m_crosses_prime_meridian;
};
public :
explicit inline geographic(Spheroid const& spheroid = Spheroid())
: m_spheroid_constants(spheroid)
{}
template <typename PointOfSegment, typename Geometry>
inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
state<Geometry>& st) const
{
if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
{
typedef geometry::formula::area_formulas
<
typename result_type<Geometry>::type,
SeriesOrder, ExpandEpsN
> area_formulas;
typename area_formulas::return_type_ellipsoidal result =
area_formulas::template ellipsoidal<FormulaPolicy::template inverse>
(p1, p2, m_spheroid_constants);
st.m_excess_sum += result.spherical_term;
st.m_correction_sum += result.ellipsoidal_term;
// Keep track whenever a segment crosses the prime meridian
if (area_formulas::crosses_prime_meridian(p1, p2))
{
st.m_crosses_prime_meridian++;
}
}
}
template <typename Geometry>
inline typename result_type<Geometry>::type
result(state<Geometry> const& st) const
{
return st.area(m_spheroid_constants);
}
Spheroid model() const
{
return m_spheroid_constants.m_spheroid;
}
private:
spheroid_constants m_spheroid_constants;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<geographic_tag>
{
typedef strategy::area::geographic<> type;
};
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_HPP

View File

@@ -0,0 +1,94 @@
// 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 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.
// Distributed under 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_STRATEGY_GEOGRAPHIC_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_HPP
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategy/geographic/envelope_segment.hpp>
#include <boost/geometry/strategy/geographic/expand_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategy/spherical/envelope.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = geometry::srs::spheroid<double>,
typename CalculationType = void
>
class geographic
: public spherical<CalculationType>
{
public:
typedef geographic_tag cs_tag;
typedef Spheroid model_type;
inline geographic()
: m_spheroid()
{}
explicit inline geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
Spheroid model() const
{
return m_spheroid;
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::geographic
<
strategy::andoyer,
geometry::srs::spheroid<double>,
CalculationType
> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_HPP

View File

@@ -0,0 +1,122 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, 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_STRATEGY_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategy/envelope.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
#include <boost/geometry/strategy/spherical/expand_box.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = geometry::srs::spheroid<double>,
typename CalculationType = void
>
class geographic_segment
{
public:
typedef Spheroid model_type;
inline geographic_segment()
: m_spheroid()
{}
explicit inline geographic_segment(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Point, typename Box>
inline void apply(Point const& point1, Point const& point2, Box& box) const
{
Point p1_normalized, p2_normalized;
strategy::normalize::spherical_point::apply(point1, p1_normalized);
strategy::normalize::spherical_point::apply(point2, p2_normalized);
geometry::strategy::azimuth::geographic
<
FormulaPolicy,
Spheroid,
CalculationType
> azimuth_geographic(m_spheroid);
typedef typename geometry::detail::cs_angular_units
<
Point
>::type units_type;
// first compute the envelope range for the first two coordinates
strategy::envelope::detail::envelope_segment_impl
<
geographic_tag
>::template apply<units_type>(geometry::get<0>(p1_normalized),
geometry::get<1>(p1_normalized),
geometry::get<0>(p2_normalized),
geometry::get<1>(p2_normalized),
box,
azimuth_geographic);
// now compute the envelope range for coordinates of
// dimension 2 and higher
strategy::envelope::detail::envelope_one_segment
<
2, dimension<Point>::value
>::apply(point1, point2, box);
}
Spheroid model() const
{
return m_spheroid;
}
private:
Spheroid m_spheroid;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::geographic_segment
<
strategy::andoyer,
srs::spheroid<double>,
CalculationType
> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_SEGMENT_HPP

View File

@@ -0,0 +1,107 @@
// 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.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_GEOGRAPHIC_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_EXPAND_SEGMENT_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategy/expand.hpp>
#include <boost/geometry/strategy/geographic/envelope_segment.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategy/spherical/expand_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = geometry::srs::spheroid<double>,
typename CalculationType = void
>
class geographic_segment
{
public:
inline geographic_segment()
: m_envelope_strategy()
{}
explicit inline geographic_segment(Spheroid const& spheroid)
: m_envelope_strategy(spheroid)
{}
template <typename Box, typename Segment>
inline void apply(Box& box, Segment const& segment) const
{
detail::segment_on_spheroid::apply(box, segment, m_envelope_strategy);
}
Spheroid model() const
{
return m_envelope_strategy.model();
}
private:
strategy::envelope::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
> m_envelope_strategy;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, geographic_tag, CalculationType>
{
typedef geographic_segment
<
strategy::andoyer,
geometry::srs::spheroid<double>,
CalculationType
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_EXPAND_SEGMENT_HPP

View File

@@ -0,0 +1,202 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2016-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, 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_STRATEGY_SPHERICAL_AREA_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP
#include <boost/geometry/formulas/area_formulas.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/strategy/area.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Spherical area calculation
\ingroup strategies
\details Calculates area on the surface of a sphere using the trapezoidal rule
\tparam RadiusTypeOrSphere \tparam_radius_or_sphere
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
}
*/
template
<
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class spherical
{
typedef typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type radius_type;
// Enables special handling of long segments
static const bool LongSegment = false;
public:
template <typename Geometry>
struct result_type
: strategy::area::detail::result_type
<
Geometry,
CalculationType
>
{};
template <typename Geometry>
class state
{
friend class spherical;
typedef typename result_type<Geometry>::type return_type;
public:
inline state()
: m_sum(0)
, m_crosses_prime_meridian(0)
{}
private:
template <typename RadiusType>
inline return_type area(RadiusType const& r) const
{
return_type result;
return_type radius = r;
// Encircles pole
if(m_crosses_prime_meridian % 2 == 1)
{
size_t times_crosses_prime_meridian
= 1 + (m_crosses_prime_meridian / 2);
result = return_type(2)
* geometry::math::pi<return_type>()
* times_crosses_prime_meridian
- geometry::math::abs(m_sum);
if(geometry::math::sign<return_type>(m_sum) == 1)
{
result = - result;
}
} else {
result = m_sum;
}
result *= radius * radius;
return result;
}
return_type m_sum;
// Keep track if encircles some pole
size_t m_crosses_prime_meridian;
};
public :
// For backward compatibility reasons the radius is set to 1
inline spherical()
: m_radius(1.0)
{}
template <typename RadiusOrSphere>
explicit inline spherical(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
template <typename PointOfSegment, typename Geometry>
inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2,
state<Geometry>& st) const
{
if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
{
typedef geometry::formula::area_formulas
<
typename result_type<Geometry>::type
> area_formulas;
st.m_sum += area_formulas::template spherical<LongSegment>(p1, p2);
// Keep track whenever a segment crosses the prime meridian
if (area_formulas::crosses_prime_meridian(p1, p2))
{
st.m_crosses_prime_meridian++;
}
}
}
template <typename Geometry>
inline typename result_type<Geometry>::type
result(state<Geometry> const& st) const
{
return st.area(m_radius);
}
srs::sphere<radius_type> model() const
{
return srs::sphere<radius_type>(m_radius);
}
private :
radius_type m_radius;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef strategy::area::spherical<> type;
};
// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
template <>
struct default_strategy<spherical_polar_tag>
{
typedef strategy::area::spherical<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP

View File

@@ -0,0 +1,113 @@
// 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, 2016, 2018, 2019.
// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates.
// 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.
// Distributed under 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_STRATEGY_SPHERICAL_ENVELOPE_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_HPP
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/iterators/segment_iterator.hpp>
#include <boost/geometry/strategy/spherical/envelope_box.hpp>
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
#include <boost/geometry/strategy/spherical/expand_box.hpp>
#include <boost/geometry/strategy/spherical/expand_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
template <typename CalculationType = void>
class spherical
{
public:
typedef spherical_tag cs_tag;
// Linestring, Ring, Polygon
template <typename Range>
static inline geometry::segment_iterator<Range const> begin(Range const& range)
{
return geometry::segments_begin(range);
}
template <typename Range>
static inline geometry::segment_iterator<Range const> end(Range const& range)
{
return geometry::segments_end(range);
}
// MultiLinestring, MultiPolygon
template <typename Box>
struct multi_state
{
void apply(Box const& single_box)
{
m_boxes.push_back(single_box);
}
void result(Box & box)
{
if (!m_boxes.empty())
{
geometry::detail::envelope::envelope_range_of_boxes::apply(m_boxes, box);
}
else
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
}
}
private:
std::vector<Box> m_boxes;
};
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical<CalculationType> type;
};
template <typename Tag, typename CalculationType>
struct default_strategy<Tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical<CalculationType> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_HPP

View File

@@ -0,0 +1,75 @@
// 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 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
// Distributed under 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_STRATEGY_SPHERICAL_ENVELOPE_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOX_HPP
#include <boost/geometry/strategy/spherical/expand_box.hpp>
#include <boost/geometry/strategy/envelope.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
struct spherical_box
: geometry::detail::envelope::envelope_box_on_spheroid
{
typedef spherical_tag cs_tag;
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::spherical_box type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,381 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2020, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#include <cstddef>
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategy/spherical/envelope_box.hpp>
#include <boost/geometry/strategy/spherical/envelope_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class spherical_multipoint
{
private:
template <std::size_t Dim>
struct coordinate_less
{
template <typename Point>
inline bool operator()(Point const& point1, Point const& point2) const
{
return math::smaller(geometry::get<Dim>(point1),
geometry::get<Dim>(point2));
}
};
template <typename Constants, typename MultiPoint, typename OutputIterator>
static inline void analyze_point_coordinates(MultiPoint const& multipoint,
bool& has_south_pole,
bool& has_north_pole,
OutputIterator oit)
{
typedef typename boost::range_value<MultiPoint>::type point_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
// analyze point coordinates:
// (1) normalize point coordinates
// (2) check if any point is the north or the south pole
// (3) put all non-pole points in a container
//
// notice that at this point in the algorithm, we have at
// least two points on the spheroid
has_south_pole = false;
has_north_pole = false;
for (iterator_type it = boost::begin(multipoint);
it != boost::end(multipoint);
++it)
{
point_type point;
normalize::spherical_point::apply(*it, point);
if (math::equals(geometry::get<1>(point),
Constants::min_latitude()))
{
has_south_pole = true;
}
else if (math::equals(geometry::get<1>(point),
Constants::max_latitude()))
{
has_north_pole = true;
}
else
{
*oit++ = point;
}
}
}
template <typename SortedRange, typename Value>
static inline Value maximum_gap(SortedRange const& sorted_range,
Value& max_gap_left,
Value& max_gap_right)
{
typedef typename boost::range_iterator
<
SortedRange const
>::type iterator_type;
iterator_type it1 = boost::begin(sorted_range), it2 = it1;
++it2;
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
Value max_gap = max_gap_right - max_gap_left;
for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)
{
Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);
if (math::larger(gap, max_gap))
{
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
max_gap = gap;
}
}
return max_gap;
}
template
<
typename Constants,
typename PointRange,
typename LongitudeLess,
typename CoordinateType
>
static inline void get_min_max_longitudes(PointRange& range,
LongitudeLess const& lon_less,
CoordinateType& lon_min,
CoordinateType& lon_max)
{
typedef typename boost::range_iterator
<
PointRange const
>::type iterator_type;
// compute min and max longitude values
std::pair<iterator_type, iterator_type> min_max_longitudes
= boost::minmax_element(boost::begin(range),
boost::end(range),
lon_less);
lon_min = geometry::get<0>(*min_max_longitudes.first);
lon_max = geometry::get<0>(*min_max_longitudes.second);
// if the longitude span is "large" compute the true maximum gap
if (math::larger(lon_max - lon_min, Constants::half_period()))
{
std::sort(boost::begin(range), boost::end(range), lon_less);
CoordinateType max_gap_left = 0, max_gap_right = 0;
CoordinateType max_gap
= maximum_gap(range, max_gap_left, max_gap_right);
CoordinateType complement_gap
= Constants::period() + lon_min - lon_max;
if (math::larger(max_gap, complement_gap))
{
lon_min = max_gap_right;
lon_max = max_gap_left + Constants::period();
}
}
}
template
<
typename Constants,
typename Iterator,
typename LatitudeLess,
typename CoordinateType
>
static inline void get_min_max_latitudes(Iterator const first,
Iterator const last,
LatitudeLess const& lat_less,
bool has_south_pole,
bool has_north_pole,
CoordinateType& lat_min,
CoordinateType& lat_max)
{
if (has_south_pole && has_north_pole)
{
lat_min = Constants::min_latitude();
lat_max = Constants::max_latitude();
}
else if (has_south_pole)
{
lat_min = Constants::min_latitude();
lat_max
= geometry::get<1>(*std::max_element(first, last, lat_less));
}
else if (has_north_pole)
{
lat_min
= geometry::get<1>(*std::min_element(first, last, lat_less));
lat_max = Constants::max_latitude();
}
else
{
std::pair<Iterator, Iterator> min_max_latitudes
= boost::minmax_element(first, last, lat_less);
lat_min = geometry::get<1>(*min_max_latitudes.first);
lat_max = geometry::get<1>(*min_max_latitudes.second);
}
}
public:
template <typename MultiPoint, typename Box>
static inline void apply(MultiPoint const& multipoint, Box& mbr)
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef math::detail::constants_on_spheroid
<
coordinate_type,
typename geometry::detail::cs_angular_units<MultiPoint>::type
> constants;
if (boost::empty(multipoint))
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(mbr);
return;
}
geometry::detail::envelope::initialize<Box, 0, 2>::apply(mbr);
if (boost::size(multipoint) == 1)
{
spherical_point::apply(range::front(multipoint), mbr);
return;
}
// analyze the points and put the non-pole ones in the
// points vector
std::vector<point_type> points;
bool has_north_pole = false, has_south_pole = false;
analyze_point_coordinates<constants>(multipoint,
has_south_pole, has_north_pole,
std::back_inserter(points));
coordinate_type lon_min, lat_min, lon_max, lat_max;
if (points.size() == 1)
{
// we have one non-pole point and at least one pole point
lon_min = geometry::get<0>(range::front(points));
lon_max = geometry::get<0>(range::front(points));
lat_min = has_south_pole
? constants::min_latitude()
: constants::max_latitude();
lat_max = has_north_pole
? constants::max_latitude()
: constants::min_latitude();
}
else if (points.empty())
{
// all points are pole points
BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);
lon_min = coordinate_type(0);
lon_max = coordinate_type(0);
lat_min = has_south_pole
? constants::min_latitude()
: constants::max_latitude();
lat_max = (has_north_pole)
? constants::max_latitude()
: constants::min_latitude();
}
else
{
get_min_max_longitudes<constants>(points,
coordinate_less<0>(),
lon_min,
lon_max);
get_min_max_latitudes<constants>(points.begin(),
points.end(),
coordinate_less<1>(),
has_south_pole,
has_north_pole,
lat_min,
lat_max);
}
typedef typename helper_geometry
<
Box,
coordinate_type,
typename geometry::detail::cs_angular_units<MultiPoint>::type
>::type helper_box_type;
helper_box_type helper_mbr;
geometry::set<min_corner, 0>(helper_mbr, lon_min);
geometry::set<min_corner, 1>(helper_mbr, lat_min);
geometry::set<max_corner, 0>(helper_mbr, lon_max);
geometry::set<max_corner, 1>(helper_mbr, lat_max);
// now transform to output MBR (per index)
geometry::detail::envelope::envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
geometry::detail::envelope::envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
// compute envelope for higher coordinates
iterator_type it = boost::begin(multipoint);
geometry::detail::envelope::envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
for (++it; it != boost::end(multipoint); ++it)
{
strategy::expand::detail::point_loop
<
2, dimension<Box>::value
>::apply(mbr, *it);
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<multi_point_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_multipoint type;
};
template <typename CalculationType>
struct default_strategy<multi_point_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_multipoint type;
};
template <typename CalculationType>
struct default_strategy<multi_point_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::spherical_multipoint type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_MULTIPOINT_HPP

View File

@@ -0,0 +1,111 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_SPHERICAL_ENVELOPE_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_POINT_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
#include <boost/geometry/strategy/envelope.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
struct spherical_point
{
template<typename Point, typename Box>
static inline void apply(Point const& point, Box& mbr)
{
Point normalized_point;
strategy::normalize::spherical_point::apply(point, normalized_point);
typename point_type<Box>::type box_point;
// transform units of input point to units of a box point
geometry::detail::envelope::transform_units(normalized_point, box_point);
geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
typedef geometry::detail::envelope::envelope_one_point
<
2, dimension<Point>::value
> per_corner;
per_corner::template apply<min_corner>(normalized_point, mbr);
per_corner::template apply<max_corner>(normalized_point, mbr);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, geographic_tag, CalculationType>
{
typedef strategy::envelope::spherical_point type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_POINT_HPP

View File

@@ -0,0 +1,437 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, 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_STRATEGY_SPHERICAL_ENVELOPE_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_SEGMENT_HPP
#include <cstddef>
#include <utility>
#include <boost/core/ignore_unused.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/formulas/meridian_segment.hpp>
#include <boost/geometry/formulas/vertex_latitude.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
#include <boost/geometry/strategy/envelope.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategies/spherical/azimuth.hpp>
#include <boost/geometry/strategy/spherical/expand_box.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry { namespace strategy { namespace envelope
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename CalculationType, typename CS_Tag>
struct envelope_segment_call_vertex_latitude
{
template <typename T1, typename T2, typename Strategy>
static inline CalculationType apply(T1 const& lat1,
T2 const& alp1,
Strategy const& )
{
return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
::apply(lat1, alp1);
}
};
template <typename CalculationType>
struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
{
template <typename T1, typename T2, typename Strategy>
static inline CalculationType apply(T1 const& lat1,
T2 const& alp1,
Strategy const& strategy)
{
return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
::apply(lat1, alp1, strategy.model());
}
};
template <typename Units, typename CS_Tag>
struct envelope_segment_convert_polar
{
template <typename T>
static inline void pre(T & , T & ) {}
template <typename T>
static inline void post(T & , T & ) {}
};
template <typename Units>
struct envelope_segment_convert_polar<Units, spherical_polar_tag>
{
template <typename T>
static inline void pre(T & lat1, T & lat2)
{
lat1 = math::latitude_convert_ep<Units>(lat1);
lat2 = math::latitude_convert_ep<Units>(lat2);
}
template <typename T>
static inline void post(T & lat1, T & lat2)
{
lat1 = math::latitude_convert_ep<Units>(lat1);
lat2 = math::latitude_convert_ep<Units>(lat2);
std::swap(lat1, lat2);
}
};
template <typename CS_Tag>
class envelope_segment_impl
{
private:
// degrees or radians
template <typename CalculationType>
static inline void swap(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2)
{
std::swap(lon1, lon2);
std::swap(lat1, lat2);
}
// radians
template <typename CalculationType>
static inline bool contains_pi_half(CalculationType const& a1,
CalculationType const& a2)
{
// azimuths a1 and a2 are assumed to be in radians
BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));
static CalculationType const pi_half = math::half_pi<CalculationType>();
return (a1 < a2)
? (a1 < pi_half && pi_half < a2)
: (a1 > pi_half && pi_half > a2);
}
// radians or degrees
template <typename Units, typename CoordinateType>
static inline bool crosses_antimeridian(CoordinateType const& lon1,
CoordinateType const& lon2)
{
typedef math::detail::constants_on_spheroid
<
CoordinateType, Units
> constants;
return math::abs(lon1 - lon2) > constants::half_period(); // > pi
}
// degrees or radians
template <typename Units, typename CalculationType, typename Strategy>
static inline void compute_box_corners(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
CalculationType a1,
CalculationType a2,
Strategy const& strategy)
{
// coordinates are assumed to be in radians
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
boost::ignore_unused(lon1, lon2);
CalculationType lat1_rad = math::as_radian<Units>(lat1);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
if (math::equals(a1, a2))
{
// the segment must lie on the equator or is very short or is meridian
return;
}
if (lat1 > lat2)
{
std::swap(lat1, lat2);
std::swap(lat1_rad, lat2_rad);
std::swap(a1, a2);
}
if (contains_pi_half(a1, a2))
{
CalculationType p_max = envelope_segment_call_vertex_latitude
<CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
CalculationType const mid_lat = lat1 + lat2;
if (mid_lat < 0)
{
// update using min latitude
CalculationType const lat_min_rad = -p_max;
CalculationType const lat_min
= math::from_radian<Units>(lat_min_rad);
if (lat1 > lat_min)
{
lat1 = lat_min;
}
}
else
{
// update using max latitude
CalculationType const lat_max_rad = p_max;
CalculationType const lat_max
= math::from_radian<Units>(lat_max_rad);
if (lat2 < lat_max)
{
lat2 = lat_max;
}
}
}
}
template <typename Units, typename CalculationType>
static inline void special_cases(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2)
{
typedef math::detail::constants_on_spheroid
<
CalculationType, Units
> constants;
bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude());
bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude());
if (is_pole1 && is_pole2)
{
// both points are poles; nothing more to do:
// longitudes are already normalized to 0
// but just in case
lon1 = 0;
lon2 = 0;
}
else if (is_pole1 && !is_pole2)
{
// first point is a pole, second point is not:
// make the longitude of the first point the same as that
// of the second point
lon1 = lon2;
}
else if (!is_pole1 && is_pole2)
{
// second point is a pole, first point is not:
// make the longitude of the second point the same as that
// of the first point
lon2 = lon1;
}
if (lon1 == lon2)
{
// segment lies on a meridian
if (lat1 > lat2)
{
std::swap(lat1, lat2);
}
return;
}
BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);
if (lon1 > lon2)
{
swap(lon1, lat1, lon2, lat2);
}
if (crosses_antimeridian<Units>(lon1, lon2))
{
lon1 += constants::period();
swap(lon1, lat1, lon2, lat2);
}
}
template
<
typename Units,
typename CalculationType,
typename Box
>
static inline void create_box(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
Box& mbr)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename helper_geometry
<
Box, box_coordinate_type, Units
>::type helper_box_type;
helper_box_type helper_mbr;
geometry::set
<
min_corner, 0
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
geometry::set
<
min_corner, 1
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
geometry::set
<
max_corner, 0
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
geometry::set
<
max_corner, 1
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
geometry::detail::envelope::transform_units(helper_mbr, mbr);
}
template <typename Units, typename CalculationType, typename Strategy>
static inline void apply(CalculationType& lon1,
CalculationType& lat1,
CalculationType& lon2,
CalculationType& lat2,
Strategy const& strategy)
{
special_cases<Units>(lon1, lat1, lon2, lat2);
CalculationType lon1_rad = math::as_radian<Units>(lon1);
CalculationType lat1_rad = math::as_radian<Units>(lat1);
CalculationType lon2_rad = math::as_radian<Units>(lon2);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
CalculationType alp1, alp2;
strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, alp1, alp2);
compute_box_corners<Units>(lon1, lat1, lon2, lat2, alp1, alp2, strategy);
}
public:
template
<
typename Units,
typename CalculationType,
typename Box,
typename Strategy
>
static inline void apply(CalculationType lon1,
CalculationType lat1,
CalculationType lon2,
CalculationType lat2,
Box& mbr,
Strategy const& strategy)
{
typedef envelope_segment_convert_polar<Units, typename cs_tag<Box>::type> convert_polar;
convert_polar::pre(lat1, lat2);
apply<Units>(lon1, lat1, lon2, lat2, strategy);
convert_polar::post(lat1, lat2);
create_box<Units>(lon1, lat1, lon2, lat2, mbr);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename CalculationType = void
>
class spherical_segment
{
public:
template <typename Point, typename Box>
static inline void apply(Point const& point1, Point const& point2,
Box& box)
{
Point p1_normalized, p2_normalized;
strategy::normalize::spherical_point::apply(point1, p1_normalized);
strategy::normalize::spherical_point::apply(point2, p2_normalized);
geometry::strategy::azimuth::spherical<CalculationType> azimuth_spherical;
typedef typename geometry::detail::cs_angular_units<Point>::type units_type;
// first compute the envelope range for the first two coordinates
strategy::envelope::detail::envelope_segment_impl
<
spherical_equatorial_tag
>::template apply<units_type>(geometry::get<0>(p1_normalized),
geometry::get<1>(p1_normalized),
geometry::get<0>(p2_normalized),
geometry::get<1>(p2_normalized),
box,
azimuth_spherical);
// now compute the envelope range for coordinates of
// dimension 2 and higher
strategy::envelope::detail::envelope_one_segment
<
2, dimension<Point>::value
>::apply(point1, point2, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, spherical_equatorial_tag, CalculationType>
{
typedef strategy::envelope::spherical_segment<CalculationType> type;
};
template <typename CalculationType>
struct default_strategy<segment_tag, spherical_polar_tag, CalculationType>
{
typedef strategy::envelope::spherical_segment<CalculationType> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_SEGMENT_HPP

View File

@@ -0,0 +1,175 @@
// 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.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015, 2016, 2017, 2018, 2019.
// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates.
// 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
// Distributed under 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_STRATEGY_SPHERICAL_EXPAND_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_BOX_HPP
#include <algorithm>
#include <cstddef>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/strategy/expand.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace envelope
{
template
<
std::size_t Index,
std::size_t DimensionCount
>
struct envelope_indexed_box_on_spheroid
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
// transform() does not work with boxes of dimension higher
// than 2; to account for such boxes we transform the min/max
// points of the boxes using the indexed_point_view
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
// first transform the units
transform_units(box_in_corner, mbr_corner);
// now transform the remaining coordinates
detail::conversion::point_to_point
<
detail::indexed_point_view<BoxIn const, Index>,
detail::indexed_point_view<BoxOut, Index>,
2,
DimensionCount
>::apply(box_in_corner, mbr_corner);
}
};
struct envelope_box_on_spheroid
{
template <typename BoxIn, typename BoxOut>
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
{
// BoxIn can be non-mutable
typename helper_geometry<BoxIn>::type box_in_normalized;
geometry::convert(box_in, box_in_normalized);
if (! is_inverse_spheroidal_coordinates(box_in))
{
strategy::normalize::spherical_box::apply(box_in, box_in_normalized);
}
geometry::detail::envelope::envelope_indexed_box_on_spheroid
<
min_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
geometry::detail::envelope::envelope_indexed_box_on_spheroid
<
max_corner, dimension<BoxIn>::value
>::apply(box_in_normalized, mbr);
}
};
}} // namespace detail::envelope
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct box_on_spheroid
{
template <typename BoxOut, typename BoxIn>
static inline void apply(BoxOut& box_out, BoxIn const& box_in)
{
// normalize both boxes and convert box-in to be of type of box-out
BoxOut mbrs[2];
geometry::detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0]);
geometry::detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1]);
// compute the envelope of the two boxes
geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct spherical_box
: detail::box_on_spheroid
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<box_tag, spherical_equatorial_tag, CalculationType>
{
typedef spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, spherical_polar_tag, CalculationType>
{
typedef spherical_box type;
};
template <typename CalculationType>
struct default_strategy<box_tag, geographic_tag, CalculationType>
{
typedef spherical_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_BOX_HPP

View File

@@ -0,0 +1,231 @@
// 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.
// 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 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.
// Distributed under 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_STRATEGY_SPHERICAL_EXPAND_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP
#include <algorithm>
#include <cstddef>
#include <functional>
#include <type_traits>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
#include <boost/geometry/strategy/expand.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// implementation for the spherical and geographic coordinate systems
template <std::size_t DimensionCount, bool IsEquatorial>
struct point_loop_on_spheroid
{
template <typename Box, typename Point>
static inline void apply(Box& box, Point const& point)
{
typedef typename point_type<Box>::type box_point_type;
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename geometry::detail::cs_angular_units<Box>::type units_type;
typedef math::detail::constants_on_spheroid
<
box_coordinate_type,
units_type
> constants;
// normalize input point and input box
Point p_normalized;
strategy::normalize::spherical_point::apply(point, p_normalized);
// transform input point to be of the same type as the box point
box_point_type box_point;
geometry::detail::envelope::transform_units(p_normalized, box_point);
if (is_inverse_spheroidal_coordinates(box))
{
geometry::set_from_radian<min_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
geometry::set_from_radian<min_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
geometry::set_from_radian<max_corner, 0>(box, geometry::get_as_radian<0>(p_normalized));
geometry::set_from_radian<max_corner, 1>(box, geometry::get_as_radian<1>(p_normalized));
} else {
strategy::normalize::spherical_box::apply(box, box);
box_coordinate_type p_lon = geometry::get<0>(box_point);
box_coordinate_type p_lat = geometry::get<1>(box_point);
typename coordinate_type<Box>::type
b_lon_min = geometry::get<min_corner, 0>(box),
b_lat_min = geometry::get<min_corner, 1>(box),
b_lon_max = geometry::get<max_corner, 0>(box),
b_lat_max = geometry::get<max_corner, 1>(box);
if (math::is_latitude_pole<units_type, IsEquatorial>(p_lat))
{
// the point of expansion is the either the north or the
// south pole; the only important coordinate here is the
// pole's latitude, as the longitude can be anything;
// we, thus, take into account the point's latitude only and return
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
return;
}
if (math::equals(b_lat_min, b_lat_max)
&& math::is_latitude_pole<units_type, IsEquatorial>(b_lat_min))
{
// the box degenerates to either the north or the south pole;
// the only important coordinate here is the pole's latitude,
// as the longitude can be anything;
// we thus take into account the box's latitude only and return
geometry::set<min_corner, 0>(box, p_lon);
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
geometry::set<max_corner, 0>(box, p_lon);
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
return;
}
// update latitudes
b_lat_min = (std::min)(b_lat_min, p_lat);
b_lat_max = (std::max)(b_lat_max, p_lat);
// update longitudes
if (math::smaller(p_lon, b_lon_min))
{
box_coordinate_type p_lon_shifted = p_lon + constants::period();
if (math::larger(p_lon_shifted, b_lon_max))
{
// here we could check using: ! math::larger(.., ..)
if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
{
b_lon_min = p_lon;
}
else
{
b_lon_max = p_lon_shifted;
}
}
}
else if (math::larger(p_lon, b_lon_max))
{
// in this case, and since p_lon is normalized in the range
// (-180, 180], we must have that b_lon_max <= 180
if (b_lon_min < 0
&& math::larger(p_lon - b_lon_max,
constants::period() - p_lon + b_lon_min))
{
b_lon_min = p_lon;
b_lon_max += constants::period();
}
else
{
b_lon_max = p_lon;
}
}
geometry::set<min_corner, 0>(box, b_lon_min);
geometry::set<min_corner, 1>(box, b_lat_min);
geometry::set<max_corner, 0>(box, b_lon_max);
geometry::set<max_corner, 1>(box, b_lat_max);
}
point_loop
<
2, DimensionCount
>::apply(box, point);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct spherical_point
{
template <typename Box, typename Point>
static void apply(Box & box, Point const& point)
{
expand::detail::point_loop_on_spheroid
<
dimension<Point>::value,
! std::is_same<typename cs_tag<Point>::type, spherical_polar_tag>::value
>::apply(box, point);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<point_tag, spherical_equatorial_tag, CalculationType>
{
typedef spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, spherical_polar_tag, CalculationType>
{
typedef spherical_point type;
};
template <typename CalculationType>
struct default_strategy<point_tag, geographic_tag, CalculationType>
{
typedef spherical_point type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_POINT_HPP

View File

@@ -0,0 +1,113 @@
// 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.
// 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 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
// Distributed under 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_STRATEGY_SPHERICAL_EXPAND_SEGMENT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_SEGMENT_HPP
#include <cstddef>
#include <functional>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/strategy/expand.hpp>
#include <boost/geometry/strategy/spherical/envelope_box.hpp>
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace expand
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct segment_on_spheroid
{
template <typename Box, typename Segment, typename Strategy>
static inline void apply(Box& box, Segment const& segment, Strategy const& strategy)
{
Box mbrs[2];
// compute the envelope of the segment
geometry::detail::envelope::envelope_segment::apply(segment, mbrs[0], strategy);
// normalize the box
strategy::envelope::spherical_box::apply(box, mbrs[1]);
// compute the envelope of the two boxes
geometry::detail::envelope::envelope_range_of_boxes::apply(mbrs, box);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template
<
typename CalculationType = void
>
class spherical_segment
{
public:
template <typename Box, typename Segment>
static inline void apply(Box& box, Segment const& segment)
{
detail::segment_on_spheroid::apply(box, segment,
strategy::envelope::spherical_segment<CalculationType>());
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<segment_tag, spherical_equatorial_tag, CalculationType>
{
typedef spherical_segment<CalculationType> type;
};
template <typename CalculationType>
struct default_strategy<segment_tag, spherical_polar_tag, CalculationType>
{
typedef spherical_segment<CalculationType> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::expand
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_EXPAND_SEGMENT_HPP